diff --git a/.editorconfig b/.editorconfig
index 140cc085c5..231d35cfe4 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,901 +1,901 @@
-[*]
-charset = utf-8
-end_of_line = lf
-indent_size = 4
-indent_style = space
-insert_final_newline = true
-max_line_length = 160
-tab_width = 4
-ij_continuation_indent_size = 8
-ij_formatter_off_tag = @formatter:off
-ij_formatter_on_tag = @formatter:on
-ij_formatter_tags_enabled = false
-ij_smart_tabs = false
-ij_visual_guides = none
-ij_wrap_on_typing = false
-
-[*.java]
-ij_java_align_consecutive_assignments = false
-ij_java_align_consecutive_variable_declarations = false
-ij_java_align_group_field_declarations = false
-ij_java_align_multiline_annotation_parameters = false
-ij_java_align_multiline_array_initializer_expression = false
-ij_java_align_multiline_assignment = false
-ij_java_align_multiline_binary_operation = false
-ij_java_align_multiline_chained_methods = false
-ij_java_align_multiline_extends_list = false
-ij_java_align_multiline_for = true
-ij_java_align_multiline_method_parentheses = false
-ij_java_align_multiline_parameters = true
-ij_java_align_multiline_parameters_in_calls = false
-ij_java_align_multiline_parenthesized_expression = false
-ij_java_align_multiline_records = true
-ij_java_align_multiline_resources = true
-ij_java_align_multiline_ternary_operation = false
-ij_java_align_multiline_text_blocks = false
-ij_java_align_multiline_throws_list = false
-ij_java_align_subsequent_simple_methods = false
-ij_java_align_throws_keyword = false
-ij_java_annotation_parameter_wrap = off
-ij_java_array_initializer_new_line_after_left_brace = false
-ij_java_array_initializer_right_brace_on_new_line = false
-ij_java_array_initializer_wrap = off
-ij_java_assert_statement_colon_on_next_line = false
-ij_java_assert_statement_wrap = off
-ij_java_assignment_wrap = off
-ij_java_binary_operation_sign_on_next_line = false
-ij_java_binary_operation_wrap = off
-ij_java_blank_lines_after_anonymous_class_header = 0
-ij_java_blank_lines_after_class_header = 0
-ij_java_blank_lines_after_imports = 1
-ij_java_blank_lines_after_package = 1
-ij_java_blank_lines_around_class = 1
-ij_java_blank_lines_around_field = 0
-ij_java_blank_lines_around_field_in_interface = 0
-ij_java_blank_lines_around_initializer = 1
-ij_java_blank_lines_around_method = 1
-ij_java_blank_lines_around_method_in_interface = 1
-ij_java_blank_lines_before_class_end = 0
-ij_java_blank_lines_before_imports = 1
-ij_java_blank_lines_before_method_body = 0
-ij_java_blank_lines_before_package = 0
-ij_java_block_brace_style = end_of_line
-ij_java_block_comment_at_first_column = true
-ij_java_builder_methods = none
-ij_java_call_parameters_new_line_after_left_paren = false
-ij_java_call_parameters_right_paren_on_new_line = false
-ij_java_call_parameters_wrap = off
-ij_java_case_statement_on_separate_line = true
-ij_java_catch_on_new_line = false
-ij_java_class_annotation_wrap = split_into_lines
-ij_java_class_brace_style = end_of_line
-ij_java_class_count_to_use_import_on_demand = 99
-ij_java_class_names_in_javadoc = 1
-ij_java_do_not_indent_top_level_class_members = false
-ij_java_do_not_wrap_after_single_annotation = false
-ij_java_do_while_brace_force = never
-ij_java_doc_add_blank_line_after_description = true
-ij_java_doc_add_blank_line_after_param_comments = false
-ij_java_doc_add_blank_line_after_return = false
-ij_java_doc_add_p_tag_on_empty_lines = true
-ij_java_doc_align_exception_comments = true
-ij_java_doc_align_param_comments = true
-ij_java_doc_do_not_wrap_if_one_line = false
-ij_java_doc_enable_formatting = true
-ij_java_doc_enable_leading_asterisks = true
-ij_java_doc_indent_on_continuation = false
-ij_java_doc_keep_empty_lines = true
-ij_java_doc_keep_empty_parameter_tag = true
-ij_java_doc_keep_empty_return_tag = true
-ij_java_doc_keep_empty_throws_tag = true
-ij_java_doc_keep_invalid_tags = true
-ij_java_doc_param_description_on_new_line = false
-ij_java_doc_preserve_line_breaks = false
-ij_java_doc_use_throws_not_exception_tag = true
-ij_java_else_on_new_line = false
-ij_java_enum_constants_wrap = off
-ij_java_extends_keyword_wrap = off
-ij_java_extends_list_wrap = off
-ij_java_field_annotation_wrap = split_into_lines
-ij_java_finally_on_new_line = false
-ij_java_for_brace_force = never
-ij_java_for_statement_new_line_after_left_paren = false
-ij_java_for_statement_right_paren_on_new_line = false
-ij_java_for_statement_wrap = off
-ij_java_generate_final_locals = false
-ij_java_generate_final_parameters = false
-ij_java_if_brace_force = never
-ij_java_imports_layout = $android.**,$androidx.**,$com.**,$junit.**,$net.**,$org.**,$java.**,$javax.**,$*,|,android.**,|,androidx.**,|,com.**,|,junit.**,|,net.**,|,org.**,|,java.**,|,javax.**,|,*,|
-ij_java_indent_case_from_switch = true
-ij_java_insert_inner_class_imports = false
-ij_java_insert_override_annotation = true
-ij_java_keep_blank_lines_before_right_brace = 2
-ij_java_keep_blank_lines_between_package_declaration_and_header = 2
-ij_java_keep_blank_lines_in_code = 2
-ij_java_keep_blank_lines_in_declarations = 2
-ij_java_keep_builder_methods_indents = false
-ij_java_keep_control_statement_in_one_line = true
-ij_java_keep_first_column_comment = true
-ij_java_keep_indents_on_empty_lines = false
-ij_java_keep_line_breaks = true
-ij_java_keep_multiple_expressions_in_one_line = false
-ij_java_keep_simple_blocks_in_one_line = false
-ij_java_keep_simple_classes_in_one_line = false
-ij_java_keep_simple_lambdas_in_one_line = false
-ij_java_keep_simple_methods_in_one_line = false
-ij_java_label_indent_absolute = false
-ij_java_label_indent_size = 0
-ij_java_lambda_brace_style = end_of_line
-ij_java_layout_static_imports_separately = true
-ij_java_line_comment_add_space = false
-ij_java_line_comment_at_first_column = true
-ij_java_method_annotation_wrap = split_into_lines
-ij_java_method_brace_style = end_of_line
-ij_java_method_call_chain_wrap = off
-ij_java_method_parameters_new_line_after_left_paren = false
-ij_java_method_parameters_right_paren_on_new_line = false
-ij_java_method_parameters_wrap = off
-ij_java_modifier_list_wrap = false
-ij_java_names_count_to_use_import_on_demand = 99
-ij_java_new_line_after_lparen_in_record_header = false
-ij_java_parameter_annotation_wrap = off
-ij_java_parentheses_expression_new_line_after_left_paren = false
-ij_java_parentheses_expression_right_paren_on_new_line = false
-ij_java_place_assignment_sign_on_next_line = false
-ij_java_prefer_longer_names = true
-ij_java_prefer_parameters_wrap = false
-ij_java_record_components_wrap = normal
-ij_java_repeat_synchronized = true
-ij_java_replace_instanceof_and_cast = false
-ij_java_replace_null_check = true
-ij_java_replace_sum_lambda_with_method_ref = true
-ij_java_resource_list_new_line_after_left_paren = false
-ij_java_resource_list_right_paren_on_new_line = false
-ij_java_resource_list_wrap = off
-ij_java_rparen_on_new_line_in_record_header = false
-ij_java_space_after_closing_angle_bracket_in_type_argument = false
-ij_java_space_after_colon = true
-ij_java_space_after_comma = true
-ij_java_space_after_comma_in_type_arguments = true
-ij_java_space_after_for_semicolon = true
-ij_java_space_after_quest = true
-ij_java_space_after_type_cast = true
-ij_java_space_before_annotation_array_initializer_left_brace = false
-ij_java_space_before_annotation_parameter_list = false
-ij_java_space_before_array_initializer_left_brace = false
-ij_java_space_before_catch_keyword = true
-ij_java_space_before_catch_left_brace = true
-ij_java_space_before_catch_parentheses = true
-ij_java_space_before_class_left_brace = true
-ij_java_space_before_colon = true
-ij_java_space_before_colon_in_foreach = true
-ij_java_space_before_comma = false
-ij_java_space_before_do_left_brace = true
-ij_java_space_before_else_keyword = true
-ij_java_space_before_else_left_brace = true
-ij_java_space_before_finally_keyword = true
-ij_java_space_before_finally_left_brace = true
-ij_java_space_before_for_left_brace = true
-ij_java_space_before_for_parentheses = true
-ij_java_space_before_for_semicolon = false
-ij_java_space_before_if_left_brace = true
-ij_java_space_before_if_parentheses = true
-ij_java_space_before_method_call_parentheses = false
-ij_java_space_before_method_left_brace = true
-ij_java_space_before_method_parentheses = false
-ij_java_space_before_opening_angle_bracket_in_type_parameter = false
-ij_java_space_before_quest = true
-ij_java_space_before_switch_left_brace = true
-ij_java_space_before_switch_parentheses = true
-ij_java_space_before_synchronized_left_brace = true
-ij_java_space_before_synchronized_parentheses = true
-ij_java_space_before_try_left_brace = true
-ij_java_space_before_try_parentheses = true
-ij_java_space_before_type_parameter_list = false
-ij_java_space_before_while_keyword = true
-ij_java_space_before_while_left_brace = true
-ij_java_space_before_while_parentheses = true
-ij_java_space_inside_one_line_enum_braces = false
-ij_java_space_within_empty_array_initializer_braces = false
-ij_java_space_within_empty_method_call_parentheses = false
-ij_java_space_within_empty_method_parentheses = false
-ij_java_spaces_around_additive_operators = true
-ij_java_spaces_around_assignment_operators = true
-ij_java_spaces_around_bitwise_operators = true
-ij_java_spaces_around_equality_operators = true
-ij_java_spaces_around_lambda_arrow = true
-ij_java_spaces_around_logical_operators = true
-ij_java_spaces_around_method_ref_dbl_colon = false
-ij_java_spaces_around_multiplicative_operators = true
-ij_java_spaces_around_relational_operators = true
-ij_java_spaces_around_shift_operators = true
-ij_java_spaces_around_type_bounds_in_type_parameters = true
-ij_java_spaces_around_unary_operator = false
-ij_java_spaces_within_angle_brackets = false
-ij_java_spaces_within_annotation_parentheses = false
-ij_java_spaces_within_array_initializer_braces = false
-ij_java_spaces_within_braces = false
-ij_java_spaces_within_brackets = false
-ij_java_spaces_within_cast_parentheses = false
-ij_java_spaces_within_catch_parentheses = false
-ij_java_spaces_within_for_parentheses = false
-ij_java_spaces_within_if_parentheses = false
-ij_java_spaces_within_method_call_parentheses = false
-ij_java_spaces_within_method_parentheses = false
-ij_java_spaces_within_parentheses = false
-ij_java_spaces_within_record_header = false
-ij_java_spaces_within_switch_parentheses = false
-ij_java_spaces_within_synchronized_parentheses = false
-ij_java_spaces_within_try_parentheses = false
-ij_java_spaces_within_while_parentheses = false
-ij_java_special_else_if_treatment = true
-ij_java_subclass_name_suffix = Impl
-ij_java_ternary_operation_signs_on_next_line = false
-ij_java_ternary_operation_wrap = off
-ij_java_test_name_suffix = Test
-ij_java_throws_keyword_wrap = off
-ij_java_throws_list_wrap = off
-ij_java_use_external_annotations = false
-ij_java_use_fq_class_names = false
-ij_java_use_relative_indents = false
-ij_java_use_single_class_imports = true
-ij_java_variable_annotation_wrap = off
-ij_java_visibility = public
-ij_java_while_brace_force = never
-ij_java_while_on_new_line = false
-ij_java_wrap_comments = false
-ij_java_wrap_first_method_in_call_chain = false
-ij_java_wrap_long_lines = false
-
-[*.properties]
-ij_properties_align_group_field_declarations = false
-ij_properties_keep_blank_lines = false
-ij_properties_key_value_delimiter = equals
-ij_properties_spaces_around_key_value_delimiter = false
-
-[.editorconfig]
-ij_editorconfig_align_group_field_declarations = false
-ij_editorconfig_space_after_colon = false
-ij_editorconfig_space_after_comma = true
-ij_editorconfig_space_before_colon = false
-ij_editorconfig_space_before_comma = false
-ij_editorconfig_spaces_around_assignment_operators = true
-
-[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}]
-ij_continuation_indent_size = 4
-ij_xml_align_attributes = false
-ij_xml_align_text = false
-ij_xml_attribute_wrap = normal
-ij_xml_block_comment_at_first_column = true
-ij_xml_keep_blank_lines = 2
-ij_xml_keep_indents_on_empty_lines = false
-ij_xml_keep_line_breaks = false
-ij_xml_keep_line_breaks_in_text = true
-ij_xml_keep_whitespaces = false
-ij_xml_keep_whitespaces_around_cdata = preserve
-ij_xml_keep_whitespaces_inside_cdata = false
-ij_xml_line_comment_at_first_column = true
-ij_xml_space_after_tag_name = false
-ij_xml_space_around_equals_in_attribute = false
-ij_xml_space_inside_empty_tag = true
-ij_xml_text_wrap = normal
-ij_xml_use_custom_settings = true
-
-[{*.bash,*.sh,*.zsh}]
-indent_size = 2
-tab_width = 2
-ij_shell_binary_ops_start_line = false
-ij_shell_keep_column_alignment_padding = false
-ij_shell_minify_program = false
-ij_shell_redirect_followed_by_space = false
-ij_shell_switch_cases_indented = false
-ij_shell_use_unix_line_separator = true
-
-[{*.c,*.c++,*.cc,*.cp,*.cpp,*.cu,*.cuh,*.cxx,*.h,*.h++,*.hh,*.hp,*.hpp,*.hxx,*.i,*.icc,*.ii,*.inl,*.ino,*.ipp,*.m,*.mm,*.pch,*.tcc,*.tpp}]
-ij_c_add_brief_tag = false
-ij_c_add_getter_prefix = true
-ij_c_add_setter_prefix = true
-ij_c_align_dictionary_pair_values = false
-ij_c_align_group_field_declarations = false
-ij_c_align_init_list_in_columns = true
-ij_c_align_multiline_array_initializer_expression = true
-ij_c_align_multiline_assignment = true
-ij_c_align_multiline_binary_operation = true
-ij_c_align_multiline_chained_methods = false
-ij_c_align_multiline_for = true
-ij_c_align_multiline_ternary_operation = true
-ij_c_array_initializer_comma_on_next_line = false
-ij_c_array_initializer_new_line_after_left_brace = false
-ij_c_array_initializer_right_brace_on_new_line = false
-ij_c_array_initializer_wrap = normal
-ij_c_assignment_wrap = off
-ij_c_binary_operation_sign_on_next_line = false
-ij_c_binary_operation_wrap = normal
-ij_c_blank_lines_after_class_header = 0
-ij_c_blank_lines_after_imports = 1
-ij_c_blank_lines_around_class = 1
-ij_c_blank_lines_around_field = 0
-ij_c_blank_lines_around_field_in_interface = 0
-ij_c_blank_lines_around_method = 1
-ij_c_blank_lines_around_method_in_interface = 1
-ij_c_blank_lines_around_namespace = 0
-ij_c_blank_lines_around_properties_in_declaration = 0
-ij_c_blank_lines_around_properties_in_interface = 0
-ij_c_blank_lines_before_imports = 1
-ij_c_blank_lines_before_method_body = 0
-ij_c_block_brace_placement = end_of_line
-ij_c_block_brace_style = end_of_line
-ij_c_block_comment_at_first_column = true
-ij_c_catch_on_new_line = false
-ij_c_class_brace_style = end_of_line
-ij_c_class_constructor_init_list_align_multiline = true
-ij_c_class_constructor_init_list_comma_on_next_line = false
-ij_c_class_constructor_init_list_new_line_after_colon = never
-ij_c_class_constructor_init_list_new_line_before_colon = if_long
-ij_c_class_constructor_init_list_wrap = normal
-ij_c_copy_is_deep = false
-ij_c_create_interface_for_categories = true
-ij_c_declare_generated_methods = true
-ij_c_description_include_member_names = true
-ij_c_discharged_short_ternary_operator = false
-ij_c_do_not_add_breaks = false
-ij_c_do_while_brace_force = never
-ij_c_else_on_new_line = false
-ij_c_enum_constants_comma_on_next_line = false
-ij_c_enum_constants_wrap = on_every_item
-ij_c_for_brace_force = never
-ij_c_for_statement_new_line_after_left_paren = false
-ij_c_for_statement_right_paren_on_new_line = false
-ij_c_for_statement_wrap = off
-ij_c_function_brace_placement = end_of_line
-ij_c_function_call_arguments_align_multiline = true
-ij_c_function_call_arguments_align_multiline_pars = false
-ij_c_function_call_arguments_comma_on_next_line = false
-ij_c_function_call_arguments_new_line_after_lpar = false
-ij_c_function_call_arguments_new_line_before_rpar = false
-ij_c_function_call_arguments_wrap = normal
-ij_c_function_non_top_after_return_type_wrap = normal
-ij_c_function_parameters_align_multiline = true
-ij_c_function_parameters_align_multiline_pars = false
-ij_c_function_parameters_comma_on_next_line = false
-ij_c_function_parameters_new_line_after_lpar = false
-ij_c_function_parameters_new_line_before_rpar = false
-ij_c_function_parameters_wrap = normal
-ij_c_function_top_after_return_type_wrap = normal
-ij_c_generate_additional_eq_operators = true
-ij_c_generate_additional_rel_operators = true
-ij_c_generate_class_constructor = true
-ij_c_generate_comparison_operators_use_std_tie = false
-ij_c_generate_instance_variables_for_properties = ask
-ij_c_generate_operators_as_members = true
-ij_c_header_guard_style_pattern = ${PROJECT_NAME}_${FILE_NAME}_${EXT}
-ij_c_if_brace_force = never
-ij_c_in_line_short_ternary_operator = true
-ij_c_indent_block_comment = true
-ij_c_indent_c_struct_members = 4
-ij_c_indent_case_from_switch = true
-ij_c_indent_class_members = 4
-ij_c_indent_directive_as_code = false
-ij_c_indent_implementation_members = 0
-ij_c_indent_inside_code_block = 4
-ij_c_indent_interface_members = 0
-ij_c_indent_interface_members_except_ivars_block = false
-ij_c_indent_namespace_members = 4
-ij_c_indent_preprocessor_directive = 0
-ij_c_indent_visibility_keywords = 0
-ij_c_insert_override = true
-ij_c_insert_virtual_with_override = false
-ij_c_introduce_auto_vars = false
-ij_c_introduce_const_params = false
-ij_c_introduce_const_vars = false
-ij_c_introduce_generate_property = false
-ij_c_introduce_generate_synthesize = true
-ij_c_introduce_globals_to_header = true
-ij_c_introduce_prop_to_private_category = false
-ij_c_introduce_static_consts = true
-ij_c_introduce_use_ns_types = false
-ij_c_ivars_prefix = _
-ij_c_keep_blank_lines_before_end = 2
-ij_c_keep_blank_lines_before_right_brace = 2
-ij_c_keep_blank_lines_in_code = 2
-ij_c_keep_blank_lines_in_declarations = 2
-ij_c_keep_case_expressions_in_one_line = false
-ij_c_keep_control_statement_in_one_line = true
-ij_c_keep_directive_at_first_column = true
-ij_c_keep_first_column_comment = true
-ij_c_keep_line_breaks = true
-ij_c_keep_nested_namespaces_in_one_line = false
-ij_c_keep_simple_blocks_in_one_line = true
-ij_c_keep_simple_methods_in_one_line = true
-ij_c_keep_structures_in_one_line = false
-ij_c_lambda_capture_list_align_multiline = false
-ij_c_lambda_capture_list_align_multiline_bracket = false
-ij_c_lambda_capture_list_comma_on_next_line = false
-ij_c_lambda_capture_list_new_line_after_lbracket = false
-ij_c_lambda_capture_list_new_line_before_rbracket = false
-ij_c_lambda_capture_list_wrap = off
-ij_c_line_comment_add_space = false
-ij_c_line_comment_at_first_column = true
-ij_c_method_brace_placement = end_of_line
-ij_c_method_call_arguments_align_by_colons = true
-ij_c_method_call_arguments_align_multiline = false
-ij_c_method_call_arguments_special_dictionary_pairs_treatment = true
-ij_c_method_call_arguments_wrap = off
-ij_c_method_call_chain_wrap = off
-ij_c_method_parameters_align_by_colons = true
-ij_c_method_parameters_align_multiline = false
-ij_c_method_parameters_wrap = off
-ij_c_namespace_brace_placement = end_of_line
-ij_c_parentheses_expression_new_line_after_left_paren = false
-ij_c_parentheses_expression_right_paren_on_new_line = false
-ij_c_place_assignment_sign_on_next_line = false
-ij_c_property_nonatomic = true
-ij_c_put_ivars_to_implementation = true
-ij_c_refactor_compatibility_aliases_and_classes = true
-ij_c_refactor_properties_and_ivars = true
-ij_c_release_style = ivar
-ij_c_retain_object_parameters_in_constructor = true
-ij_c_semicolon_after_method_signature = false
-ij_c_shift_operation_align_multiline = true
-ij_c_shift_operation_wrap = normal
-ij_c_show_non_virtual_functions = false
-ij_c_space_after_colon = true
-ij_c_space_after_colon_in_selector = false
-ij_c_space_after_comma = true
-ij_c_space_after_cup_in_blocks = false
-ij_c_space_after_dictionary_literal_colon = true
-ij_c_space_after_for_semicolon = true
-ij_c_space_after_init_list_colon = true
-ij_c_space_after_method_parameter_type_parentheses = false
-ij_c_space_after_method_return_type_parentheses = false
-ij_c_space_after_pointer_in_declaration = false
-ij_c_space_after_quest = true
-ij_c_space_after_reference_in_declaration = false
-ij_c_space_after_reference_in_rvalue = false
-ij_c_space_after_structures_rbrace = true
-ij_c_space_after_superclass_colon = true
-ij_c_space_after_type_cast = true
-ij_c_space_after_visibility_sign_in_method_declaration = true
-ij_c_space_before_autorelease_pool_lbrace = true
-ij_c_space_before_catch_keyword = true
-ij_c_space_before_catch_left_brace = true
-ij_c_space_before_catch_parentheses = true
-ij_c_space_before_category_parentheses = true
-ij_c_space_before_chained_send_message = true
-ij_c_space_before_class_left_brace = true
-ij_c_space_before_colon = true
-ij_c_space_before_comma = false
-ij_c_space_before_dictionary_literal_colon = false
-ij_c_space_before_do_left_brace = true
-ij_c_space_before_else_keyword = true
-ij_c_space_before_else_left_brace = true
-ij_c_space_before_for_left_brace = true
-ij_c_space_before_for_parentheses = true
-ij_c_space_before_for_semicolon = false
-ij_c_space_before_if_left_brace = true
-ij_c_space_before_if_parentheses = true
-ij_c_space_before_init_list = false
-ij_c_space_before_init_list_colon = true
-ij_c_space_before_method_call_parentheses = false
-ij_c_space_before_method_left_brace = true
-ij_c_space_before_method_parentheses = false
-ij_c_space_before_namespace_lbrace = true
-ij_c_space_before_pointer_in_declaration = true
-ij_c_space_before_property_attributes_parentheses = false
-ij_c_space_before_protocols_brackets = true
-ij_c_space_before_quest = true
-ij_c_space_before_reference_in_declaration = true
-ij_c_space_before_superclass_colon = true
-ij_c_space_before_switch_left_brace = true
-ij_c_space_before_switch_parentheses = true
-ij_c_space_before_template_call_lt = false
-ij_c_space_before_template_declaration_lt = false
-ij_c_space_before_try_left_brace = true
-ij_c_space_before_while_keyword = true
-ij_c_space_before_while_left_brace = true
-ij_c_space_before_while_parentheses = true
-ij_c_space_between_adjacent_brackets = false
-ij_c_space_between_operator_and_punctuator = false
-ij_c_space_within_empty_array_initializer_braces = false
-ij_c_spaces_around_additive_operators = true
-ij_c_spaces_around_assignment_operators = true
-ij_c_spaces_around_bitwise_operators = true
-ij_c_spaces_around_equality_operators = true
-ij_c_spaces_around_lambda_arrow = true
-ij_c_spaces_around_logical_operators = true
-ij_c_spaces_around_multiplicative_operators = true
-ij_c_spaces_around_pm_operators = false
-ij_c_spaces_around_relational_operators = true
-ij_c_spaces_around_shift_operators = true
-ij_c_spaces_around_unary_operator = false
-ij_c_spaces_within_array_initializer_braces = false
-ij_c_spaces_within_braces = true
-ij_c_spaces_within_brackets = false
-ij_c_spaces_within_cast_parentheses = false
-ij_c_spaces_within_catch_parentheses = false
-ij_c_spaces_within_category_parentheses = false
-ij_c_spaces_within_empty_braces = false
-ij_c_spaces_within_empty_function_call_parentheses = false
-ij_c_spaces_within_empty_function_declaration_parentheses = false
-ij_c_spaces_within_empty_lambda_capture_list_bracket = false
-ij_c_spaces_within_empty_template_call_ltgt = false
-ij_c_spaces_within_empty_template_declaration_ltgt = false
-ij_c_spaces_within_for_parentheses = false
-ij_c_spaces_within_function_call_parentheses = false
-ij_c_spaces_within_function_declaration_parentheses = false
-ij_c_spaces_within_if_parentheses = false
-ij_c_spaces_within_lambda_capture_list_bracket = false
-ij_c_spaces_within_method_parameter_type_parentheses = false
-ij_c_spaces_within_method_return_type_parentheses = false
-ij_c_spaces_within_parentheses = false
-ij_c_spaces_within_property_attributes_parentheses = false
-ij_c_spaces_within_protocols_brackets = false
-ij_c_spaces_within_send_message_brackets = false
-ij_c_spaces_within_switch_parentheses = false
-ij_c_spaces_within_template_call_ltgt = false
-ij_c_spaces_within_template_declaration_ltgt = false
-ij_c_spaces_within_template_double_gt = true
-ij_c_spaces_within_while_parentheses = false
-ij_c_special_else_if_treatment = true
-ij_c_superclass_list_after_colon = never
-ij_c_superclass_list_align_multiline = true
-ij_c_superclass_list_before_colon = if_long
-ij_c_superclass_list_comma_on_next_line = false
-ij_c_superclass_list_wrap = on_every_item
-ij_c_tag_prefix_of_block_comment = at
-ij_c_tag_prefix_of_line_comment = back_slash
-ij_c_template_call_arguments_align_multiline = false
-ij_c_template_call_arguments_align_multiline_pars = false
-ij_c_template_call_arguments_comma_on_next_line = false
-ij_c_template_call_arguments_new_line_after_lt = false
-ij_c_template_call_arguments_new_line_before_gt = false
-ij_c_template_call_arguments_wrap = off
-ij_c_template_declaration_function_body_indent = false
-ij_c_template_declaration_function_wrap = split_into_lines
-ij_c_template_declaration_struct_body_indent = false
-ij_c_template_declaration_struct_wrap = split_into_lines
-ij_c_template_parameters_align_multiline = false
-ij_c_template_parameters_align_multiline_pars = false
-ij_c_template_parameters_comma_on_next_line = false
-ij_c_template_parameters_new_line_after_lt = false
-ij_c_template_parameters_new_line_before_gt = false
-ij_c_template_parameters_wrap = off
-ij_c_ternary_operation_signs_on_next_line = true
-ij_c_ternary_operation_wrap = normal
-ij_c_type_qualifiers_placement = before
-ij_c_use_modern_casts = true
-ij_c_use_setters_in_constructor = true
-ij_c_while_brace_force = never
-ij_c_while_on_new_line = false
-ij_c_wrap_property_declaration = off
-
-[{*.cmake,CMakeLists.txt}]
-ij_cmake_align_multiline_parameters_in_calls = false
-ij_cmake_force_commands_case = 2
-ij_cmake_keep_blank_lines_in_code = 2
-ij_cmake_space_before_for_parentheses = true
-ij_cmake_space_before_if_parentheses = true
-ij_cmake_space_before_method_call_parentheses = false
-ij_cmake_space_before_method_parentheses = false
-ij_cmake_space_before_while_parentheses = true
-ij_cmake_spaces_within_for_parentheses = false
-ij_cmake_spaces_within_if_parentheses = false
-ij_cmake_spaces_within_method_call_parentheses = false
-ij_cmake_spaces_within_method_parentheses = false
-ij_cmake_spaces_within_while_parentheses = false
-
-[{*.gant,*.gradle,*.groovy,*.gy}]
-ij_groovy_align_group_field_declarations = false
-ij_groovy_align_multiline_array_initializer_expression = false
-ij_groovy_align_multiline_assignment = false
-ij_groovy_align_multiline_binary_operation = false
-ij_groovy_align_multiline_chained_methods = false
-ij_groovy_align_multiline_extends_list = false
-ij_groovy_align_multiline_for = true
-ij_groovy_align_multiline_list_or_map = true
-ij_groovy_align_multiline_method_parentheses = false
-ij_groovy_align_multiline_parameters = true
-ij_groovy_align_multiline_parameters_in_calls = false
-ij_groovy_align_multiline_resources = true
-ij_groovy_align_multiline_ternary_operation = false
-ij_groovy_align_multiline_throws_list = false
-ij_groovy_align_named_args_in_map = true
-ij_groovy_align_throws_keyword = false
-ij_groovy_array_initializer_new_line_after_left_brace = false
-ij_groovy_array_initializer_right_brace_on_new_line = false
-ij_groovy_array_initializer_wrap = off
-ij_groovy_assert_statement_wrap = off
-ij_groovy_assignment_wrap = off
-ij_groovy_binary_operation_wrap = off
-ij_groovy_blank_lines_after_class_header = 0
-ij_groovy_blank_lines_after_imports = 1
-ij_groovy_blank_lines_after_package = 1
-ij_groovy_blank_lines_around_class = 1
-ij_groovy_blank_lines_around_field = 0
-ij_groovy_blank_lines_around_field_in_interface = 0
-ij_groovy_blank_lines_around_method = 1
-ij_groovy_blank_lines_around_method_in_interface = 1
-ij_groovy_blank_lines_before_imports = 1
-ij_groovy_blank_lines_before_method_body = 0
-ij_groovy_blank_lines_before_package = 0
-ij_groovy_block_brace_style = end_of_line
-ij_groovy_block_comment_at_first_column = true
-ij_groovy_call_parameters_new_line_after_left_paren = false
-ij_groovy_call_parameters_right_paren_on_new_line = false
-ij_groovy_call_parameters_wrap = off
-ij_groovy_catch_on_new_line = false
-ij_groovy_class_annotation_wrap = split_into_lines
-ij_groovy_class_brace_style = end_of_line
-ij_groovy_class_count_to_use_import_on_demand = 5
-ij_groovy_do_while_brace_force = never
-ij_groovy_else_on_new_line = false
-ij_groovy_enum_constants_wrap = off
-ij_groovy_extends_keyword_wrap = off
-ij_groovy_extends_list_wrap = off
-ij_groovy_field_annotation_wrap = split_into_lines
-ij_groovy_finally_on_new_line = false
-ij_groovy_for_brace_force = never
-ij_groovy_for_statement_new_line_after_left_paren = false
-ij_groovy_for_statement_right_paren_on_new_line = false
-ij_groovy_for_statement_wrap = off
-ij_groovy_if_brace_force = never
-ij_groovy_import_annotation_wrap = 2
-ij_groovy_imports_layout = *,|,javax.**,java.**,|,$*
-ij_groovy_indent_case_from_switch = true
-ij_groovy_indent_label_blocks = true
-ij_groovy_insert_inner_class_imports = false
-ij_groovy_keep_blank_lines_before_right_brace = 2
-ij_groovy_keep_blank_lines_in_code = 2
-ij_groovy_keep_blank_lines_in_declarations = 2
-ij_groovy_keep_control_statement_in_one_line = true
-ij_groovy_keep_first_column_comment = true
-ij_groovy_keep_indents_on_empty_lines = false
-ij_groovy_keep_line_breaks = true
-ij_groovy_keep_multiple_expressions_in_one_line = false
-ij_groovy_keep_simple_blocks_in_one_line = false
-ij_groovy_keep_simple_classes_in_one_line = true
-ij_groovy_keep_simple_lambdas_in_one_line = true
-ij_groovy_keep_simple_methods_in_one_line = true
-ij_groovy_label_indent_absolute = false
-ij_groovy_label_indent_size = 0
-ij_groovy_lambda_brace_style = end_of_line
-ij_groovy_layout_static_imports_separately = true
-ij_groovy_line_comment_add_space = false
-ij_groovy_line_comment_at_first_column = true
-ij_groovy_method_annotation_wrap = split_into_lines
-ij_groovy_method_brace_style = end_of_line
-ij_groovy_method_call_chain_wrap = off
-ij_groovy_method_parameters_new_line_after_left_paren = false
-ij_groovy_method_parameters_right_paren_on_new_line = false
-ij_groovy_method_parameters_wrap = off
-ij_groovy_modifier_list_wrap = false
-ij_groovy_names_count_to_use_import_on_demand = 3
-ij_groovy_parameter_annotation_wrap = off
-ij_groovy_parentheses_expression_new_line_after_left_paren = false
-ij_groovy_parentheses_expression_right_paren_on_new_line = false
-ij_groovy_prefer_parameters_wrap = false
-ij_groovy_resource_list_new_line_after_left_paren = false
-ij_groovy_resource_list_right_paren_on_new_line = false
-ij_groovy_resource_list_wrap = off
-ij_groovy_space_after_assert_separator = true
-ij_groovy_space_after_colon = true
-ij_groovy_space_after_comma = true
-ij_groovy_space_after_comma_in_type_arguments = true
-ij_groovy_space_after_for_semicolon = true
-ij_groovy_space_after_quest = true
-ij_groovy_space_after_type_cast = true
-ij_groovy_space_before_annotation_parameter_list = false
-ij_groovy_space_before_array_initializer_left_brace = false
-ij_groovy_space_before_assert_separator = false
-ij_groovy_space_before_catch_keyword = true
-ij_groovy_space_before_catch_left_brace = true
-ij_groovy_space_before_catch_parentheses = true
-ij_groovy_space_before_class_left_brace = true
-ij_groovy_space_before_closure_left_brace = true
-ij_groovy_space_before_colon = true
-ij_groovy_space_before_comma = false
-ij_groovy_space_before_do_left_brace = true
-ij_groovy_space_before_else_keyword = true
-ij_groovy_space_before_else_left_brace = true
-ij_groovy_space_before_finally_keyword = true
-ij_groovy_space_before_finally_left_brace = true
-ij_groovy_space_before_for_left_brace = true
-ij_groovy_space_before_for_parentheses = true
-ij_groovy_space_before_for_semicolon = false
-ij_groovy_space_before_if_left_brace = true
-ij_groovy_space_before_if_parentheses = true
-ij_groovy_space_before_method_call_parentheses = false
-ij_groovy_space_before_method_left_brace = true
-ij_groovy_space_before_method_parentheses = false
-ij_groovy_space_before_quest = true
-ij_groovy_space_before_switch_left_brace = true
-ij_groovy_space_before_switch_parentheses = true
-ij_groovy_space_before_synchronized_left_brace = true
-ij_groovy_space_before_synchronized_parentheses = true
-ij_groovy_space_before_try_left_brace = true
-ij_groovy_space_before_try_parentheses = true
-ij_groovy_space_before_while_keyword = true
-ij_groovy_space_before_while_left_brace = true
-ij_groovy_space_before_while_parentheses = true
-ij_groovy_space_in_named_argument = true
-ij_groovy_space_in_named_argument_before_colon = false
-ij_groovy_space_within_empty_array_initializer_braces = false
-ij_groovy_space_within_empty_method_call_parentheses = false
-ij_groovy_spaces_around_additive_operators = true
-ij_groovy_spaces_around_assignment_operators = true
-ij_groovy_spaces_around_bitwise_operators = true
-ij_groovy_spaces_around_equality_operators = true
-ij_groovy_spaces_around_lambda_arrow = true
-ij_groovy_spaces_around_logical_operators = true
-ij_groovy_spaces_around_multiplicative_operators = true
-ij_groovy_spaces_around_regex_operators = true
-ij_groovy_spaces_around_relational_operators = true
-ij_groovy_spaces_around_shift_operators = true
-ij_groovy_spaces_within_annotation_parentheses = false
-ij_groovy_spaces_within_array_initializer_braces = false
-ij_groovy_spaces_within_braces = true
-ij_groovy_spaces_within_brackets = false
-ij_groovy_spaces_within_cast_parentheses = false
-ij_groovy_spaces_within_catch_parentheses = false
-ij_groovy_spaces_within_for_parentheses = false
-ij_groovy_spaces_within_gstring_injection_braces = false
-ij_groovy_spaces_within_if_parentheses = false
-ij_groovy_spaces_within_list_or_map = false
-ij_groovy_spaces_within_method_call_parentheses = false
-ij_groovy_spaces_within_method_parentheses = false
-ij_groovy_spaces_within_parentheses = false
-ij_groovy_spaces_within_switch_parentheses = false
-ij_groovy_spaces_within_synchronized_parentheses = false
-ij_groovy_spaces_within_try_parentheses = false
-ij_groovy_spaces_within_tuple_expression = false
-ij_groovy_spaces_within_while_parentheses = false
-ij_groovy_special_else_if_treatment = true
-ij_groovy_ternary_operation_wrap = off
-ij_groovy_throws_keyword_wrap = off
-ij_groovy_throws_list_wrap = off
-ij_groovy_use_flying_geese_braces = false
-ij_groovy_use_fq_class_names = false
-ij_groovy_use_fq_class_names_in_javadoc = true
-ij_groovy_use_relative_indents = false
-ij_groovy_use_single_class_imports = true
-ij_groovy_variable_annotation_wrap = off
-ij_groovy_while_brace_force = never
-ij_groovy_while_on_new_line = false
-ij_groovy_wrap_long_lines = false
-
-[{*.gradle.kts,*.kt,*.kts,*.main.kts}]
-ij_kotlin_align_in_columns_case_branch = true
-ij_kotlin_align_multiline_binary_operation = false
-ij_kotlin_align_multiline_extends_list = false
-ij_kotlin_align_multiline_method_parentheses = false
-ij_kotlin_align_multiline_parameters = true
-ij_kotlin_align_multiline_parameters_in_calls = false
-ij_kotlin_allow_trailing_comma = false
-ij_kotlin_allow_trailing_comma_on_call_site = false
-ij_kotlin_assignment_wrap = off
-ij_kotlin_blank_lines_after_class_header = 0
-ij_kotlin_blank_lines_around_block_when_branches = 0
-ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1
-ij_kotlin_block_comment_at_first_column = true
-ij_kotlin_call_parameters_new_line_after_left_paren = false
-ij_kotlin_call_parameters_right_paren_on_new_line = false
-ij_kotlin_call_parameters_wrap = off
-ij_kotlin_catch_on_new_line = false
-ij_kotlin_class_annotation_wrap = off
-ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL
-ij_kotlin_continuation_indent_for_chained_calls = true
-ij_kotlin_continuation_indent_for_expression_bodies = true
-ij_kotlin_continuation_indent_in_argument_lists = true
-ij_kotlin_continuation_indent_in_elvis = true
-ij_kotlin_continuation_indent_in_if_conditions = true
-ij_kotlin_continuation_indent_in_parameter_lists = true
-ij_kotlin_continuation_indent_in_supertype_lists = true
-ij_kotlin_else_on_new_line = false
-ij_kotlin_enum_constants_wrap = off
-ij_kotlin_extends_list_wrap = off
-ij_kotlin_field_annotation_wrap = normal
-ij_kotlin_finally_on_new_line = false
-ij_kotlin_if_rparen_on_new_line = false
-ij_kotlin_import_nested_classes = false
-ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^
-ij_kotlin_insert_whitespaces_in_simple_one_line_method = true
-ij_kotlin_keep_blank_lines_before_right_brace = 0
-ij_kotlin_keep_blank_lines_in_code = 1
-ij_kotlin_keep_blank_lines_in_declarations = 1
-ij_kotlin_keep_first_column_comment = true
-ij_kotlin_keep_indents_on_empty_lines = false
-ij_kotlin_keep_line_breaks = true
-ij_kotlin_lbrace_on_next_line = false
-ij_kotlin_line_comment_add_space = false
-ij_kotlin_line_comment_at_first_column = true
-ij_kotlin_method_annotation_wrap = split_into_lines
-ij_kotlin_method_call_chain_wrap = off
-ij_kotlin_method_parameters_new_line_after_left_paren = false
-ij_kotlin_method_parameters_right_paren_on_new_line = false
-ij_kotlin_method_parameters_wrap = off
-ij_kotlin_name_count_to_use_star_import = 2147483647
-ij_kotlin_name_count_to_use_star_import_for_members = 2147483647
-ij_kotlin_packages_to_use_import_on_demand = kotlinx.android.synthetic.**
-ij_kotlin_parameter_annotation_wrap = off
-ij_kotlin_space_after_comma = true
-ij_kotlin_space_after_extend_colon = true
-ij_kotlin_space_after_type_colon = true
-ij_kotlin_space_before_catch_parentheses = true
-ij_kotlin_space_before_comma = false
-ij_kotlin_space_before_extend_colon = true
-ij_kotlin_space_before_for_parentheses = true
-ij_kotlin_space_before_if_parentheses = true
-ij_kotlin_space_before_lambda_arrow = true
-ij_kotlin_space_before_type_colon = false
-ij_kotlin_space_before_when_parentheses = true
-ij_kotlin_space_before_while_parentheses = true
-ij_kotlin_spaces_around_additive_operators = true
-ij_kotlin_spaces_around_assignment_operators = true
-ij_kotlin_spaces_around_equality_operators = true
-ij_kotlin_spaces_around_function_type_arrow = true
-ij_kotlin_spaces_around_logical_operators = true
-ij_kotlin_spaces_around_multiplicative_operators = true
-ij_kotlin_spaces_around_range = false
-ij_kotlin_spaces_around_relational_operators = true
-ij_kotlin_spaces_around_unary_operator = false
-ij_kotlin_spaces_around_when_arrow = true
-ij_kotlin_use_custom_formatting_for_modifiers = true
-ij_kotlin_variable_annotation_wrap = off
-ij_kotlin_while_on_new_line = false
-ij_kotlin_wrap_elvis_expressions = 1
-ij_kotlin_wrap_expression_body_functions = 0
-ij_kotlin_wrap_first_method_in_call_chain = false
-
-[{*.har,*.json}]
-indent_size = 2
-ij_json_keep_blank_lines_in_code = 0
-ij_json_keep_indents_on_empty_lines = false
-ij_json_keep_line_breaks = true
-ij_json_space_after_colon = true
-ij_json_space_after_comma = true
-ij_json_space_before_colon = true
-ij_json_space_before_comma = false
-ij_json_spaces_within_braces = false
-ij_json_spaces_within_brackets = false
-ij_json_wrap_long_lines = false
-
-[{*.htm,*.html,*.sht,*.shtm,*.shtml}]
-ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
-ij_html_align_attributes = true
-ij_html_align_text = false
-ij_html_attribute_wrap = normal
-ij_html_block_comment_at_first_column = true
-ij_html_do_not_align_children_of_min_lines = 0
-ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p
-ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot
-ij_html_enforce_quotes = false
-ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var
-ij_html_keep_blank_lines = 2
-ij_html_keep_indents_on_empty_lines = false
-ij_html_keep_line_breaks = true
-ij_html_keep_line_breaks_in_text = true
-ij_html_keep_whitespaces = false
-ij_html_keep_whitespaces_inside = span,pre,textarea
-ij_html_line_comment_at_first_column = true
-ij_html_new_line_after_last_attribute = never
-ij_html_new_line_before_first_attribute = never
-ij_html_quote_style = double
-ij_html_remove_new_line_before_tags = br
-ij_html_space_after_tag_name = false
-ij_html_space_around_equality_in_attribute = false
-ij_html_space_inside_empty_tag = false
-ij_html_text_wrap = normal
-ij_html_uniform_ident = false
-
-[{*.yaml,*.yml}]
-indent_size = 2
-ij_yaml_align_values_properties = do_not_align
-ij_yaml_autoinsert_sequence_marker = true
-ij_yaml_block_mapping_on_new_line = false
-ij_yaml_indent_sequence_value = true
-ij_yaml_keep_indents_on_empty_lines = false
-ij_yaml_keep_line_breaks = true
-ij_yaml_sequence_on_new_line = false
-ij_yaml_space_before_colon = false
-ij_yaml_spaces_within_braces = true
-ij_yaml_spaces_within_brackets = true
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+max_line_length = 160
+tab_width = 4
+ij_continuation_indent_size = 8
+ij_formatter_off_tag = @formatter:off
+ij_formatter_on_tag = @formatter:on
+ij_formatter_tags_enabled = false
+ij_smart_tabs = false
+ij_visual_guides = none
+ij_wrap_on_typing = false
+
+[*.java]
+ij_java_align_consecutive_assignments = false
+ij_java_align_consecutive_variable_declarations = false
+ij_java_align_group_field_declarations = false
+ij_java_align_multiline_annotation_parameters = false
+ij_java_align_multiline_array_initializer_expression = false
+ij_java_align_multiline_assignment = false
+ij_java_align_multiline_binary_operation = false
+ij_java_align_multiline_chained_methods = false
+ij_java_align_multiline_extends_list = false
+ij_java_align_multiline_for = true
+ij_java_align_multiline_method_parentheses = false
+ij_java_align_multiline_parameters = true
+ij_java_align_multiline_parameters_in_calls = false
+ij_java_align_multiline_parenthesized_expression = false
+ij_java_align_multiline_records = true
+ij_java_align_multiline_resources = true
+ij_java_align_multiline_ternary_operation = false
+ij_java_align_multiline_text_blocks = false
+ij_java_align_multiline_throws_list = false
+ij_java_align_subsequent_simple_methods = false
+ij_java_align_throws_keyword = false
+ij_java_annotation_parameter_wrap = off
+ij_java_array_initializer_new_line_after_left_brace = false
+ij_java_array_initializer_right_brace_on_new_line = false
+ij_java_array_initializer_wrap = off
+ij_java_assert_statement_colon_on_next_line = false
+ij_java_assert_statement_wrap = off
+ij_java_assignment_wrap = off
+ij_java_binary_operation_sign_on_next_line = false
+ij_java_binary_operation_wrap = off
+ij_java_blank_lines_after_anonymous_class_header = 0
+ij_java_blank_lines_after_class_header = 0
+ij_java_blank_lines_after_imports = 1
+ij_java_blank_lines_after_package = 1
+ij_java_blank_lines_around_class = 1
+ij_java_blank_lines_around_field = 0
+ij_java_blank_lines_around_field_in_interface = 0
+ij_java_blank_lines_around_initializer = 1
+ij_java_blank_lines_around_method = 1
+ij_java_blank_lines_around_method_in_interface = 1
+ij_java_blank_lines_before_class_end = 0
+ij_java_blank_lines_before_imports = 1
+ij_java_blank_lines_before_method_body = 0
+ij_java_blank_lines_before_package = 0
+ij_java_block_brace_style = end_of_line
+ij_java_block_comment_at_first_column = true
+ij_java_builder_methods = none
+ij_java_call_parameters_new_line_after_left_paren = false
+ij_java_call_parameters_right_paren_on_new_line = false
+ij_java_call_parameters_wrap = off
+ij_java_case_statement_on_separate_line = true
+ij_java_catch_on_new_line = false
+ij_java_class_annotation_wrap = split_into_lines
+ij_java_class_brace_style = end_of_line
+ij_java_class_count_to_use_import_on_demand = 99
+ij_java_class_names_in_javadoc = 1
+ij_java_do_not_indent_top_level_class_members = false
+ij_java_do_not_wrap_after_single_annotation = false
+ij_java_do_while_brace_force = never
+ij_java_doc_add_blank_line_after_description = true
+ij_java_doc_add_blank_line_after_param_comments = false
+ij_java_doc_add_blank_line_after_return = false
+ij_java_doc_add_p_tag_on_empty_lines = true
+ij_java_doc_align_exception_comments = true
+ij_java_doc_align_param_comments = true
+ij_java_doc_do_not_wrap_if_one_line = false
+ij_java_doc_enable_formatting = true
+ij_java_doc_enable_leading_asterisks = true
+ij_java_doc_indent_on_continuation = false
+ij_java_doc_keep_empty_lines = true
+ij_java_doc_keep_empty_parameter_tag = true
+ij_java_doc_keep_empty_return_tag = true
+ij_java_doc_keep_empty_throws_tag = true
+ij_java_doc_keep_invalid_tags = true
+ij_java_doc_param_description_on_new_line = false
+ij_java_doc_preserve_line_breaks = false
+ij_java_doc_use_throws_not_exception_tag = true
+ij_java_else_on_new_line = false
+ij_java_enum_constants_wrap = off
+ij_java_extends_keyword_wrap = off
+ij_java_extends_list_wrap = off
+ij_java_field_annotation_wrap = split_into_lines
+ij_java_finally_on_new_line = false
+ij_java_for_brace_force = never
+ij_java_for_statement_new_line_after_left_paren = false
+ij_java_for_statement_right_paren_on_new_line = false
+ij_java_for_statement_wrap = off
+ij_java_generate_final_locals = false
+ij_java_generate_final_parameters = false
+ij_java_if_brace_force = never
+ij_java_imports_layout = $android.**,$androidx.**,$com.**,$junit.**,$net.**,$org.**,$java.**,$javax.**,$*,|,android.**,|,androidx.**,|,com.**,|,junit.**,|,net.**,|,org.**,|,java.**,|,javax.**,|,*,|
+ij_java_indent_case_from_switch = true
+ij_java_insert_inner_class_imports = false
+ij_java_insert_override_annotation = true
+ij_java_keep_blank_lines_before_right_brace = 2
+ij_java_keep_blank_lines_between_package_declaration_and_header = 2
+ij_java_keep_blank_lines_in_code = 2
+ij_java_keep_blank_lines_in_declarations = 2
+ij_java_keep_builder_methods_indents = false
+ij_java_keep_control_statement_in_one_line = true
+ij_java_keep_first_column_comment = true
+ij_java_keep_indents_on_empty_lines = false
+ij_java_keep_line_breaks = true
+ij_java_keep_multiple_expressions_in_one_line = false
+ij_java_keep_simple_blocks_in_one_line = false
+ij_java_keep_simple_classes_in_one_line = false
+ij_java_keep_simple_lambdas_in_one_line = false
+ij_java_keep_simple_methods_in_one_line = false
+ij_java_label_indent_absolute = false
+ij_java_label_indent_size = 0
+ij_java_lambda_brace_style = end_of_line
+ij_java_layout_static_imports_separately = true
+ij_java_line_comment_add_space = false
+ij_java_line_comment_at_first_column = true
+ij_java_method_annotation_wrap = split_into_lines
+ij_java_method_brace_style = end_of_line
+ij_java_method_call_chain_wrap = off
+ij_java_method_parameters_new_line_after_left_paren = false
+ij_java_method_parameters_right_paren_on_new_line = false
+ij_java_method_parameters_wrap = off
+ij_java_modifier_list_wrap = false
+ij_java_names_count_to_use_import_on_demand = 99
+ij_java_new_line_after_lparen_in_record_header = false
+ij_java_parameter_annotation_wrap = off
+ij_java_parentheses_expression_new_line_after_left_paren = false
+ij_java_parentheses_expression_right_paren_on_new_line = false
+ij_java_place_assignment_sign_on_next_line = false
+ij_java_prefer_longer_names = true
+ij_java_prefer_parameters_wrap = false
+ij_java_record_components_wrap = normal
+ij_java_repeat_synchronized = true
+ij_java_replace_instanceof_and_cast = false
+ij_java_replace_null_check = true
+ij_java_replace_sum_lambda_with_method_ref = true
+ij_java_resource_list_new_line_after_left_paren = false
+ij_java_resource_list_right_paren_on_new_line = false
+ij_java_resource_list_wrap = off
+ij_java_rparen_on_new_line_in_record_header = false
+ij_java_space_after_closing_angle_bracket_in_type_argument = false
+ij_java_space_after_colon = true
+ij_java_space_after_comma = true
+ij_java_space_after_comma_in_type_arguments = true
+ij_java_space_after_for_semicolon = true
+ij_java_space_after_quest = true
+ij_java_space_after_type_cast = true
+ij_java_space_before_annotation_array_initializer_left_brace = false
+ij_java_space_before_annotation_parameter_list = false
+ij_java_space_before_array_initializer_left_brace = false
+ij_java_space_before_catch_keyword = true
+ij_java_space_before_catch_left_brace = true
+ij_java_space_before_catch_parentheses = true
+ij_java_space_before_class_left_brace = true
+ij_java_space_before_colon = true
+ij_java_space_before_colon_in_foreach = true
+ij_java_space_before_comma = false
+ij_java_space_before_do_left_brace = true
+ij_java_space_before_else_keyword = true
+ij_java_space_before_else_left_brace = true
+ij_java_space_before_finally_keyword = true
+ij_java_space_before_finally_left_brace = true
+ij_java_space_before_for_left_brace = true
+ij_java_space_before_for_parentheses = true
+ij_java_space_before_for_semicolon = false
+ij_java_space_before_if_left_brace = true
+ij_java_space_before_if_parentheses = true
+ij_java_space_before_method_call_parentheses = false
+ij_java_space_before_method_left_brace = true
+ij_java_space_before_method_parentheses = false
+ij_java_space_before_opening_angle_bracket_in_type_parameter = false
+ij_java_space_before_quest = true
+ij_java_space_before_switch_left_brace = true
+ij_java_space_before_switch_parentheses = true
+ij_java_space_before_synchronized_left_brace = true
+ij_java_space_before_synchronized_parentheses = true
+ij_java_space_before_try_left_brace = true
+ij_java_space_before_try_parentheses = true
+ij_java_space_before_type_parameter_list = false
+ij_java_space_before_while_keyword = true
+ij_java_space_before_while_left_brace = true
+ij_java_space_before_while_parentheses = true
+ij_java_space_inside_one_line_enum_braces = false
+ij_java_space_within_empty_array_initializer_braces = false
+ij_java_space_within_empty_method_call_parentheses = false
+ij_java_space_within_empty_method_parentheses = false
+ij_java_spaces_around_additive_operators = true
+ij_java_spaces_around_assignment_operators = true
+ij_java_spaces_around_bitwise_operators = true
+ij_java_spaces_around_equality_operators = true
+ij_java_spaces_around_lambda_arrow = true
+ij_java_spaces_around_logical_operators = true
+ij_java_spaces_around_method_ref_dbl_colon = false
+ij_java_spaces_around_multiplicative_operators = true
+ij_java_spaces_around_relational_operators = true
+ij_java_spaces_around_shift_operators = true
+ij_java_spaces_around_type_bounds_in_type_parameters = true
+ij_java_spaces_around_unary_operator = false
+ij_java_spaces_within_angle_brackets = false
+ij_java_spaces_within_annotation_parentheses = false
+ij_java_spaces_within_array_initializer_braces = false
+ij_java_spaces_within_braces = false
+ij_java_spaces_within_brackets = false
+ij_java_spaces_within_cast_parentheses = false
+ij_java_spaces_within_catch_parentheses = false
+ij_java_spaces_within_for_parentheses = false
+ij_java_spaces_within_if_parentheses = false
+ij_java_spaces_within_method_call_parentheses = false
+ij_java_spaces_within_method_parentheses = false
+ij_java_spaces_within_parentheses = false
+ij_java_spaces_within_record_header = false
+ij_java_spaces_within_switch_parentheses = false
+ij_java_spaces_within_synchronized_parentheses = false
+ij_java_spaces_within_try_parentheses = false
+ij_java_spaces_within_while_parentheses = false
+ij_java_special_else_if_treatment = true
+ij_java_subclass_name_suffix = Impl
+ij_java_ternary_operation_signs_on_next_line = false
+ij_java_ternary_operation_wrap = off
+ij_java_test_name_suffix = Test
+ij_java_throws_keyword_wrap = off
+ij_java_throws_list_wrap = off
+ij_java_use_external_annotations = false
+ij_java_use_fq_class_names = false
+ij_java_use_relative_indents = false
+ij_java_use_single_class_imports = true
+ij_java_variable_annotation_wrap = off
+ij_java_visibility = public
+ij_java_while_brace_force = never
+ij_java_while_on_new_line = false
+ij_java_wrap_comments = false
+ij_java_wrap_first_method_in_call_chain = false
+ij_java_wrap_long_lines = false
+
+[*.properties]
+ij_properties_align_group_field_declarations = false
+ij_properties_keep_blank_lines = false
+ij_properties_key_value_delimiter = equals
+ij_properties_spaces_around_key_value_delimiter = false
+
+[.editorconfig]
+ij_editorconfig_align_group_field_declarations = false
+ij_editorconfig_space_after_colon = false
+ij_editorconfig_space_after_comma = true
+ij_editorconfig_space_before_colon = false
+ij_editorconfig_space_before_comma = false
+ij_editorconfig_spaces_around_assignment_operators = true
+
+[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}]
+ij_continuation_indent_size = 4
+ij_xml_align_attributes = false
+ij_xml_align_text = false
+ij_xml_attribute_wrap = normal
+ij_xml_block_comment_at_first_column = true
+ij_xml_keep_blank_lines = 2
+ij_xml_keep_indents_on_empty_lines = false
+ij_xml_keep_line_breaks = false
+ij_xml_keep_line_breaks_in_text = true
+ij_xml_keep_whitespaces = false
+ij_xml_keep_whitespaces_around_cdata = preserve
+ij_xml_keep_whitespaces_inside_cdata = false
+ij_xml_line_comment_at_first_column = true
+ij_xml_space_after_tag_name = false
+ij_xml_space_around_equals_in_attribute = false
+ij_xml_space_inside_empty_tag = true
+ij_xml_text_wrap = normal
+ij_xml_use_custom_settings = true
+
+[{*.bash,*.sh,*.zsh}]
+indent_size = 2
+tab_width = 2
+ij_shell_binary_ops_start_line = false
+ij_shell_keep_column_alignment_padding = false
+ij_shell_minify_program = false
+ij_shell_redirect_followed_by_space = false
+ij_shell_switch_cases_indented = false
+ij_shell_use_unix_line_separator = true
+
+[{*.c,*.c++,*.cc,*.cp,*.cpp,*.cu,*.cuh,*.cxx,*.h,*.h++,*.hh,*.hp,*.hpp,*.hxx,*.i,*.icc,*.ii,*.inl,*.ino,*.ipp,*.m,*.mm,*.pch,*.tcc,*.tpp}]
+ij_c_add_brief_tag = false
+ij_c_add_getter_prefix = true
+ij_c_add_setter_prefix = true
+ij_c_align_dictionary_pair_values = false
+ij_c_align_group_field_declarations = false
+ij_c_align_init_list_in_columns = true
+ij_c_align_multiline_array_initializer_expression = true
+ij_c_align_multiline_assignment = true
+ij_c_align_multiline_binary_operation = true
+ij_c_align_multiline_chained_methods = false
+ij_c_align_multiline_for = true
+ij_c_align_multiline_ternary_operation = true
+ij_c_array_initializer_comma_on_next_line = false
+ij_c_array_initializer_new_line_after_left_brace = false
+ij_c_array_initializer_right_brace_on_new_line = false
+ij_c_array_initializer_wrap = normal
+ij_c_assignment_wrap = off
+ij_c_binary_operation_sign_on_next_line = false
+ij_c_binary_operation_wrap = normal
+ij_c_blank_lines_after_class_header = 0
+ij_c_blank_lines_after_imports = 1
+ij_c_blank_lines_around_class = 1
+ij_c_blank_lines_around_field = 0
+ij_c_blank_lines_around_field_in_interface = 0
+ij_c_blank_lines_around_method = 1
+ij_c_blank_lines_around_method_in_interface = 1
+ij_c_blank_lines_around_namespace = 0
+ij_c_blank_lines_around_properties_in_declaration = 0
+ij_c_blank_lines_around_properties_in_interface = 0
+ij_c_blank_lines_before_imports = 1
+ij_c_blank_lines_before_method_body = 0
+ij_c_block_brace_placement = end_of_line
+ij_c_block_brace_style = end_of_line
+ij_c_block_comment_at_first_column = true
+ij_c_catch_on_new_line = false
+ij_c_class_brace_style = end_of_line
+ij_c_class_constructor_init_list_align_multiline = true
+ij_c_class_constructor_init_list_comma_on_next_line = false
+ij_c_class_constructor_init_list_new_line_after_colon = never
+ij_c_class_constructor_init_list_new_line_before_colon = if_long
+ij_c_class_constructor_init_list_wrap = normal
+ij_c_copy_is_deep = false
+ij_c_create_interface_for_categories = true
+ij_c_declare_generated_methods = true
+ij_c_description_include_member_names = true
+ij_c_discharged_short_ternary_operator = false
+ij_c_do_not_add_breaks = false
+ij_c_do_while_brace_force = never
+ij_c_else_on_new_line = false
+ij_c_enum_constants_comma_on_next_line = false
+ij_c_enum_constants_wrap = on_every_item
+ij_c_for_brace_force = never
+ij_c_for_statement_new_line_after_left_paren = false
+ij_c_for_statement_right_paren_on_new_line = false
+ij_c_for_statement_wrap = off
+ij_c_function_brace_placement = end_of_line
+ij_c_function_call_arguments_align_multiline = true
+ij_c_function_call_arguments_align_multiline_pars = false
+ij_c_function_call_arguments_comma_on_next_line = false
+ij_c_function_call_arguments_new_line_after_lpar = false
+ij_c_function_call_arguments_new_line_before_rpar = false
+ij_c_function_call_arguments_wrap = normal
+ij_c_function_non_top_after_return_type_wrap = normal
+ij_c_function_parameters_align_multiline = true
+ij_c_function_parameters_align_multiline_pars = false
+ij_c_function_parameters_comma_on_next_line = false
+ij_c_function_parameters_new_line_after_lpar = false
+ij_c_function_parameters_new_line_before_rpar = false
+ij_c_function_parameters_wrap = normal
+ij_c_function_top_after_return_type_wrap = normal
+ij_c_generate_additional_eq_operators = true
+ij_c_generate_additional_rel_operators = true
+ij_c_generate_class_constructor = true
+ij_c_generate_comparison_operators_use_std_tie = false
+ij_c_generate_instance_variables_for_properties = ask
+ij_c_generate_operators_as_members = true
+ij_c_header_guard_style_pattern = ${PROJECT_NAME}_${FILE_NAME}_${EXT}
+ij_c_if_brace_force = never
+ij_c_in_line_short_ternary_operator = true
+ij_c_indent_block_comment = true
+ij_c_indent_c_struct_members = 4
+ij_c_indent_case_from_switch = true
+ij_c_indent_class_members = 4
+ij_c_indent_directive_as_code = false
+ij_c_indent_implementation_members = 0
+ij_c_indent_inside_code_block = 4
+ij_c_indent_interface_members = 0
+ij_c_indent_interface_members_except_ivars_block = false
+ij_c_indent_namespace_members = 4
+ij_c_indent_preprocessor_directive = 0
+ij_c_indent_visibility_keywords = 0
+ij_c_insert_override = true
+ij_c_insert_virtual_with_override = false
+ij_c_introduce_auto_vars = false
+ij_c_introduce_const_params = false
+ij_c_introduce_const_vars = false
+ij_c_introduce_generate_property = false
+ij_c_introduce_generate_synthesize = true
+ij_c_introduce_globals_to_header = true
+ij_c_introduce_prop_to_private_category = false
+ij_c_introduce_static_consts = true
+ij_c_introduce_use_ns_types = false
+ij_c_ivars_prefix = _
+ij_c_keep_blank_lines_before_end = 2
+ij_c_keep_blank_lines_before_right_brace = 2
+ij_c_keep_blank_lines_in_code = 2
+ij_c_keep_blank_lines_in_declarations = 2
+ij_c_keep_case_expressions_in_one_line = false
+ij_c_keep_control_statement_in_one_line = true
+ij_c_keep_directive_at_first_column = true
+ij_c_keep_first_column_comment = true
+ij_c_keep_line_breaks = true
+ij_c_keep_nested_namespaces_in_one_line = false
+ij_c_keep_simple_blocks_in_one_line = true
+ij_c_keep_simple_methods_in_one_line = true
+ij_c_keep_structures_in_one_line = false
+ij_c_lambda_capture_list_align_multiline = false
+ij_c_lambda_capture_list_align_multiline_bracket = false
+ij_c_lambda_capture_list_comma_on_next_line = false
+ij_c_lambda_capture_list_new_line_after_lbracket = false
+ij_c_lambda_capture_list_new_line_before_rbracket = false
+ij_c_lambda_capture_list_wrap = off
+ij_c_line_comment_add_space = false
+ij_c_line_comment_at_first_column = true
+ij_c_method_brace_placement = end_of_line
+ij_c_method_call_arguments_align_by_colons = true
+ij_c_method_call_arguments_align_multiline = false
+ij_c_method_call_arguments_special_dictionary_pairs_treatment = true
+ij_c_method_call_arguments_wrap = off
+ij_c_method_call_chain_wrap = off
+ij_c_method_parameters_align_by_colons = true
+ij_c_method_parameters_align_multiline = false
+ij_c_method_parameters_wrap = off
+ij_c_namespace_brace_placement = end_of_line
+ij_c_parentheses_expression_new_line_after_left_paren = false
+ij_c_parentheses_expression_right_paren_on_new_line = false
+ij_c_place_assignment_sign_on_next_line = false
+ij_c_property_nonatomic = true
+ij_c_put_ivars_to_implementation = true
+ij_c_refactor_compatibility_aliases_and_classes = true
+ij_c_refactor_properties_and_ivars = true
+ij_c_release_style = ivar
+ij_c_retain_object_parameters_in_constructor = true
+ij_c_semicolon_after_method_signature = false
+ij_c_shift_operation_align_multiline = true
+ij_c_shift_operation_wrap = normal
+ij_c_show_non_virtual_functions = false
+ij_c_space_after_colon = true
+ij_c_space_after_colon_in_selector = false
+ij_c_space_after_comma = true
+ij_c_space_after_cup_in_blocks = false
+ij_c_space_after_dictionary_literal_colon = true
+ij_c_space_after_for_semicolon = true
+ij_c_space_after_init_list_colon = true
+ij_c_space_after_method_parameter_type_parentheses = false
+ij_c_space_after_method_return_type_parentheses = false
+ij_c_space_after_pointer_in_declaration = false
+ij_c_space_after_quest = true
+ij_c_space_after_reference_in_declaration = false
+ij_c_space_after_reference_in_rvalue = false
+ij_c_space_after_structures_rbrace = true
+ij_c_space_after_superclass_colon = true
+ij_c_space_after_type_cast = true
+ij_c_space_after_visibility_sign_in_method_declaration = true
+ij_c_space_before_autorelease_pool_lbrace = true
+ij_c_space_before_catch_keyword = true
+ij_c_space_before_catch_left_brace = true
+ij_c_space_before_catch_parentheses = true
+ij_c_space_before_category_parentheses = true
+ij_c_space_before_chained_send_message = true
+ij_c_space_before_class_left_brace = true
+ij_c_space_before_colon = true
+ij_c_space_before_comma = false
+ij_c_space_before_dictionary_literal_colon = false
+ij_c_space_before_do_left_brace = true
+ij_c_space_before_else_keyword = true
+ij_c_space_before_else_left_brace = true
+ij_c_space_before_for_left_brace = true
+ij_c_space_before_for_parentheses = true
+ij_c_space_before_for_semicolon = false
+ij_c_space_before_if_left_brace = true
+ij_c_space_before_if_parentheses = true
+ij_c_space_before_init_list = false
+ij_c_space_before_init_list_colon = true
+ij_c_space_before_method_call_parentheses = false
+ij_c_space_before_method_left_brace = true
+ij_c_space_before_method_parentheses = false
+ij_c_space_before_namespace_lbrace = true
+ij_c_space_before_pointer_in_declaration = true
+ij_c_space_before_property_attributes_parentheses = false
+ij_c_space_before_protocols_brackets = true
+ij_c_space_before_quest = true
+ij_c_space_before_reference_in_declaration = true
+ij_c_space_before_superclass_colon = true
+ij_c_space_before_switch_left_brace = true
+ij_c_space_before_switch_parentheses = true
+ij_c_space_before_template_call_lt = false
+ij_c_space_before_template_declaration_lt = false
+ij_c_space_before_try_left_brace = true
+ij_c_space_before_while_keyword = true
+ij_c_space_before_while_left_brace = true
+ij_c_space_before_while_parentheses = true
+ij_c_space_between_adjacent_brackets = false
+ij_c_space_between_operator_and_punctuator = false
+ij_c_space_within_empty_array_initializer_braces = false
+ij_c_spaces_around_additive_operators = true
+ij_c_spaces_around_assignment_operators = true
+ij_c_spaces_around_bitwise_operators = true
+ij_c_spaces_around_equality_operators = true
+ij_c_spaces_around_lambda_arrow = true
+ij_c_spaces_around_logical_operators = true
+ij_c_spaces_around_multiplicative_operators = true
+ij_c_spaces_around_pm_operators = false
+ij_c_spaces_around_relational_operators = true
+ij_c_spaces_around_shift_operators = true
+ij_c_spaces_around_unary_operator = false
+ij_c_spaces_within_array_initializer_braces = false
+ij_c_spaces_within_braces = true
+ij_c_spaces_within_brackets = false
+ij_c_spaces_within_cast_parentheses = false
+ij_c_spaces_within_catch_parentheses = false
+ij_c_spaces_within_category_parentheses = false
+ij_c_spaces_within_empty_braces = false
+ij_c_spaces_within_empty_function_call_parentheses = false
+ij_c_spaces_within_empty_function_declaration_parentheses = false
+ij_c_spaces_within_empty_lambda_capture_list_bracket = false
+ij_c_spaces_within_empty_template_call_ltgt = false
+ij_c_spaces_within_empty_template_declaration_ltgt = false
+ij_c_spaces_within_for_parentheses = false
+ij_c_spaces_within_function_call_parentheses = false
+ij_c_spaces_within_function_declaration_parentheses = false
+ij_c_spaces_within_if_parentheses = false
+ij_c_spaces_within_lambda_capture_list_bracket = false
+ij_c_spaces_within_method_parameter_type_parentheses = false
+ij_c_spaces_within_method_return_type_parentheses = false
+ij_c_spaces_within_parentheses = false
+ij_c_spaces_within_property_attributes_parentheses = false
+ij_c_spaces_within_protocols_brackets = false
+ij_c_spaces_within_send_message_brackets = false
+ij_c_spaces_within_switch_parentheses = false
+ij_c_spaces_within_template_call_ltgt = false
+ij_c_spaces_within_template_declaration_ltgt = false
+ij_c_spaces_within_template_double_gt = true
+ij_c_spaces_within_while_parentheses = false
+ij_c_special_else_if_treatment = true
+ij_c_superclass_list_after_colon = never
+ij_c_superclass_list_align_multiline = true
+ij_c_superclass_list_before_colon = if_long
+ij_c_superclass_list_comma_on_next_line = false
+ij_c_superclass_list_wrap = on_every_item
+ij_c_tag_prefix_of_block_comment = at
+ij_c_tag_prefix_of_line_comment = back_slash
+ij_c_template_call_arguments_align_multiline = false
+ij_c_template_call_arguments_align_multiline_pars = false
+ij_c_template_call_arguments_comma_on_next_line = false
+ij_c_template_call_arguments_new_line_after_lt = false
+ij_c_template_call_arguments_new_line_before_gt = false
+ij_c_template_call_arguments_wrap = off
+ij_c_template_declaration_function_body_indent = false
+ij_c_template_declaration_function_wrap = split_into_lines
+ij_c_template_declaration_struct_body_indent = false
+ij_c_template_declaration_struct_wrap = split_into_lines
+ij_c_template_parameters_align_multiline = false
+ij_c_template_parameters_align_multiline_pars = false
+ij_c_template_parameters_comma_on_next_line = false
+ij_c_template_parameters_new_line_after_lt = false
+ij_c_template_parameters_new_line_before_gt = false
+ij_c_template_parameters_wrap = off
+ij_c_ternary_operation_signs_on_next_line = true
+ij_c_ternary_operation_wrap = normal
+ij_c_type_qualifiers_placement = before
+ij_c_use_modern_casts = true
+ij_c_use_setters_in_constructor = true
+ij_c_while_brace_force = never
+ij_c_while_on_new_line = false
+ij_c_wrap_property_declaration = off
+
+[{*.cmake,CMakeLists.txt}]
+ij_cmake_align_multiline_parameters_in_calls = false
+ij_cmake_force_commands_case = 2
+ij_cmake_keep_blank_lines_in_code = 2
+ij_cmake_space_before_for_parentheses = true
+ij_cmake_space_before_if_parentheses = true
+ij_cmake_space_before_method_call_parentheses = false
+ij_cmake_space_before_method_parentheses = false
+ij_cmake_space_before_while_parentheses = true
+ij_cmake_spaces_within_for_parentheses = false
+ij_cmake_spaces_within_if_parentheses = false
+ij_cmake_spaces_within_method_call_parentheses = false
+ij_cmake_spaces_within_method_parentheses = false
+ij_cmake_spaces_within_while_parentheses = false
+
+[{*.gant,*.gradle,*.groovy,*.gy}]
+ij_groovy_align_group_field_declarations = false
+ij_groovy_align_multiline_array_initializer_expression = false
+ij_groovy_align_multiline_assignment = false
+ij_groovy_align_multiline_binary_operation = false
+ij_groovy_align_multiline_chained_methods = false
+ij_groovy_align_multiline_extends_list = false
+ij_groovy_align_multiline_for = true
+ij_groovy_align_multiline_list_or_map = true
+ij_groovy_align_multiline_method_parentheses = false
+ij_groovy_align_multiline_parameters = true
+ij_groovy_align_multiline_parameters_in_calls = false
+ij_groovy_align_multiline_resources = true
+ij_groovy_align_multiline_ternary_operation = false
+ij_groovy_align_multiline_throws_list = false
+ij_groovy_align_named_args_in_map = true
+ij_groovy_align_throws_keyword = false
+ij_groovy_array_initializer_new_line_after_left_brace = false
+ij_groovy_array_initializer_right_brace_on_new_line = false
+ij_groovy_array_initializer_wrap = off
+ij_groovy_assert_statement_wrap = off
+ij_groovy_assignment_wrap = off
+ij_groovy_binary_operation_wrap = off
+ij_groovy_blank_lines_after_class_header = 0
+ij_groovy_blank_lines_after_imports = 1
+ij_groovy_blank_lines_after_package = 1
+ij_groovy_blank_lines_around_class = 1
+ij_groovy_blank_lines_around_field = 0
+ij_groovy_blank_lines_around_field_in_interface = 0
+ij_groovy_blank_lines_around_method = 1
+ij_groovy_blank_lines_around_method_in_interface = 1
+ij_groovy_blank_lines_before_imports = 1
+ij_groovy_blank_lines_before_method_body = 0
+ij_groovy_blank_lines_before_package = 0
+ij_groovy_block_brace_style = end_of_line
+ij_groovy_block_comment_at_first_column = true
+ij_groovy_call_parameters_new_line_after_left_paren = false
+ij_groovy_call_parameters_right_paren_on_new_line = false
+ij_groovy_call_parameters_wrap = off
+ij_groovy_catch_on_new_line = false
+ij_groovy_class_annotation_wrap = split_into_lines
+ij_groovy_class_brace_style = end_of_line
+ij_groovy_class_count_to_use_import_on_demand = 5
+ij_groovy_do_while_brace_force = never
+ij_groovy_else_on_new_line = false
+ij_groovy_enum_constants_wrap = off
+ij_groovy_extends_keyword_wrap = off
+ij_groovy_extends_list_wrap = off
+ij_groovy_field_annotation_wrap = split_into_lines
+ij_groovy_finally_on_new_line = false
+ij_groovy_for_brace_force = never
+ij_groovy_for_statement_new_line_after_left_paren = false
+ij_groovy_for_statement_right_paren_on_new_line = false
+ij_groovy_for_statement_wrap = off
+ij_groovy_if_brace_force = never
+ij_groovy_import_annotation_wrap = 2
+ij_groovy_imports_layout = *,|,javax.**,java.**,|,$*
+ij_groovy_indent_case_from_switch = true
+ij_groovy_indent_label_blocks = true
+ij_groovy_insert_inner_class_imports = false
+ij_groovy_keep_blank_lines_before_right_brace = 2
+ij_groovy_keep_blank_lines_in_code = 2
+ij_groovy_keep_blank_lines_in_declarations = 2
+ij_groovy_keep_control_statement_in_one_line = true
+ij_groovy_keep_first_column_comment = true
+ij_groovy_keep_indents_on_empty_lines = false
+ij_groovy_keep_line_breaks = true
+ij_groovy_keep_multiple_expressions_in_one_line = false
+ij_groovy_keep_simple_blocks_in_one_line = false
+ij_groovy_keep_simple_classes_in_one_line = true
+ij_groovy_keep_simple_lambdas_in_one_line = true
+ij_groovy_keep_simple_methods_in_one_line = true
+ij_groovy_label_indent_absolute = false
+ij_groovy_label_indent_size = 0
+ij_groovy_lambda_brace_style = end_of_line
+ij_groovy_layout_static_imports_separately = true
+ij_groovy_line_comment_add_space = false
+ij_groovy_line_comment_at_first_column = true
+ij_groovy_method_annotation_wrap = split_into_lines
+ij_groovy_method_brace_style = end_of_line
+ij_groovy_method_call_chain_wrap = off
+ij_groovy_method_parameters_new_line_after_left_paren = false
+ij_groovy_method_parameters_right_paren_on_new_line = false
+ij_groovy_method_parameters_wrap = off
+ij_groovy_modifier_list_wrap = false
+ij_groovy_names_count_to_use_import_on_demand = 3
+ij_groovy_parameter_annotation_wrap = off
+ij_groovy_parentheses_expression_new_line_after_left_paren = false
+ij_groovy_parentheses_expression_right_paren_on_new_line = false
+ij_groovy_prefer_parameters_wrap = false
+ij_groovy_resource_list_new_line_after_left_paren = false
+ij_groovy_resource_list_right_paren_on_new_line = false
+ij_groovy_resource_list_wrap = off
+ij_groovy_space_after_assert_separator = true
+ij_groovy_space_after_colon = true
+ij_groovy_space_after_comma = true
+ij_groovy_space_after_comma_in_type_arguments = true
+ij_groovy_space_after_for_semicolon = true
+ij_groovy_space_after_quest = true
+ij_groovy_space_after_type_cast = true
+ij_groovy_space_before_annotation_parameter_list = false
+ij_groovy_space_before_array_initializer_left_brace = false
+ij_groovy_space_before_assert_separator = false
+ij_groovy_space_before_catch_keyword = true
+ij_groovy_space_before_catch_left_brace = true
+ij_groovy_space_before_catch_parentheses = true
+ij_groovy_space_before_class_left_brace = true
+ij_groovy_space_before_closure_left_brace = true
+ij_groovy_space_before_colon = true
+ij_groovy_space_before_comma = false
+ij_groovy_space_before_do_left_brace = true
+ij_groovy_space_before_else_keyword = true
+ij_groovy_space_before_else_left_brace = true
+ij_groovy_space_before_finally_keyword = true
+ij_groovy_space_before_finally_left_brace = true
+ij_groovy_space_before_for_left_brace = true
+ij_groovy_space_before_for_parentheses = true
+ij_groovy_space_before_for_semicolon = false
+ij_groovy_space_before_if_left_brace = true
+ij_groovy_space_before_if_parentheses = true
+ij_groovy_space_before_method_call_parentheses = false
+ij_groovy_space_before_method_left_brace = true
+ij_groovy_space_before_method_parentheses = false
+ij_groovy_space_before_quest = true
+ij_groovy_space_before_switch_left_brace = true
+ij_groovy_space_before_switch_parentheses = true
+ij_groovy_space_before_synchronized_left_brace = true
+ij_groovy_space_before_synchronized_parentheses = true
+ij_groovy_space_before_try_left_brace = true
+ij_groovy_space_before_try_parentheses = true
+ij_groovy_space_before_while_keyword = true
+ij_groovy_space_before_while_left_brace = true
+ij_groovy_space_before_while_parentheses = true
+ij_groovy_space_in_named_argument = true
+ij_groovy_space_in_named_argument_before_colon = false
+ij_groovy_space_within_empty_array_initializer_braces = false
+ij_groovy_space_within_empty_method_call_parentheses = false
+ij_groovy_spaces_around_additive_operators = true
+ij_groovy_spaces_around_assignment_operators = true
+ij_groovy_spaces_around_bitwise_operators = true
+ij_groovy_spaces_around_equality_operators = true
+ij_groovy_spaces_around_lambda_arrow = true
+ij_groovy_spaces_around_logical_operators = true
+ij_groovy_spaces_around_multiplicative_operators = true
+ij_groovy_spaces_around_regex_operators = true
+ij_groovy_spaces_around_relational_operators = true
+ij_groovy_spaces_around_shift_operators = true
+ij_groovy_spaces_within_annotation_parentheses = false
+ij_groovy_spaces_within_array_initializer_braces = false
+ij_groovy_spaces_within_braces = true
+ij_groovy_spaces_within_brackets = false
+ij_groovy_spaces_within_cast_parentheses = false
+ij_groovy_spaces_within_catch_parentheses = false
+ij_groovy_spaces_within_for_parentheses = false
+ij_groovy_spaces_within_gstring_injection_braces = false
+ij_groovy_spaces_within_if_parentheses = false
+ij_groovy_spaces_within_list_or_map = false
+ij_groovy_spaces_within_method_call_parentheses = false
+ij_groovy_spaces_within_method_parentheses = false
+ij_groovy_spaces_within_parentheses = false
+ij_groovy_spaces_within_switch_parentheses = false
+ij_groovy_spaces_within_synchronized_parentheses = false
+ij_groovy_spaces_within_try_parentheses = false
+ij_groovy_spaces_within_tuple_expression = false
+ij_groovy_spaces_within_while_parentheses = false
+ij_groovy_special_else_if_treatment = true
+ij_groovy_ternary_operation_wrap = off
+ij_groovy_throws_keyword_wrap = off
+ij_groovy_throws_list_wrap = off
+ij_groovy_use_flying_geese_braces = false
+ij_groovy_use_fq_class_names = false
+ij_groovy_use_fq_class_names_in_javadoc = true
+ij_groovy_use_relative_indents = false
+ij_groovy_use_single_class_imports = true
+ij_groovy_variable_annotation_wrap = off
+ij_groovy_while_brace_force = never
+ij_groovy_while_on_new_line = false
+ij_groovy_wrap_long_lines = false
+
+[{*.gradle.kts,*.kt,*.kts,*.main.kts}]
+ij_kotlin_align_in_columns_case_branch = false
+ij_kotlin_align_multiline_binary_operation = false
+ij_kotlin_align_multiline_extends_list = false
+ij_kotlin_align_multiline_method_parentheses = false
+ij_kotlin_align_multiline_parameters = true
+ij_kotlin_align_multiline_parameters_in_calls = false
+ij_kotlin_allow_trailing_comma = false
+ij_kotlin_allow_trailing_comma_on_call_site = false
+ij_kotlin_assignment_wrap = off
+ij_kotlin_blank_lines_after_class_header = 0
+ij_kotlin_blank_lines_around_block_when_branches = 0
+ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1
+ij_kotlin_block_comment_at_first_column = true
+ij_kotlin_call_parameters_new_line_after_left_paren = false
+ij_kotlin_call_parameters_right_paren_on_new_line = false
+ij_kotlin_call_parameters_wrap = off
+ij_kotlin_catch_on_new_line = false
+ij_kotlin_class_annotation_wrap = off
+ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL
+ij_kotlin_continuation_indent_for_chained_calls = true
+ij_kotlin_continuation_indent_for_expression_bodies = true
+ij_kotlin_continuation_indent_in_argument_lists = true
+ij_kotlin_continuation_indent_in_elvis = true
+ij_kotlin_continuation_indent_in_if_conditions = true
+ij_kotlin_continuation_indent_in_parameter_lists = true
+ij_kotlin_continuation_indent_in_supertype_lists = true
+ij_kotlin_else_on_new_line = false
+ij_kotlin_enum_constants_wrap = off
+ij_kotlin_extends_list_wrap = off
+ij_kotlin_field_annotation_wrap = normal
+ij_kotlin_finally_on_new_line = false
+ij_kotlin_if_rparen_on_new_line = false
+ij_kotlin_import_nested_classes = false
+ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^
+ij_kotlin_insert_whitespaces_in_simple_one_line_method = true
+ij_kotlin_keep_blank_lines_before_right_brace = 0
+ij_kotlin_keep_blank_lines_in_code = 1
+ij_kotlin_keep_blank_lines_in_declarations = 1
+ij_kotlin_keep_first_column_comment = true
+ij_kotlin_keep_indents_on_empty_lines = false
+ij_kotlin_keep_line_breaks = true
+ij_kotlin_lbrace_on_next_line = false
+ij_kotlin_line_comment_add_space = false
+ij_kotlin_line_comment_at_first_column = true
+ij_kotlin_method_annotation_wrap = split_into_lines
+ij_kotlin_method_call_chain_wrap = off
+ij_kotlin_method_parameters_new_line_after_left_paren = true
+ij_kotlin_method_parameters_right_paren_on_new_line = true
+ij_kotlin_method_parameters_wrap = off
+ij_kotlin_name_count_to_use_star_import = 2147483647
+ij_kotlin_name_count_to_use_star_import_for_members = 2147483647
+ij_kotlin_packages_to_use_import_on_demand = kotlinx.android.synthetic.**
+ij_kotlin_parameter_annotation_wrap = off
+ij_kotlin_space_after_comma = true
+ij_kotlin_space_after_extend_colon = true
+ij_kotlin_space_after_type_colon = true
+ij_kotlin_space_before_catch_parentheses = true
+ij_kotlin_space_before_comma = false
+ij_kotlin_space_before_extend_colon = true
+ij_kotlin_space_before_for_parentheses = true
+ij_kotlin_space_before_if_parentheses = true
+ij_kotlin_space_before_lambda_arrow = true
+ij_kotlin_space_before_type_colon = false
+ij_kotlin_space_before_when_parentheses = true
+ij_kotlin_space_before_while_parentheses = true
+ij_kotlin_spaces_around_additive_operators = true
+ij_kotlin_spaces_around_assignment_operators = true
+ij_kotlin_spaces_around_equality_operators = true
+ij_kotlin_spaces_around_function_type_arrow = true
+ij_kotlin_spaces_around_logical_operators = true
+ij_kotlin_spaces_around_multiplicative_operators = true
+ij_kotlin_spaces_around_range = false
+ij_kotlin_spaces_around_relational_operators = true
+ij_kotlin_spaces_around_unary_operator = false
+ij_kotlin_spaces_around_when_arrow = true
+ij_kotlin_use_custom_formatting_for_modifiers = true
+ij_kotlin_variable_annotation_wrap = off
+ij_kotlin_while_on_new_line = false
+ij_kotlin_wrap_elvis_expressions = 1
+ij_kotlin_wrap_expression_body_functions = 0
+ij_kotlin_wrap_first_method_in_call_chain = false
+
+[{*.har,*.json}]
+indent_size = 2
+ij_json_keep_blank_lines_in_code = 0
+ij_json_keep_indents_on_empty_lines = false
+ij_json_keep_line_breaks = true
+ij_json_space_after_colon = true
+ij_json_space_after_comma = true
+ij_json_space_before_colon = true
+ij_json_space_before_comma = false
+ij_json_spaces_within_braces = false
+ij_json_spaces_within_brackets = false
+ij_json_wrap_long_lines = false
+
+[{*.htm,*.html,*.sht,*.shtm,*.shtml}]
+ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
+ij_html_align_attributes = true
+ij_html_align_text = false
+ij_html_attribute_wrap = normal
+ij_html_block_comment_at_first_column = true
+ij_html_do_not_align_children_of_min_lines = 0
+ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p
+ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot
+ij_html_enforce_quotes = false
+ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var
+ij_html_keep_blank_lines = 2
+ij_html_keep_indents_on_empty_lines = false
+ij_html_keep_line_breaks = true
+ij_html_keep_line_breaks_in_text = true
+ij_html_keep_whitespaces = false
+ij_html_keep_whitespaces_inside = span,pre,textarea
+ij_html_line_comment_at_first_column = true
+ij_html_new_line_after_last_attribute = never
+ij_html_new_line_before_first_attribute = never
+ij_html_quote_style = double
+ij_html_remove_new_line_before_tags = br
+ij_html_space_after_tag_name = false
+ij_html_space_around_equality_in_attribute = false
+ij_html_space_inside_empty_tag = false
+ij_html_text_wrap = normal
+ij_html_uniform_ident = false
+
+[{*.yaml,*.yml}]
+indent_size = 2
+ij_yaml_align_values_properties = do_not_align
+ij_yaml_autoinsert_sequence_marker = true
+ij_yaml_block_mapping_on_new_line = false
+ij_yaml_indent_sequence_value = true
+ij_yaml_keep_indents_on_empty_lines = false
+ij_yaml_keep_line_breaks = true
+ij_yaml_sequence_on_new_line = false
+ij_yaml_space_before_colon = false
+ij_yaml_spaces_within_braces = true
+ij_yaml_spaces_within_brackets = true
diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml
index a7daaac14b..1ab5d835b2 100644
--- a/.github/ISSUE_TEMPLATE/bug.yml
+++ b/.github/ISSUE_TEMPLATE/bug.yml
@@ -73,3 +73,14 @@ body:
- 'No'
validations:
required: true
+ - type: dropdown
+ id: pr
+ attributes:
+ label: Are you willing to provide a PR?
+ description: |
+ Providing a PR can drastically speed up the process of fixing this bug. Don't worry, it's still OK to answer 'No' :).
+ options:
+ - 'Yes'
+ - 'No'
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml
index 71adce718e..2dd968951f 100644
--- a/.github/ISSUE_TEMPLATE/enhancement.yml
+++ b/.github/ISSUE_TEMPLATE/enhancement.yml
@@ -34,3 +34,14 @@ body:
placeholder: Is there anything else you'd like to add?
validations:
required: false
+ - type: dropdown
+ id: pr
+ attributes:
+ label: Are you willing to provide a PR?
+ description: |
+ Don't worry, it's still OK to answer 'No' :).
+ options:
+ - 'Yes'
+ - 'No'
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/release.yml b/.github/ISSUE_TEMPLATE/release.yml
index 7cb47fa952..e663a49fdb 100644
--- a/.github/ISSUE_TEMPLATE/release.yml
+++ b/.github/ISSUE_TEMPLATE/release.yml
@@ -49,24 +49,34 @@ body:
### Once tested and validated internally
- - [ ] Create a new beta release on the GooglePlay console and upload the 4 signed Apks.
+ - [ ] Create a new open testing release on the GooglePlay console and upload the 4 signed Apks.
- [ ] Check that the version codes are correct
- [ ] Copy the fastlane change to the GooglePlay console in the section en-GB.
- - [ ] Push to beta release to 100% of the users
- - [ ] Notify the F-Droid team so that they can schedule the publication on F-Droid
+ - [ ] Push the open testing release to 100% of the users
+ - [ ] Notify the F-Droid team [here](https://matrix.to/#/!LAAuJLQXYHjMNWKrCK:matrix.org?via=matrix.org&via=bubu1.eu&via=lant.uk) so that they can schedule the publication on F-Droid
+ - [ ] The application is available to the PlayStore testers (live). Google can take between 1 hour and up to 7 days to approve the release.
+ - [ ] The application is available to the F-Droid users.
- ### Once Live on PlayStore
+ ### Once open testing is live on PlayStore
- [ ] Ping the Android public room and update its topic
- - [ ] Add an entry in the internal diary
- ### After at least 2 days
+ ### Once Live on F-Droid
+
+ - [ ] Update the Android public room topic
+
+ ### After at least 2 days (generally next Monday)
- [ ] Check the [rageshakes](https://github.com/matrix-org/element-android-rageshakes/issues)
- [ ] Check the crash reports on the GooglePlay console
- [ ] Check the Android Element room for any reported issues on the new version
- - [ ] If all is OK, push to production and notify Markus (Bubu) to release the F-Droid version
- - [ ] Ping the Android public room and update its topic with the new available version
+ - [ ] If all is OK, promote the open testing release to production. Generally using a 100% roll out, but can be a smaller value depending on the release content.
+ - [ ] The application is available to the PlayStore users (live). Google can take (again!) between 1 hour and up to 7 days to approve the release.
+
+ ### Once production is live on PlayStore
+
+ - [ ] Ping the Android public room and update its topic
+ - [ ] Add an entry in the internal diary
### Android SDK2
@@ -90,12 +100,20 @@ body:
##### Release on MavenCentral
+ - [ ] Checkout the branch `main`
- [ ] Run the command `./gradlew publish --no-daemon --no-parallel`. You'll need some non-public element to do so
+ - [ ] Run the command `./gradlew closeAndReleaseRepository`. If it is working well, you can jump directly to the final step of this section.
+
+ If `./gradlew closeAndReleaseRepository` fails (for instance, several repositories are waiting to be handled), you have to close and release the repository manually. Do the following steps:
+
- [ ] Connect to https://s01.oss.sonatype.org
- [ ] Click on Staging Repositories and check the the files have been uploaded
- [ ] Click on close
- [ ] Wait (check Activity tab until step "Repository closed" is displayed)
- [ ] Click on release. The staging repository will disappear
+
+ Final step
+
- [ ] Check that the release is available in https://repo1.maven.org/maven2/org/matrix/android/matrix-android-sdk2/ (it can take a few minutes)
##### Release on GitHub
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9517a4f3a7..1c0491fda4 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -8,8 +8,9 @@ on:
# Enrich gradle.properties for CI/CD
env:
CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx2g
+ -Porg.gradle.jvmargs=-Xmx4g
-Porg.gradle.parallel=false
+ --no-daemon
jobs:
debug:
@@ -46,8 +47,9 @@ jobs:
release:
name: Build unsigned GPlay APKs
runs-on: ubuntu-latest
- if: github.ref == 'refs/heads/main'
- # Only runs on main, no concurrency.
+ concurrency:
+ group: ${{ github.ref == 'refs/head/main' && format('build-release-apk-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('build-release-apk-develop-{0}', github.sha) || format('build-debug-{0}', github.ref) }}
+ cancel-in-progress: ${{ github.ref != 'refs/head/main' }}
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
@@ -59,7 +61,7 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Assemble GPlay unsigned apk
- run: ./gradlew clean assembleGplayRelease $CI_GRADLE_ARG_PROPERTIES --stacktrace
+ run: ./gradlew clean assembleGplayRelease $CI_GRADLE_ARG_PROPERTIES --stacktrace
- name: Upload Gplay unsigned APKs
uses: actions/upload-artifact@v3
with:
@@ -67,4 +69,26 @@ jobs:
path: |
vector/build/outputs/apk/*/release/*.apk
-# TODO add exodus checks
+ exodus:
+ runs-on: ubuntu-latest
+ needs: release
+ steps:
+ - name: Obtain apk from artifact
+ id: download
+ uses: actions/download-artifact@v3
+ with:
+ name: vector-gplay-release-unsigned
+ - name: Show apks in artifact
+ run: ls -R ${{steps.download.outputs.download-path}}
+ - name: Execute exodus-standalone
+ uses: docker://exodusprivacy/exodus-standalone:latest
+ with:
+ args: /github/workspace/gplay/release/vector-gplay-universal-release-unsigned.apk -j -o /github/workspace/exodus.json
+ - name: Upload exodus json report
+ uses: actions/upload-artifact@v3
+ with:
+ name: exodus.json
+ path: |
+ exodus.json
+ - name: Check for trackers
+ run: "jq -e '.trackers == []' exodus.json > /dev/null || { echo '::error static analysis identified user tracking library' ; exit 1; }"
diff --git a/.github/workflows/post-pr.yml b/.github/workflows/post-pr.yml
index 8fe51eb8d5..a7f1d6f204 100644
--- a/.github/workflows/post-pr.yml
+++ b/.github/workflows/post-pr.yml
@@ -13,6 +13,7 @@ env:
CI_GRADLE_ARG_PROPERTIES: >
-Porg.gradle.jvmargs=-Xmx4g
-Porg.gradle.parallel=false
+ --no-daemon
jobs:
@@ -29,200 +30,6 @@ jobs:
steps:
- run: echo "Run those tests!" # no-op success
- # Run Android Tests
- integration-tests:
- name: Matrix SDK - Running Integration Tests
- needs: should-i-run
- runs-on: macos-latest
- strategy:
- fail-fast: false
- matrix:
- api-level: [ 28 ]
- steps:
- - uses: actions/checkout@v3
- - uses: gradle/wrapper-validation-action@v1
- - uses: actions/setup-java@v3
- with:
- distribution: 'adopt'
- java-version: 11
- - name: Set up Python 3.8
- uses: actions/setup-python@v3
- with:
- python-version: 3.8
- - uses: actions/cache@v3
- with:
- path: |
- ~/.gradle/caches
- ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- restore-keys: |
- ${{ runner.os }}-gradle-
- - name: Start synapse server
- uses: michaelkaye/setup-matrix-synapse@v1.0.3
- with:
- uploadLogs: true
- httpPort: 8080
- disableRateLimiting: true
- public_baseurl: "http://10.0.2.2:8080/"
- # package: org.matrix.android.sdk.session
- - name: Run integration tests for Matrix SDK [org.matrix.android.sdk.session] API[${{ matrix.api-level }}]
- uses: reactivecircus/android-emulator-runner@v2
- with:
- api-level: ${{ matrix.api-level }}
- arch: x86
- profile: Nexus 5X
- force-avd-creation: false
- emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
- emulator-build: 7425822
- script: |
- adb root
- adb logcat -c
- touch emulator-session.log
- chmod 777 emulator-session.log
- adb logcat >> emulator-session.log &
- ./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.session' matrix-sdk-android:connectedDebugAndroidTest
- - name: Read Results [org.matrix.android.sdk.session]
- if: always()
- id: get-comment-body-session
- run: python3 ./tools/ci/render_test_output.py session ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
- - name: Remove adb logcat
- if: always()
- run: pkill -9 adb
- - name: Run integration tests for Matrix SDK [org.matrix.android.sdk.account] API[${{ matrix.api-level }}]
- if: always()
- uses: reactivecircus/android-emulator-runner@v2
- with:
- api-level: ${{ matrix.api-level }}
- arch: x86
- profile: Nexus 5X
- force-avd-creation: false
- emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
- emulator-build: 7425822
- script: |
- adb root
- adb logcat -c
- touch emulator-account.log
- chmod 777 emulator-account.log
- adb logcat >> emulator-account.log &
- ./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.account' matrix-sdk-android:connectedDebugAndroidTest
- - name: Read Results [org.matrix.android.sdk.account]
- if: always()
- id: get-comment-body-account
- run: python3 ./tools/ci/render_test_output.py account ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
- - name: Remove adb logcat
- if: always()
- run: pkill -9 adb
- # package: org.matrix.android.sdk.internal
- - name: Run integration tests for Matrix SDK [org.matrix.android.sdk.internal] API[${{ matrix.api-level }}]
- if: always()
- uses: reactivecircus/android-emulator-runner@v2
- with:
- api-level: ${{ matrix.api-level }}
- arch: x86
- profile: Nexus 5X
- force-avd-creation: false
- emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
- emulator-build: 7425822
- script: |
- adb root
- adb logcat -c
- touch emulator-internal.log
- chmod 777 emulator-internal.log
- adb logcat >> emulator-internal.log &
- ./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.internal' matrix-sdk-android:connectedDebugAndroidTest
- - name: Read Results [org.matrix.android.sdk.internal]
- if: always()
- id: get-comment-body-internal
- run: python3 ./tools/ci/render_test_output.py internal ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
- - name: Remove adb logcat
- if: always()
- run: pkill -9 adb
- # package: org.matrix.android.sdk.ordering
- - name: Run integration tests for Matrix SDK [org.matrix.android.sdk.ordering] API[${{ matrix.api-level }}]
- if: always()
- uses: reactivecircus/android-emulator-runner@v2
- with:
- api-level: ${{ matrix.api-level }}
- arch: x86
- profile: Nexus 5X
- force-avd-creation: false
- emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
- emulator-build: 7425822
- script: |
- adb root
- adb logcat -c
- touch emulator-ordering.log
- chmod 777 emulator-ordering.log
- adb logcat >> emulator-ordering.log &
- ./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.ordering' matrix-sdk-android:connectedDebugAndroidTest
- - name: Read Results [org.matrix.android.sdk.ordering]
- if: always()
- id: get-comment-body-ordering
- run: python3 ./tools/ci/render_test_output.py ordering ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
- - name: Remove adb logcat
- if: always()
- run: pkill -9 adb
- # package: class PermalinkParserTest
- - name: Run integration tests for Matrix SDK class [org.matrix.android.sdk.PermalinkParserTest] API[${{ matrix.api-level }}]
- if: always()
- uses: reactivecircus/android-emulator-runner@v2
- with:
- api-level: ${{ matrix.api-level }}
- arch: x86
- profile: Nexus 5X
- force-avd-creation: false
- emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
- emulator-build: 7425822
- script: |
- adb root
- adb logcat -c
- touch emulator-permalink.log
- chmod 777 emulator-permalink.log
- adb logcat >> emulator-permalink.log &
- ./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.class='org.matrix.android.sdk.PermalinkParserTest' matrix-sdk-android:connectedDebugAndroidTest
- - name: Read Results [org.matrix.android.sdk.PermalinkParserTest]
- if: always()
- id: get-comment-body-permalink
- run: python3 ./tools/ci/render_test_output.py permalink ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
- - name: Remove adb logcat
- if: always()
- run: pkill -9 adb
- # package: class PermalinkParserTest
- - name: Find Comment
- if: always() && github.event_name == 'pull_request'
- uses: peter-evans/find-comment@v2
- id: fc
- with:
- issue-number: ${{ github.event.pull_request.number }}
- comment-author: 'github-actions[bot]'
- body-includes: Integration Tests Results
- - name: Publish results to PR
- if: always() && github.event_name == 'pull_request'
- uses: peter-evans/create-or-update-comment@v2
- with:
- comment-id: ${{ steps.fc.outputs.comment-id }}
- issue-number: ${{ github.event.pull_request.number }}
- body: |
- ### Matrix SDK
- ## Integration Tests Results:
- - `[org.matrix.android.sdk.session]`
${{ steps.get-comment-body-session.outputs.session }}
- - `[org.matrix.android.sdk.account]`
${{ steps.get-comment-body-account.outputs.account }}
- - `[org.matrix.android.sdk.internal]`
${{ steps.get-comment-body-internal.outputs.internal }}
- - `[org.matrix.android.sdk.ordering]`
${{ steps.get-comment-body-ordering.outputs.ordering }}
- - `[org.matrix.android.sdk.PermalinkParserTest]`
${{ steps.get-comment-body-permalink.outputs.permalink }}
- edit-mode: replace
- - name: Upload Test Report Log
- uses: actions/upload-artifact@v3
- if: always()
- with:
- name: integrationtest-error-results
- path: |
- emulator-permalink.log
- emulator-internal.log
- emulator-ordering.log
- emulator-account.log
- emulator-session.log
-
ui-tests:
name: UI Tests (Synapse)
needs: should-i-run
@@ -235,7 +42,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.8
- uses: actions/setup-python@v3
+ uses: actions/setup-python@v4
with:
python-version: 3.8
- uses: actions/cache@v3
@@ -282,42 +89,13 @@ jobs:
emulator.log
failure_screenshots/
- codecov-units:
- name: Unit tests with code coverage
- needs: should-i-run
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-java@v3
- with:
- distribution: 'adopt'
- java-version: '11'
- - uses: actions/cache@v3
- with:
- path: |
- ~/.gradle/caches
- ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- restore-keys: |
- ${{ runner.os }}-gradle-
- - run: ./gradlew allCodeCoverageReport $CI_GRADLE_ARG_PROPERTIES
- - name: Upload Codecov data
- uses: actions/upload-artifact@v3
- if: always()
- with:
- name: codecov-xml
- path: |
- build/reports/jacoco/allCodeCoverageReport/allCodeCoverageReport.xml
-
# Notify the channel about delayed failures
notify:
name: Notify matrix
runs-on: ubuntu-latest
needs:
- should-i-run
- - integration-tests
- ui-tests
- - codecov-units
if: always() && (needs.should-i-run.result == 'success' ) && ((needs.codecov-units.result != 'success' ) || (needs.ui-tests.result != 'success') || (needs.integration-tests.result != 'success'))
# No concurrency required, runs every time on a schedule.
steps:
diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml
index 014139d0ba..d7f5ce8b57 100644
--- a/.github/workflows/quality.yml
+++ b/.github/workflows/quality.yml
@@ -9,6 +9,8 @@ on:
env:
CI_GRADLE_ARG_PROPERTIES: >
-Porg.gradle.jvmargs=-Xmx4g
+ -Porg.gradle.parallel=false
+ --no-daemon
jobs:
check:
@@ -113,13 +115,13 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Dependency analysis
- run: ./gradlew buildHealth $CI_GRADLE_ARG_PROPERTIES
+ run: ./gradlew dependencyCheckAnalyze $CI_GRADLE_ARG_PROPERTIES
- name: Upload dependency analysis
if: always()
uses: actions/upload-artifact@v3
with:
name: dependency-analysis
- path: build/reports/dependency-analysis/build-health-report.txt
+ path: build/reports/dependency-check-report.html
# Lint for main module
android-lint:
@@ -140,7 +142,7 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Lint analysis
- run: ./gradlew clean :vector:lint --stacktrace
+ run: ./gradlew clean :vector:lint --stacktrace $CI_GRADLE_ARG_PROPERTIES
- name: Upload reports
if: always()
uses: actions/upload-artifact@v3
@@ -173,7 +175,7 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Lint ${{ matrix.target }} release
- run: ./gradlew clean lint${{ matrix.target }}Release --stacktrace
+ run: ./gradlew clean lint${{ matrix.target }}Release --stacktrace $CI_GRADLE_ARG_PROPERTIES
- name: Upload ${{ matrix.target }} linting report
if: always()
uses: actions/upload-artifact@v3
@@ -193,7 +195,7 @@ jobs:
- uses: actions/checkout@v3
- name: Run detekt
run: |
- ./gradlew detekt
+ ./gradlew detekt $CI_GRADLE_ARG_PROPERTIES
- name: Upload reports
if: always()
uses: actions/upload-artifact@v3
diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml
deleted file mode 100644
index 6809751d91..0000000000
--- a/.github/workflows/sonarqube.yml
+++ /dev/null
@@ -1,81 +0,0 @@
-name: Sonarqube nightly
-
-on:
- schedule:
- - cron: '0 20 * * *'
-
-# Enrich gradle.properties for CI/CD
-env:
- CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx4g
- -Porg.gradle.parallel=false
-jobs:
- codecov-units:
- name: Unit tests with code coverage
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-java@v3
- with:
- distribution: 'adopt'
- java-version: '11'
- - uses: actions/cache@v3
- with:
- path: |
- ~/.gradle/caches
- ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- restore-keys: |
- ${{ runner.os }}-gradle-
- - run: ./gradlew allCodeCoverageReport $CI_GRADLE_ARG_PROPERTIES
- - name: Upload Codecov data
- uses: actions/upload-artifact@v3
- if: always()
- with:
- name: codecov-xml
- path: |
- build/reports/jacoco/allCodeCoverageReport/allCodeCoverageReport.xml
-
- sonarqube:
- name: Sonarqube upload
- runs-on: ubuntu-latest
- needs:
- - codecov-units
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-java@v3
- with:
- distribution: 'adopt'
- java-version: '11'
- - uses: actions/cache@v3
- with:
- path: |
- ~/.gradle/caches
- ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- restore-keys: |
- ${{ runner.os }}-gradle-
- - uses: actions/download-artifact@v3
- with:
- name: codecov-xml # will restore to allCodeCoverageReport.xml by default; we restore to the same location in following tasks
- - run: mkdir -p build/reports/jacoco/allCodeCoverageReport/
- - run: mv allCodeCoverageReport.xml build/reports/jacoco/allCodeCoverageReport/
- - run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES
- env:
- ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }}
-
-# Notify the channel about sonarqube failures
- notify:
- name: Notify matrix
- runs-on: ubuntu-latest
- needs:
- - sonarqube
- - codecov-units
- if: always() && (needs.sonarqube.result != 'success' || needs.codecov-units.result != 'success')
- steps:
- - uses: michaelkaye/matrix-hookshot-action@v1.0.0
- with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
- hookshot_url: ${{ secrets.ELEMENT_ANDROID_HOOKSHOT_URL }}
- text_template: "Sonarqube run (on ${{ github.ref }}): {{#each job_statuses }}{{#with this }}{{#if completed }} {{name}} {{conclusion}} at {{completed_at}}, {{/if}}{{/with}}{{/each}}"
- html_template: "Sonarqube run (on ${{ github.ref }}): {{#each job_statuses }}{{#with this }}{{#if completed }}
{{icon conclusion}} {{name}} {{conclusion}} at {{completed_at}} [details]{{/if}}{{/with}}{{/each}}"
diff --git a/.github/workflows/sync-from-external-sources.yml b/.github/workflows/sync-from-external-sources.yml
index 796d915ea6..fdc1bbcb96 100644
--- a/.github/workflows/sync-from-external-sources.yml
+++ b/.github/workflows/sync-from-external-sources.yml
@@ -13,7 +13,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.8
- uses: actions/setup-python@v3
+ uses: actions/setup-python@v4
with:
python-version: 3.8
- name: Install Prerequisite dependencies
@@ -40,7 +40,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.8
- uses: actions/setup-python@v3
+ uses: actions/setup-python@v4
with:
python-version: 3.8
- name: Install Prerequisite dependencies
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 3e8de8979c..1a9cc5c239 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -8,77 +8,111 @@ on:
# Enrich gradle.properties for CI/CD
env:
CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx2g
+ -Porg.gradle.jvmargs=-Xmx4g
-Porg.gradle.parallel=false
+ --no-daemon
jobs:
- # Build Android Tests
- build-android-tests:
- name: Build Android Tests
- runs-on: ubuntu-latest
- concurrency:
- group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('build-android-tests-{0}', github.ref) }}
- cancel-in-progress: true
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-java@v3
- with:
- distribution: 'adopt'
- java-version: 11
- - uses: actions/cache@v3
- with:
- path: |
- ~/.gradle/caches
- ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- restore-keys: |
- ${{ runner.os }}-gradle-
- - name: Build Android Tests
- run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES --stacktrace
-
- unit-tests:
- name: Run Unit Tests
- runs-on: ubuntu-latest
+ tests:
+ name: Runs all tests
+ runs-on: macos-latest # for the emulator
# Allow all jobs on main and develop. Just one per PR.
concurrency:
group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v3
- - uses: actions/cache@v3
with:
- path: |
- ~/.gradle/caches
- ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- restore-keys: |
- ${{ runner.os }}-gradle-
- - name: Run unit tests
- run: ./gradlew clean test $CI_GRADLE_ARG_PROPERTIES --stacktrace
+ fetch-depth: 0
+ - uses: actions/setup-java@v3
+ with:
+ distribution: 'adopt'
+ java-version: '11'
+ - uses: gradle/gradle-build-action@v2
+ - uses: actions/setup-python@v4
+ with:
+ python-version: 3.8
+ - uses: michaelkaye/setup-matrix-synapse@v1.0.3
+ with:
+ uploadLogs: true
+ httpPort: 8080
+ disableRateLimiting: true
+ public_baseurl: "http://10.0.2.2:8080/"
+ - name: Run all the codecoverage tests at once
+ id: tests
+ uses: reactivecircus/android-emulator-runner@v2
+ continue-on-error: true
+ with:
+ api-level: 28
+ arch: x86
+ profile: Nexus 5X
+ force-avd-creation: false
+ emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
+ disable-animations: true
+ emulator-build: 7425822
+ script: |
+ ./gradlew unitTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew instrumentationTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew generateCoverageReport --stacktrace $CI_GRADLE_ARG_PROPERTIES
+# NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves stes.tests.outcome = 'failure'
+ - name: Run all the codecoverage tests at once (retry if emulator failed)
+ uses: reactivecircus/android-emulator-runner@v2
+ if: always() && steps.tests.outcome == 'failure' # don't run if previous step succeeded.
+ with:
+ api-level: 28
+ arch: x86
+ profile: Nexus 5X
+ force-avd-creation: false
+ emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
+ disable-animations: true
+ emulator-build: 7425822
+ script: |
+ ./gradlew unitTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew instrumentationTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew generateCoverageReport --stacktrace $CI_GRADLE_ARG_PROPERTIES
+ - run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES
+ if: always() # we may have failed a previous step and retried, that's OK
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }}
+
- name: Format unit test results
if: always()
run: python3 ./tools/ci/render_test_output.py unit ./**/build/test-results/**/*.xml
- - name: Publish Unit Test Results
- uses: EnricoMi/publish-unit-test-result-action@v1
- if: always() &&
- github.event.sender.login != 'dependabot[bot]' &&
- ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository )
- with:
- files: ./**/build/test-results/**/*.xml
-# Notify the channel about runs against develop or main that have failures, as PRs should have caught these first.
- notify:
- runs-on: ubuntu-latest
- needs:
- - unit-tests
- - build-android-tests
- if: ${{ (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/main' ) && failure() }}
- steps:
- - uses: michaelkaye/matrix-hookshot-action@v0.3.0
- with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
- matrix_access_token: ${{ secrets.ELEMENT_ANDROID_NOTIFICATION_ACCESS_TOKEN }}
- matrix_room_id: ${{ secrets.ELEMENT_ANDROID_INTERNAL_ROOM_ID }}
- text_template: "Build is broken for ${{ github.ref }}: {{#each job_statuses }}{{#with this }}{{#if completed }}{{name}} {{conclusion}} at {{completed_at}}, {{/if}}{{/with}}{{/each}}"
- html_template: "Build is broken for ${{ github.ref }}: {{#each job_statuses }}{{#with this }}{{#if completed }}
{{icon conclusion }} {{name}} {{conclusion}} at {{completed_at}} [details]{{/if}}{{/with}}{{/each}}"
+# can't be run on macos due to containers.
+# - name: Publish Unit Test Results
+# uses: EnricoMi/publish-unit-test-result-action@v1
+# if: always() &&
+# github.event.sender.login != 'dependabot[bot]' &&
+# ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository )
+# with:
+# files: ./**/build/test-results/**/*.xml
+
+# Unneeded as part of the test suite above, kept around in case we want to re-enable them.
+#
+# # Build Android Tests
+# build-android-tests:
+# name: Build Android Tests
+# runs-on: ubuntu-latest
+# concurrency:
+# group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('build-android-tests-{0}', github.ref) }}
+# cancel-in-progress: true
+# steps:
+# - uses: actions/checkout@v3
+# - uses: actions/setup-java@v3
+# with:
+# distribution: 'adopt'
+# java-version: 11
+# - uses: actions/cache@v3
+# with:
+# path: |
+# ~/.gradle/caches
+# ~/.gradle/wrapper
+# key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
+# restore-keys: |
+# ${{ runner.os }}-gradle-
+# - name: Build Android Tests
+# run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES --stacktrace
diff --git a/.github/workflows/triage-labelled.yml b/.github/workflows/triage-labelled.yml
index 82d5931ce7..c49b33d582 100644
--- a/.github/workflows/triage-labelled.yml
+++ b/.github/workflows/triage-labelled.yml
@@ -9,15 +9,15 @@ jobs:
name: Add Z-Labs label for features behind labs flags
runs-on: ubuntu-latest
if: >
- contains(github.event.issue.labels.*.name, 'A-Maths') ||
- contains(github.event.issue.labels.*.name, 'A-Message-Pinning') ||
- contains(github.event.issue.labels.*.name, 'A-Polls') ||
- contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
- contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') ||
- contains(github.event.issue.labels.*.name, 'Z-IA') ||
- contains(github.event.issue.labels.*.name, 'A-Themes-Custom') ||
- contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
- contains(github.event.issue.labels.*.name, 'A-Tags')
+ contains(github.event.issue.labels.*.name, 'A-Maths') ||
+ contains(github.event.issue.labels.*.name, 'A-Message-Pinning') ||
+ contains(github.event.issue.labels.*.name, 'A-Polls') ||
+ contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
+ contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') ||
+ contains(github.event.issue.labels.*.name, 'Z-IA') ||
+ contains(github.event.issue.labels.*.name, 'A-Themes-Custom') ||
+ contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
+ contains(github.event.issue.labels.*.name, 'A-Tags')
steps:
- uses: actions/github-script@v5
with:
@@ -79,7 +79,7 @@ jobs:
name: X-Needs-Product to Design project board
runs-on: ubuntu-latest
if: >
- contains(github.event.issue.labels.*.name, 'X-Needs-Product')
+ contains(github.event.issue.labels.*.name, 'X-Needs-Product')
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
@@ -105,10 +105,7 @@ jobs:
# Skip in forks
if: >
github.repository == 'vector-im/element-android' &&
- (contains(github.event.issue.labels.*.name, 'A-Spaces') ||
- contains(github.event.issue.labels.*.name, 'A-Space-Settings') ||
- contains(github.event.issue.labels.*.name, 'A-Subspaces') ||
- contains(github.event.issue.labels.*.name, 'Z-IA'))
+ (contains(github.event.issue.labels.*.name, 'Team: Delight'))
steps:
- uses: octokit/graphql-action@v2.x
with:
@@ -201,7 +198,7 @@ jobs:
env:
PROJECT_ID: "PN_kwDOAM0swc3m-g"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
-
+
move_ftue_issues:
name: Z-FTUE to Mobile FTUE board
runs-on: ubuntu-latest
diff --git a/.github/workflows/triage-priority-bugs.yml b/.github/workflows/triage-priority-bugs.yml
index 70c337e748..6cde154370 100644
--- a/.github/workflows/triage-priority-bugs.yml
+++ b/.github/workflows/triage-priority-bugs.yml
@@ -14,10 +14,7 @@ jobs:
!contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') &&
!contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') &&
!contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') &&
- !contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification') &&
- !contains(github.event.issue.labels.*.name, 'A-Spaces') &&
- !contains(github.event.issue.labels.*.name, 'A-Spaces-Settings') &&
- !contains(github.event.issue.labels.*.name, 'A-Subspaces')) &&
+ !contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification')) &&
(contains(github.event.issue.labels.*.name, 'T-Defect') &&
contains(github.event.issue.labels.*.name, 'S-Critical') &&
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
diff --git a/.gitignore b/.gitignore
index 9b9b001ba1..2978e876b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,7 +17,7 @@
/fastlane/report.xml
/fastlane/README.md
-/library/build
+/**/build
.tmp_unpatched_strings
.tmp_new_patched_strings
diff --git a/.idea/dictionaries/bmarty.xml b/.idea/dictionaries/bmarty.xml
index 85290e72df..c29bca95f2 100644
--- a/.idea/dictionaries/bmarty.xml
+++ b/.idea/dictionaries/bmarty.xml
@@ -40,6 +40,7 @@
sygnal
threepid
uisi
+ unifiedpush
unpublish
unwedging
vctr
diff --git a/CHANGES.md b/CHANGES.md
index 60497402e9..b66e567f5b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,132 @@
+Changes in Element v1.4.27 (2022-07-06)
+=======================================
+
+Bugfixes 🐛
+----------
+ - Fixes crash when sharing plain text, such as a url ([#6451](https://github.com/vector-im/element-android/issues/6451))
+ - Fix crashes on Timeline [Thread] due to range validation ([#6461](https://github.com/vector-im/element-android/issues/6461))
+ - Fix crashes when opening Thread ([#6463](https://github.com/vector-im/element-android/issues/6463))
+ - Fix ConcurrentModificationException on BackgroundDetectionObserver ([#6469](https://github.com/vector-im/element-android/issues/6469))
+
+
+Changes in Element v1.4.26 (2022-06-30)
+=======================================
+
+Features ✨
+----------
+ - Use UnifiedPush and allows user to have push without FCM. ([#3448](https://github.com/vector-im/element-android/issues/3448))
+ - Replace ffmpeg-kit with libopus and libopusenc. ([#6203](https://github.com/vector-im/element-android/issues/6203))
+ - Improve lock screen implementation. ([#6217](https://github.com/vector-im/element-android/issues/6217))
+ - Allow sharing text based content via android's share menu (eg .ics files) ([#6285](https://github.com/vector-im/element-android/issues/6285))
+ - Promote live location labs flag ([#6350](https://github.com/vector-im/element-android/issues/6350))
+ - [Location sharing] - Stop any active live before starting a new one ([#6364](https://github.com/vector-im/element-android/issues/6364))
+ - Expose pusher profile tag in advanced settings ([#6369](https://github.com/vector-im/element-android/issues/6369))
+
+Bugfixes 🐛
+----------
+ - Fixes concurrent modification crash when signing out or launching the app ([#5821](https://github.com/vector-im/element-android/issues/5821))
+ - Refactor - better naming, return native user id and not sip user id and create a dm with the native user instead of with the sip user. ([#6101](https://github.com/vector-im/element-android/issues/6101))
+ - Fixed /upgraderoom command not doing anything ([#6154](https://github.com/vector-im/element-android/issues/6154))
+ - Fixed crash when opening large images in the timeline ([#6290](https://github.com/vector-im/element-android/issues/6290))
+ - [Location sharing] Fix crash when starting/stopping a live when offline ([#6315](https://github.com/vector-im/element-android/issues/6315))
+ - Fix loop in timeline and simplify management of chunks and timeline events. ([#6318](https://github.com/vector-im/element-android/issues/6318))
+ - Update design and behaviour on widget permission bottom sheet ([#6326](https://github.com/vector-im/element-android/issues/6326))
+ - Fix | Some user verification requests couldn't be accepted/declined ([#6328](https://github.com/vector-im/element-android/issues/6328))
+ - [Location sharing] Fix stop of a live not possible from another device ([#6349](https://github.com/vector-im/element-android/issues/6349))
+ - Fix backslash escapes in formatted messages ([#6357](https://github.com/vector-im/element-android/issues/6357))
+ - Fixes wrong error message when signing in with wrong credentials ([#6371](https://github.com/vector-im/element-android/issues/6371))
+ - [Location Share] - Adding missing prefix "u=" for uncertainty in geo URI ([#6375](https://github.com/vector-im/element-android/issues/6375))
+
+In development 🚧
+----------------
+ - FTUE - Adds automatic homeserver selection when typing a full matrix id during registration or login ([#6162](https://github.com/vector-im/element-android/issues/6162))
+
+Improved Documentation 📚
+------------------------
+ - Update the PR process doc to come back to one reviewer with optional additional reviewers. ([#6396](https://github.com/vector-im/element-android/issues/6396))
+
+SDK API changes ⚠️
+------------------
+ - Group all location sharing related API into LocationSharingService ([#5864](https://github.com/vector-im/element-android/issues/5864))
+ - Add support for MSC2457 - opting in or out of logging out all devices when changing password ([#6191](https://github.com/vector-im/element-android/issues/6191))
+ - Create `QueryStateEventValue` to do query on `stateKey` for State Event. Also remove the default parameter values for those type. ([#6319](https://github.com/vector-im/element-android/issues/6319))
+
+Other changes
+-------------
+ - - Notify of the latest known location in LocationTracker to avoid multiple locations at start
+ - Debounce location updates
+ - Improve location providers access ([#5913](https://github.com/vector-im/element-android/issues/5913))
+ - Add unit tests for LiveLocationAggregationProcessor code ([#6155](https://github.com/vector-im/element-android/issues/6155))
+ - Making screenshots in bug reports opt in instead of opt out ([#6261](https://github.com/vector-im/element-android/issues/6261))
+ - Setup [Flipper](https://fbflipper.com/) ([#6300](https://github.com/vector-im/element-android/issues/6300))
+ - CreatePollViewModel unit tests ([#6320](https://github.com/vector-im/element-android/issues/6320))
+ - Fix flaky test in voice recording feature. ([#6329](https://github.com/vector-im/element-android/issues/6329))
+ - Poll view state unit tests ([#6366](https://github.com/vector-im/element-android/issues/6366))
+ - Let LoadRoomMembersTask insert by chunk to release db. ([#6394](https://github.com/vector-im/element-android/issues/6394))
+
+
+Changes in Element v1.4.25 (2022-06-27)
+=======================================
+
+Bugfixes 🐛
+----------
+- Second attempt to fix session database migration to version 30.
+
+Changes in Element v1.4.24 (2022-06-22)
+=======================================
+
+Bugfixes 🐛
+----------
+- First attempt to fix session database migration to version 30.
+
+Changes in Element v1.4.23 (2022-06-21)
+=======================================
+
+Bugfixes 🐛
+----------
+ - Fix loop in timeline and simplify management of chunks and timeline events. ([#6318](https://github.com/vector-im/element-android/issues/6318))
+
+
+Changes in Element v1.4.22 (2022-06-14)
+=======================================
+
+Features ✨
+----------
+ - Make read receipt avatar list more compact ([#5970](https://github.com/vector-im/element-android/issues/5970))
+ - Allow .well-known configuration to override key sharing mode ([#6147](https://github.com/vector-im/element-android/issues/6147))
+ - Re-organize location settings flags ([#6244](https://github.com/vector-im/element-android/issues/6244))
+ - Add report action for live location messages ([#6280](https://github.com/vector-im/element-android/issues/6280))
+
+Bugfixes 🐛
+----------
+ - Fix cases of missing, swapped, or duplicated messages ([#5528](https://github.com/vector-im/element-android/issues/5528))
+ - Fix wrong status of live location sharing in timeline ([#6209](https://github.com/vector-im/element-android/issues/6209))
+ - Fix StackOverflowError while recording voice message ([#6222](https://github.com/vector-im/element-android/issues/6222))
+ - Text cropped: "Secure backup" ([#6232](https://github.com/vector-im/element-android/issues/6232))
+ - Fix copyright attributions of map views ([#6247](https://github.com/vector-im/element-android/issues/6247))
+ - Fix flickering bottom bar of live location item ([#6264](https://github.com/vector-im/element-android/issues/6264))
+
+In development 🚧
+----------------
+ - FTUE - Adds Sign Up tracking ([#5285](https://github.com/vector-im/element-android/issues/5285))
+
+SDK API changes ⚠️
+------------------
+ - Some methods from `Session` have been moved to a new `SyncService`, that you can retrieve from a `Session`.
+ - `SyncStatusService` method has been moved to the new `SyncService`
+ - `InitSyncStep` have been moved and renamed to `InitialSyncStep`
+ - `SyncStatusService.Status` has been renamed to `SyncRequestState`
+ - The existing `SyncService` has been renamed to `SyncAndroidService` because of name clash with the new SDK Service ([#6029](https://github.com/vector-im/element-android/issues/6029))
+ - Allows `AuthenticationService.getLoginFlow` to fail without resetting state from previously successful calls ([#6093](https://github.com/vector-im/element-android/issues/6093))
+ - Allows new passwords to be passed at the point of confirmation when resetting a password ([#6169](https://github.com/vector-im/element-android/issues/6169))
+
+Other changes
+-------------
+ - Adds support for parsing homeserver versions without a patch number ([#6017](https://github.com/vector-im/element-android/issues/6017))
+ - Updating exit onboarding dialog copy formatting to match iOS ([#6087](https://github.com/vector-im/element-android/issues/6087))
+ - Disables when arrow alignment in code style ([#6126](https://github.com/vector-im/element-android/issues/6126))
+
+
Changes in Element 1.4.20 (2022-06-13)
======================================
diff --git a/README.md b/README.md
index 54dfb7b288..7acb5aa638 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
[![Buildkite](https://badge.buildkite.com/ad0065c1b70f557cd3b1d3d68f9c2154010f83c4d6f71706a9.svg?branch=develop)](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop)
[![Weblate](https://translate.element.io/widgets/element-android/-/svg-badge.svg)](https://translate.element.io/engage/element-android/?utm_source=widget)
[![Element Android Matrix room #element-android:matrix.org](https://img.shields.io/matrix/element-android:matrix.org.svg?label=%23element-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-android:matrix.org)
-[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=im.vector.app.android&metric=alert_status)](https://sonarcloud.io/dashboard?id=im.vector.app.android)
-[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=im.vector.app.android&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=im.vector.app.android)
-[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=im.vector.app.android&metric=bugs)](https://sonarcloud.io/dashboard?id=im.vector.app.android)
+[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-android&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vector-im_element-android)
+[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-android&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=vector-im_element-android)
+[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-android&metric=bugs)](https://sonarcloud.io/summary/new_code?id=vector-im_element-android)
# Element Android
diff --git a/build.gradle b/build.gradle
index 635db83e14..0244080ad0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -25,11 +25,11 @@ buildscript {
classpath libs.gradle.kotlinPlugin
classpath libs.gradle.hiltPlugin
classpath 'com.google.gms:google-services:4.3.10'
- classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
+ classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5'
classpath "com.likethesalad.android:stem-plugin:2.1.1"
- classpath 'org.owasp:dependency-check-gradle:7.1.0.1'
- classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.21"
+ classpath 'org.owasp:dependency-check-gradle:7.1.1'
+ classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.0"
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -43,7 +43,7 @@ plugins {
id "io.gitlab.arturbosch.detekt" version "1.20.0"
// Dependency Analysis
- id 'com.autonomousapps.dependency-analysis' version "1.4.0"
+ id 'com.autonomousapps.dependency-analysis' version "1.9.0"
}
// https://github.com/jeremylong/DependencyCheck
@@ -168,7 +168,7 @@ def launchTask = getGradle()
.toString()
.toLowerCase()
-if (launchTask.contains("codeCoverageReport".toLowerCase())) {
+if (launchTask.contains("coverage".toLowerCase())) {
apply from: 'coverage.gradle'
}
@@ -180,8 +180,8 @@ apply plugin: 'org.sonarqube'
sonarqube {
properties {
- property "sonar.projectName", "Element-Android"
- property "sonar.projectKey", "im.vector.app.android"
+ property "sonar.projectName", "element-android"
+ property "sonar.projectKey", "vector-im_element-android"
property "sonar.host.url", "https://sonarcloud.io"
property "sonar.projectVersion", project(":vector").android.defaultConfig.versionName
property "sonar.sourceEncoding", "UTF-8"
@@ -191,7 +191,7 @@ sonarqube {
property "sonar.links.issue", "https://github.com/vector-im/element-android/issues"
property "sonar.organization", "new_vector_ltd_organization"
property "sonar.java.coveragePlugin", "jacoco"
- property "sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/jacoco/allCodeCoverageReport/allCodeCoverageReport.xml"
+ property "sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/jacoco/generateCoverageReport/generateCoverageReport.xml"
property "sonar.login", project.hasProperty("SONAR_LOGIN") ? SONAR_LOGIN : "invalid"
}
}
@@ -252,11 +252,7 @@ dependencyAnalysis {
exclude("org.json:json") // Used in unit tests, overwrites the one bundled into Android
}
}
- project(":library:ui-styles") {
- onUnusedDependencies {
- exclude("com.github.vector-im:PFLockScreen-Android") // False positive
- }
- }
+ project(":library:ui-styles")
project(":matrix-sdk-android") {
onUnusedDependencies {
exclude("io.reactivex.rxjava2:rxkotlin") // Transitively required for mocking realm as monarchy doesn't expose Rx
@@ -271,6 +267,8 @@ dependencyAnalysis {
onUnusedDependencies {
// False positives
exclude(
+ "androidx.fragment:fragment-testing",
+ "com.facebook.soloader:soloader",
"com.vanniktech:emoji-google",
"com.vanniktech:emoji-material",
"org.maplibre.gl:android-plugin-annotation-v9",
diff --git a/coverage.gradle b/coverage.gradle
index b62ce0b4a0..f278a475ef 100644
--- a/coverage.gradle
+++ b/coverage.gradle
@@ -1,9 +1,36 @@
-def excludes = [ ]
+def excludes = [
+// dependency injection graph
+'**/*Module.*',
+'**/*Module*.*',
+
+// Framework entry points
+'**/*Activity*',
+'**/*Fragment*',
+'**/*Application*',
+
+// We would like to exclude android widgets as well but our naming is inconsistent
+
+// Proof of concept
+'**/*Login2*',
+
+// Generated
+'**/*JsonAdapter*',
+'**/*Item.*',
+'**/*$Holder.*',
+'**/*ViewHolder.*',
+'**/*View.*',
+'**/*BottomSheet.*'
+]
def initializeReport(report, projects, classExcludes) {
projects.each { project -> project.apply plugin: 'jacoco' }
- report.executionData { fileTree(rootProject.rootDir.absolutePath).include("**/build/jacoco/*.exec") }
+ report.executionData {
+ fileTree(rootProject.rootDir.absolutePath).include(
+ "**/build/**/*.exec",
+ "**/build/outputs/code_coverage/**/coverage.ec",
+ )
+ }
report.reports {
xml.enabled true
html.enabled true
@@ -43,13 +70,21 @@ def collectProjects(predicate) {
return subprojects.findAll { it.buildFile.isFile() && predicate(it) }
}
-task allCodeCoverageReport(type: JacocoReport) {
+task generateCoverageReport(type: JacocoReport) {
outputs.upToDateWhen { false }
rootProject.apply plugin: 'jacoco'
- // to limit projects in a specific report, add
- // def excludedProjects = [ ... ]
- // def projects = collectProjects { !excludedProjects.contains(it.name) }
- def projects = collectProjects { true }
- dependsOn { projects*.test }
+ def projects = collectProjects { ['vector', 'matrix-sdk-android'].contains(it.name) }
initializeReport(it, projects, excludes)
}
+
+task unitTestsWithCoverage(type: GradleBuild) {
+ // the 7.1.3 android gradle plugin has a bug where enableTestCoverage generates invalid coverage
+ startParameter.projectProperties.coverage = [enableTestCoverage: false]
+ tasks = [':vector:testGplayDebugUnitTest', ':matrix-sdk-android:testDebugUnitTest']
+}
+
+task instrumentationTestsWithCoverage(type: GradleBuild) {
+ startParameter.projectProperties.coverage = [enableTestCoverage: true]
+ startParameter.projectProperties['android.testInstrumentationRunnerArguments.notPackage'] = 'im.vector.app.ui'
+ tasks = [':vector:connectedGplayDebugAndroidTest', 'matrix-sdk-android:connectedDebugAndroidTest']
+}
diff --git a/dependencies.gradle b/dependencies.gradle
index 2f2b48463d..6f034eddd8 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -13,7 +13,7 @@ ext.versions = [
def gradle = "7.1.3"
// Ref: https://kotlinlang.org/releases.html
def kotlin = "1.6.21"
-def kotlinCoroutines = "1.6.2"
+def kotlinCoroutines = "1.6.3"
def dagger = "2.42"
def retrofit = "2.9.0"
def arrow = "0.8.2"
@@ -21,20 +21,21 @@ def markwon = "4.6.2"
def moshi = "1.13.0"
def lifecycle = "2.4.1"
def flowBinding = "1.2.0"
+def flipper = "0.151.1"
def epoxy = "4.6.2"
-def mavericks = "2.6.1"
+def mavericks = "2.7.0"
def glide = "4.13.2"
def bigImageViewer = "1.8.1"
def jjwt = "0.11.5"
def vanniktechEmoji = "0.15.0"
+def fragment = "1.4.1"
+
// Testing
-def mockk = "1.12.4"
+def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819
def espresso = "3.4.0"
def androidxTest = "1.4.0"
def androidxOrchestrator = "1.4.1"
-
-
ext.libs = [
gradle : [
'gradlePlugin' : "com.android.tools.build:gradle:$gradle",
@@ -49,12 +50,16 @@ ext.libs = [
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
],
androidx : [
+ 'annotation' : "androidx.annotation:annotation:1.4.0",
'activity' : "androidx.activity:activity:1.4.0",
- 'appCompat' : "androidx.appcompat:appcompat:1.4.1",
- 'core' : "androidx.core:core-ktx:1.7.0",
+ 'annotations' : "androidx.annotation:annotation:1.3.0",
+ 'appCompat' : "androidx.appcompat:appcompat:1.4.2",
+ 'biometric' : "androidx.biometric:biometric:1.1.0",
+ 'core' : "androidx.core:core-ktx:1.8.0",
'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
'exifinterface' : "androidx.exifinterface:exifinterface:1.3.3",
- 'fragmentKtx' : "androidx.fragment:fragment-ktx:1.4.1",
+ 'fragmentKtx' : "androidx.fragment:fragment-ktx:$fragment",
+ 'fragmentTesting' : "androidx.fragment:fragment-testing:$fragment",
'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.4",
'work' : "androidx.work:work-runtime-ktx:2.7.1",
'autoFill' : "androidx.autofill:autofill:1.1.0",
@@ -79,14 +84,19 @@ ext.libs = [
'transition' : "androidx.transition:transition:1.2.0",
],
google : [
- 'material' : "com.google.android.material:material:1.6.0"
+ 'material' : "com.google.android.material:material:1.6.1"
],
dagger : [
'dagger' : "com.google.dagger:dagger:$dagger",
'daggerCompiler' : "com.google.dagger:dagger-compiler:$dagger",
'hilt' : "com.google.dagger:hilt-android:$dagger",
+ 'hiltAndroidTesting' : "com.google.dagger:hilt-android-testing:$dagger",
'hiltCompiler' : "com.google.dagger:hilt-compiler:$dagger"
],
+ flipper : [
+ 'flipper' : "com.facebook.flipper:flipper:$flipper",
+ 'flipperNetworkPlugin' : "com.facebook.flipper:flipper-network-plugin:$flipper",
+ ],
squareup : [
'moshi' : "com.squareup.moshi:moshi:$moshi",
'moshiKt' : "com.squareup.moshi:moshi-kotlin:$moshi",
@@ -156,3 +166,5 @@ ext.libs = [
'junit' : "junit:junit:4.13.2"
]
]
+
+
diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle
index da9623efdd..b8722d3a29 100644
--- a/dependencies_groups.gradle
+++ b/dependencies_groups.gradle
@@ -33,6 +33,7 @@ ext.groups = [
],
group: [
'com.android',
+ 'com.android.ndk.thirdparty',
'com.android.tools',
'com.google.firebase',
'com.google.testing.platform',
@@ -54,6 +55,7 @@ ext.groups = [
'com.dropbox.core',
'com.soywiz.korlibs.korte',
'com.facebook.fbjni',
+ 'com.facebook.flipper',
'com.facebook.fresco',
'com.facebook.infer.annotation',
'com.facebook.soloader',
@@ -95,6 +97,7 @@ ext.groups = [
'com.ibm.icu',
'com.jakewharton.android.repackaged',
'com.jakewharton.timber',
+ 'com.kgurgul.flipper',
'com.linkedin.dexmaker',
'com.mapbox.mapboxsdk',
'com.nulab-inc',
@@ -170,6 +173,7 @@ ext.groups = [
'org.glassfish.jaxb',
'org.hamcrest',
'org.jacoco',
+ 'org.java-websocket',
'org.jetbrains',
'org.jetbrains.dokka',
'org.jetbrains.intellij.deps',
diff --git a/docs/flipper.md b/docs/flipper.md
new file mode 100644
index 0000000000..495425ce5f
--- /dev/null
+++ b/docs/flipper.md
@@ -0,0 +1,58 @@
+# Flipper
+
+
+
+* [Introduction](#introduction)
+* [Setup](#setup)
+ * [Troubleshoot](#troubleshoot)
+ * [No device found issue](#no-device-found-issue)
+ * [Diagnostic Activity](#diagnostic-activity)
+ * [Other](#other)
+* [Links](#links)
+
+
+
+## Introduction
+
+[Flipper](https://fbflipper.com) is a powerful tool from Meta, which allow to inspect the running application details and states from your computer.
+
+Flipper is configured in the Element Android project to let the developers be able to:
+- inspect all the Realm databases content;
+- do layout inspection;
+- see the crash logs;
+- see the logcat;
+- see all the network requests;
+- see all the SharedPreferences;
+- take screenshots and record videos of the device;
+- and more!
+
+## Setup
+
+- Install Flipper on your computer. Follow instructions here: https://fbflipper.com/docs/getting-started/index/
+- Run the debug version of Element on an emulator or on a real device.
+
+### Troubleshoot
+
+#### No device found issue
+
+The configuration of the Flipper application has to be updated. The issue has been asked and answered here: https://stackoverflow.com/questions/71744103/android-emulator-unable-to-connect-to-flipper/72608113#72608113
+
+#### Diagnostic Activity
+
+Flipper comes with a Diagnostic Activity that you can start from command line using:
+
+```shell
+adb shell am start -n im.vector.app.debug/com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity
+```
+
+It provides some log which can help to figure out what's going on client side.
+
+#### Other
+
+https://fbflipper.com/docs/getting-started/troubleshooting/android/ may help.
+
+## Links
+
+- Official Flipper website: https://fbflipper.com
+- Realm Plugin for Flipper: https://github.com/kamgurgul/Flipper-Realm
+- Dedicated Matrix room: https://matrix.to/#/#unifiedpush:matrix.org
diff --git a/docs/pull_request.md b/docs/pull_request.md
index d2d2bb7a3b..eebf2814a9 100644
--- a/docs/pull_request.md
+++ b/docs/pull_request.md
@@ -83,15 +83,16 @@ Exceptions can occur:
##### PR Review Assignment
-We use automatic assignment for PR reviews. A PR is automatically routed by GitHub to 2 team members using the round robin algorithm. The process is the following:
+We use automatic assignment for PR reviews. **A PR is automatically routed by GitHub to one team member** using the round robin algorithm. Additional reviewers can be used for complex changes or when the first reviewer is not confident enough on the changes.
+The process is the following:
-- The PR creator can assign specific people if they have another Android developer in their team or they think a specific reviewer should take a look at the PR.
-- If there are missing reviewers, the PR creator assigns the [element-android-reviewers](https://github.com/orgs/vector-im/teams/element-android-reviewers) team as a reviewer.
-- GitHub automatically assigns other reviewers. If one of the chosen reviewers is not available (holiday, etc.), remove them and set again the team, GitHub will select another reviewer.
+- The PR creator selects the [element-android-reviewers](https://github.com/orgs/vector-im/teams/element-android-reviewers) team as a reviewer.
+- GitHub automatically assign the reviewer. If the reviewer is not available (holiday, etc.), remove them and set again the team, GitHub will select another reviewer.
+- Alternatively, the PR creator can directly assign specific people if they have another Android developer in their team or they think a specific reviewer should take a look at their PR.
- Reviewers get a notification to make the review: they review the code following the good practice (see the rest of this document).
- After making their own review, if they feel not confident enough, they can ask another person for a full review, or they can tag someone within a PR comment to check specific lines.
-For PRs coming from the community, the issue wrangler can assign either the team [element-android-reviewers](https://github.com/orgs/vector-im/teams/element-android-reviewers) or any members directly.
+For PRs coming from the community, the issue wrangler can assign either the team [element-android-reviewers](https://github.com/orgs/vector-im/teams/element-android-reviewers) or any member directly.
##### PR review time
@@ -102,6 +103,7 @@ Some tips to achieve it:
- Set up your GH notifications correctly
- Check your pulls page: [https://github.com/pulls](https://github.com/pulls)
- Check your pending assigned PRs before starting or resuming your day to day tasks
+- If you are busy with high priority tasks, inform the author. They will find another developer
It is hard to define a deadline for a review. It depends on the PR size and the complexity. Let's start with a goal of 24h (working day!) for a PR smaller than 500 lines. If bigger, the submitter and the reviewer should discuss.
diff --git a/docs/unifiedpush.md b/docs/unifiedpush.md
new file mode 100644
index 0000000000..2851644e66
--- /dev/null
+++ b/docs/unifiedpush.md
@@ -0,0 +1,58 @@
+# UnifiedPush
+
+
+
+* [Introduction](#introduction)
+* [Configuration in Element-Android and their forks](#configuration-in-element-android-and-their-forks)
+ * [Enabling and disabling the feature](#enabling-and-disabling-the-feature)
+ * [Override the configuration at runtime](#override-the-configuration-at-runtime)
+ * [Enabling the feature](#enabling-the-feature)
+ * [Disabling the feature](#disabling-the-feature)
+ * [Useful links](#useful-links)
+
+
+
+## Introduction
+
+The recently started UnifiedPush project is an Android protocol and library for apps to be able to receive distributor-agnostic push notifications.
+
+The *F-Droid* and *Gplay* flavors of Element Android support UnifiedPush, so the user can use any distributor installed on their devices. This would make it possible to have push notifications without depending on Google services or libraries. Currently, the main distributors are [ntfy](https://ntfy.sh) which does not require any setup (like manual registration) to use the public server and [NextPush](https://github.com/UP-NextPush/android), available as a nextcloud application.
+
+The *Gplay* variant uses a UnifiedPush library which basically embed a FCM distributor built into the application (so a user doesn't need to do anything other than install the app to get FCM notifications). This variant uses Google Services to receive notifications if the user has not installed any distributor.
+
+The *F-Droid* variant does not use this library to avoid any proprietary blob. It will use a polling service if the user has not installed any distributor.
+
+In all cases, if there are other distributors available, the user will have to opt-in to one of them in the preferences.
+
+## Configuration in Element-Android and their forks
+
+### Enabling and disabling the feature
+
+Allowing the user to use an alternative distributor can be changed in [Config](../vector-config/src/main/java/im/vector/app/config/Config.kt). The flag is named `ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS`. Default value is `true`.
+
+#### Override the configuration at runtime
+
+On debug version, it is possible to override this configuration at runtime, using the `Feature` screen. The Feature is named `Allow external UnifiedPush distributors`.
+
+#### Enabling the feature
+
+This is the default behavior of Element Android.
+
+If `ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS` is set to true, it allows any available external UnifiedPush distributor to be chosen by the user.
+- For Gplay variant it means that FCM will be used by default, but user can choose another UnifiedPush distributor;
+- For F-Droid variant, it means that background polling will be used by default, but user can choose another UnifiedPush distributor.
+- On the UI, the setting to choose an alternative distributor will be visible to the user, and some tests in the notification troubleshoot screen will shown.
+- For F-Droid, if the user has chosen a distributor, the settings to configure the background polling will be hidden.
+
+#### Disabling the feature
+
+If `ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS` is set to false, it prevents the usage of external UnifiedPush distributors.
+- For Gplay variant it means that only FCM will be used;
+- For F-Droid variant, it means that only background polling will be used.
+- On the UI, the setting to choose an alternative distributor will be hidden to the user, and some tests in the notification troubleshoot screen will be hidden.
+
+### Useful links
+
+- UnifiedPush official website: [https://unifiedpush.org/](https://unifiedpush.org/)
+- List of available distributors can be retrieved here: [https://unifiedpush.org/users/distributors/](https://unifiedpush.org/users/distributors/)
+- UnifiedPush project discussion can occurs here: [#unifiedpush:matrix.org](https://matrix.to/#/#unifiedpush:matrix.org)
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104160.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104160.txt
new file mode 100644
index 0000000000..922d4dc76b
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Vylepšena správa šifrovaných zpráv. Opravy různých chyb a vylepšení stability.
+Úplný seznam změn: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104180.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104180.txt
new file mode 100644
index 0000000000..578549ce6c
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40104180.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability.
+Úplný seznam změn: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104190.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104190.txt
new file mode 100644
index 0000000000..578549ce6c
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40104190.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability.
+Úplný seznam změn: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104200.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104200.txt
new file mode 100644
index 0000000000..578549ce6c
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40104200.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability.
+Úplný seznam změn: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40104220.txt b/fastlane/metadata/android/en-US/changelogs/40104220.txt
new file mode 100644
index 0000000000..61db61727a
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40104220.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Various bug fixes and stability improvements.
+Full changelog: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40104230.txt b/fastlane/metadata/android/en-US/changelogs/40104230.txt
new file mode 100644
index 0000000000..61db61727a
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40104230.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Various bug fixes and stability improvements.
+Full changelog: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40104240.txt b/fastlane/metadata/android/en-US/changelogs/40104240.txt
new file mode 100644
index 0000000000..61db61727a
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40104240.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Various bug fixes and stability improvements.
+Full changelog: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40104250.txt b/fastlane/metadata/android/en-US/changelogs/40104250.txt
new file mode 100644
index 0000000000..61db61727a
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40104250.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Various bug fixes and stability improvements.
+Full changelog: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40104260.txt b/fastlane/metadata/android/en-US/changelogs/40104260.txt
new file mode 100644
index 0000000000..8808866c5d
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40104260.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Use UnifiedPush and allows user to have push without FCM.
+Full changelog: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40104270.txt b/fastlane/metadata/android/en-US/changelogs/40104270.txt
new file mode 100644
index 0000000000..61db61727a
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40104270.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Various bug fixes and stability improvements.
+Full changelog: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/et/changelogs/40104160.txt b/fastlane/metadata/android/et/changelogs/40104160.txt
new file mode 100644
index 0000000000..aa5a341dd3
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: krüptitud sõnumite parem haldus, lisaks pisiparandused ja stabiilsust parandavad kohendused.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/et/changelogs/40104180.txt b/fastlane/metadata/android/et/changelogs/40104180.txt
new file mode 100644
index 0000000000..1df5ac4176
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40104180.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/et/changelogs/40104190.txt b/fastlane/metadata/android/et/changelogs/40104190.txt
new file mode 100644
index 0000000000..1df5ac4176
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40104190.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/et/changelogs/40104200.txt b/fastlane/metadata/android/et/changelogs/40104200.txt
new file mode 100644
index 0000000000..1df5ac4176
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40104200.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/fa/changelogs/40104160.txt b/fastlane/metadata/android/fa/changelogs/40104160.txt
new file mode 100644
index 0000000000..1687ba2419
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+تغییرات عمده در این نگارش: مدیریت بهتر پیامهای رمزگذاشته. رفع اشکالهای مختلف و بهبودهای پایداری.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/fa/changelogs/40104180.txt b/fastlane/metadata/android/fa/changelogs/40104180.txt
new file mode 100644
index 0000000000..29efb95925
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40104180.txt
@@ -0,0 +1,2 @@
+تغییرات عمده در این نگارش: رفع اشکالهای مختلف و بهبودهای پایداری.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/fa/changelogs/40104190.txt b/fastlane/metadata/android/fa/changelogs/40104190.txt
new file mode 100644
index 0000000000..29efb95925
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40104190.txt
@@ -0,0 +1,2 @@
+تغییرات عمده در این نگارش: رفع اشکالهای مختلف و بهبودهای پایداری.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/fa/changelogs/40104200.txt b/fastlane/metadata/android/fa/changelogs/40104200.txt
new file mode 100644
index 0000000000..29efb95925
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40104200.txt
@@ -0,0 +1,2 @@
+تغییرات عمده در این نگارش: رفع اشکالهای مختلف و بهبودهای پایداری.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104160.txt b/fastlane/metadata/android/fr-FR/changelogs/40104160.txt
new file mode 100644
index 0000000000..6a19c6ea39
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Meilleure gestion des messages chiffrés. Plusieurs corrections de bogues et d’améliorations de stabilité.
+Intégralité des changements : https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104180.txt b/fastlane/metadata/android/fr-FR/changelogs/40104180.txt
new file mode 100644
index 0000000000..fe61fd021c
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40104180.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Plusieurs corrections de bogues et d’améliorations de stabilité.
+Intégralité des changements : https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104190.txt b/fastlane/metadata/android/fr-FR/changelogs/40104190.txt
new file mode 100644
index 0000000000..fe61fd021c
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40104190.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Plusieurs corrections de bogues et d’améliorations de stabilité.
+Intégralité des changements : https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104200.txt b/fastlane/metadata/android/fr-FR/changelogs/40104200.txt
new file mode 100644
index 0000000000..fe61fd021c
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40104200.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Plusieurs corrections de bogues et d’améliorations de stabilité.
+Intégralité des changements : https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/id/changelogs/40104160.txt b/fastlane/metadata/android/id/changelogs/40104160.txt
new file mode 100644
index 0000000000..8f248ffed4
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Pengelolaan pesan terenkripsi lebih baik. Banyak perbaikan kutu dan perbaikan stabilitas.
+Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/id/changelogs/40104180.txt b/fastlane/metadata/android/id/changelogs/40104180.txt
new file mode 100644
index 0000000000..1017951d47
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40104180.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas.
+Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/id/changelogs/40104190.txt b/fastlane/metadata/android/id/changelogs/40104190.txt
new file mode 100644
index 0000000000..1017951d47
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40104190.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas.
+Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/id/changelogs/40104200.txt b/fastlane/metadata/android/id/changelogs/40104200.txt
new file mode 100644
index 0000000000..1017951d47
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40104200.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas.
+Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/it-IT/changelogs/40104160.txt b/fastlane/metadata/android/it-IT/changelogs/40104160.txt
new file mode 100644
index 0000000000..943a42de99
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: migliorata la gestione dei messaggi cifrati. Varie correzioni e miglioramenti della stabilità.
+Cronologia completa: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/it-IT/changelogs/40104180.txt b/fastlane/metadata/android/it-IT/changelogs/40104180.txt
new file mode 100644
index 0000000000..556a6fc7ea
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40104180.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità.
+Cronologia completa: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/it-IT/changelogs/40104190.txt b/fastlane/metadata/android/it-IT/changelogs/40104190.txt
new file mode 100644
index 0000000000..556a6fc7ea
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40104190.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità.
+Cronologia completa: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/it-IT/changelogs/40104200.txt b/fastlane/metadata/android/it-IT/changelogs/40104200.txt
new file mode 100644
index 0000000000..556a6fc7ea
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40104200.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità.
+Cronologia completa: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/iw-IL/title.txt b/fastlane/metadata/android/iw-IL/title.txt
index d8849a5023..56ae517696 100644
--- a/fastlane/metadata/android/iw-IL/title.txt
+++ b/fastlane/metadata/android/iw-IL/title.txt
@@ -1 +1 @@
-אלמנט (בעבר Riot.im)
+אלמנט - התכתבות מאובטחת
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101060.txt b/fastlane/metadata/android/pl-PL/changelogs/40101060.txt
new file mode 100644
index 0000000000..17af495632
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40101060.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wesji: poprawki dla wesji 1.1.5
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.6
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101070.txt b/fastlane/metadata/android/pl-PL/changelogs/40101070.txt
new file mode 100644
index 0000000000..2959ba88e0
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Eksperymentalne wsparcie dla przestrzeni, Kompresowanie video przed wysłaniem.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101080.txt b/fastlane/metadata/android/pl-PL/changelogs/40101080.txt
new file mode 100644
index 0000000000..95f77a0f25
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40101080.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Poprawki w przestrzeniach
+Pełna lista zmian https://github.com/vector-im/element-android/releases/tag/v1.1.8
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101090.txt b/fastlane/metadata/android/pl-PL/changelogs/40101090.txt
new file mode 100644
index 0000000000..0bc111fa70
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40101090.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Dodano wsparcie dla sieci gitter.im .
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.9
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101100.txt b/fastlane/metadata/android/pl-PL/changelogs/40101100.txt
new file mode 100644
index 0000000000..2eace7771d
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40101100.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Nowe funkcje dla przestrzeni i aktualizacja motywu i stylu.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.10
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101110.txt b/fastlane/metadata/android/pl-PL/changelogs/40101110.txt
new file mode 100644
index 0000000000..5afc3ca5a7
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40101110.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Dodano nowe funkcje do przestrzeni i zaktualizowano motyw i styl aplikacji. (poprawki błędóœ dla wesji 1.1.10)
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.11
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40104160.txt b/fastlane/metadata/android/pl-PL/changelogs/40104160.txt
new file mode 100644
index 0000000000..104ed45352
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Lepsze zarządzanie zaszyfrowanymi wiadomościami. , Poprawki błędów i stabilności.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104160.txt b/fastlane/metadata/android/pt-BR/changelogs/40104160.txt
new file mode 100644
index 0000000000..eec5dca30f
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Melhor gerenciamento de mensagens encriptadas. Vários consertos de bugs e melhorias de estabilidade.
+Changelog completo: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104180.txt b/fastlane/metadata/android/pt-BR/changelogs/40104180.txt
new file mode 100644
index 0000000000..6e11e92579
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40104180.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Vários consertos de bugs e melhorias de estabilidade.
+Changelog completo: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104190.txt b/fastlane/metadata/android/pt-BR/changelogs/40104190.txt
new file mode 100644
index 0000000000..6e11e92579
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40104190.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Vários consertos de bugs e melhorias de estabilidade.
+Changelog completo: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104200.txt b/fastlane/metadata/android/pt-BR/changelogs/40104200.txt
new file mode 100644
index 0000000000..6e11e92579
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40104200.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Vários consertos de bugs e melhorias de estabilidade.
+Changelog completo: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/sk/changelogs/40104160.txt b/fastlane/metadata/android/sk/changelogs/40104160.txt
new file mode 100644
index 0000000000..e6e2f45c32
--- /dev/null
+++ b/fastlane/metadata/android/sk/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+Hlavné zmeny v tejto verzii: Lepšia spravovanie zašifrovaných správ. Rôzne opravy chýb a vylepšenia stability.
+Úplný zoznam zmien: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/sk/changelogs/40104180.txt b/fastlane/metadata/android/sk/changelogs/40104180.txt
new file mode 100644
index 0000000000..50670f18c2
--- /dev/null
+++ b/fastlane/metadata/android/sk/changelogs/40104180.txt
@@ -0,0 +1,2 @@
+Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability.
+Úplný zoznam zmien: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/sk/changelogs/40104190.txt b/fastlane/metadata/android/sk/changelogs/40104190.txt
new file mode 100644
index 0000000000..50670f18c2
--- /dev/null
+++ b/fastlane/metadata/android/sk/changelogs/40104190.txt
@@ -0,0 +1,2 @@
+Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability.
+Úplný zoznam zmien: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/sk/changelogs/40104200.txt b/fastlane/metadata/android/sk/changelogs/40104200.txt
new file mode 100644
index 0000000000..50670f18c2
--- /dev/null
+++ b/fastlane/metadata/android/sk/changelogs/40104200.txt
@@ -0,0 +1,2 @@
+Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability.
+Úplný zoznam zmien: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104160.txt b/fastlane/metadata/android/sv-SE/changelogs/40104160.txt
new file mode 100644
index 0000000000..cf7eda6ef8
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Bättre hantering av krypterade meddelanden. Diverse buggfixar och stabilitetsförbättringar.
+Full ändringslogg: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104180.txt b/fastlane/metadata/android/sv-SE/changelogs/40104180.txt
new file mode 100644
index 0000000000..d8db452b51
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40104180.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Diverse buggfixar och stabilitetsförbättringar.
+Full ändringslogg: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104190.txt b/fastlane/metadata/android/sv-SE/changelogs/40104190.txt
new file mode 100644
index 0000000000..d8db452b51
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40104190.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Diverse buggfixar och stabilitetsförbättringar.
+Full ändringslogg: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104200.txt b/fastlane/metadata/android/sv-SE/changelogs/40104200.txt
new file mode 100644
index 0000000000..d8db452b51
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40104200.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Diverse buggfixar och stabilitetsförbättringar.
+Full ändringslogg: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/uk/changelogs/40104000.txt b/fastlane/metadata/android/uk/changelogs/40104000.txt
index 6abfdcf929..b4203b0e3f 100644
--- a/fastlane/metadata/android/uk/changelogs/40104000.txt
+++ b/fastlane/metadata/android/uk/changelogs/40104000.txt
@@ -1,2 +1,2 @@
-Основні зміни в цій версії: Початкова реалізація тредів повідомлень. Повідомлення бульбашки.
+Основні зміни в цій версії: Початкова реалізація гілок повідомлень. Повідомлення бульбашки.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.4.0
diff --git a/fastlane/metadata/android/uk/changelogs/40104060.txt b/fastlane/metadata/android/uk/changelogs/40104060.txt
index 28f051724a..a5dac44be2 100644
--- a/fastlane/metadata/android/uk/changelogs/40104060.txt
+++ b/fastlane/metadata/android/uk/changelogs/40104060.txt
@@ -1,2 +1,2 @@
-Основні зміни в цій версії: Хронологія тредів працює наживо і швидше. Усунуто різні вади й поліпшено стабільність.
+Основні зміни в цій версії: Хронологія гілок працює наживо і швидше. Усунуто різні вади й поліпшено стабільність.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.4.6
diff --git a/fastlane/metadata/android/uk/changelogs/40104080.txt b/fastlane/metadata/android/uk/changelogs/40104080.txt
index e5f7e7b271..5155793561 100644
--- a/fastlane/metadata/android/uk/changelogs/40104080.txt
+++ b/fastlane/metadata/android/uk/changelogs/40104080.txt
@@ -1,2 +1,2 @@
-Основні зміни в цій версії: Хронологія тредів працює наживо і швидше. Усунуто різні вади й поліпшено стабільність.
+Основні зміни в цій версії: Хронологія гілок працює наживо і швидше. Усунуто різні вади й поліпшено стабільність.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/uk/changelogs/40104160.txt b/fastlane/metadata/android/uk/changelogs/40104160.txt
new file mode 100644
index 0000000000..33ad65f75c
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: Поліпшено керування зашифрованими повідомленнями. Усунуто різні вади й поліпшено стабільність.
+Вичерпний перелік змін: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/uk/changelogs/40104180.txt b/fastlane/metadata/android/uk/changelogs/40104180.txt
new file mode 100644
index 0000000000..252a57c9d9
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40104180.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність.
+Вичерпний перелік змін: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/uk/changelogs/40104190.txt b/fastlane/metadata/android/uk/changelogs/40104190.txt
new file mode 100644
index 0000000000..252a57c9d9
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40104190.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність.
+Вичерпний перелік змін: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/uk/changelogs/40104200.txt b/fastlane/metadata/android/uk/changelogs/40104200.txt
new file mode 100644
index 0000000000..252a57c9d9
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40104200.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність.
+Вичерпний перелік змін: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104160.txt b/fastlane/metadata/android/zh-TW/changelogs/40104160.txt
new file mode 100644
index 0000000000..0e64d36868
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40104160.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:對於被加密的訊息有更好的管理方式。多個臭蟲修復與穩定性改善。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104180.txt b/fastlane/metadata/android/zh-TW/changelogs/40104180.txt
new file mode 100644
index 0000000000..4bcca9a0b8
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40104180.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:多個臭蟲修復與穩定性改善。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104190.txt b/fastlane/metadata/android/zh-TW/changelogs/40104190.txt
new file mode 100644
index 0000000000..4bcca9a0b8
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40104190.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:多個臭蟲修復與穩定性改善。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104200.txt b/fastlane/metadata/android/zh-TW/changelogs/40104200.txt
new file mode 100644
index 0000000000..4bcca9a0b8
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40104200.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:多個臭蟲修復與穩定性改善。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases
diff --git a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt
index 21af114c26..764cf8419a 100644
--- a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt
+++ b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt
@@ -271,7 +271,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
directionDetector.handleTouchEvent(event)
return when (swipeDirection) {
- SwipeDirection.Up, SwipeDirection.Down -> {
+ SwipeDirection.Up, SwipeDirection.Down -> {
if (isSwipeToDismissAllowed && !wasScaled && isImagePagerIdle) {
swipeDismissHandler.onTouch(views.rootContainer, event)
} else true
@@ -279,7 +279,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
SwipeDirection.Left, SwipeDirection.Right -> {
views.attachmentPager.dispatchTouchEvent(event)
}
- else -> true
+ else -> true
}
}
diff --git a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentsAdapter.kt b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentsAdapter.kt
index 4805a1186b..77ddb27c63 100644
--- a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentsAdapter.kt
+++ b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentsAdapter.kt
@@ -42,18 +42,18 @@ class AttachmentsAdapter : RecyclerView.Adapter() {
val inflater = LayoutInflater.from(parent.context)
val itemView = inflater.inflate(viewType, parent, false)
return when (viewType) {
- R.layout.item_image_attachment -> ZoomableImageViewHolder(itemView)
+ R.layout.item_image_attachment -> ZoomableImageViewHolder(itemView)
R.layout.item_animated_image_attachment -> AnimatedImageViewHolder(itemView)
- R.layout.item_video_attachment -> VideoViewHolder(itemView)
- else -> UnsupportedViewHolder(itemView)
+ R.layout.item_video_attachment -> VideoViewHolder(itemView)
+ else -> UnsupportedViewHolder(itemView)
}
}
override fun getItemViewType(position: Int): Int {
val info = attachmentSourceProvider!!.getAttachmentInfoAt(position)
return when (info) {
- is AttachmentInfo.Image -> R.layout.item_image_attachment
- is AttachmentInfo.Video -> R.layout.item_video_attachment
+ is AttachmentInfo.Image -> R.layout.item_image_attachment
+ is AttachmentInfo.Video -> R.layout.item_video_attachment
is AttachmentInfo.AnimatedImage -> R.layout.item_animated_image_attachment
// is AttachmentInfo.Audio -> TODO()
// is AttachmentInfo.File -> TODO()
@@ -68,13 +68,13 @@ class AttachmentsAdapter : RecyclerView.Adapter() {
attachmentSourceProvider?.getAttachmentInfoAt(position)?.let {
holder.bind(it)
when (it) {
- is AttachmentInfo.Image -> {
+ is AttachmentInfo.Image -> {
attachmentSourceProvider?.loadImage((holder as ZoomableImageViewHolder).target, it)
}
is AttachmentInfo.AnimatedImage -> {
attachmentSourceProvider?.loadImage((holder as AnimatedImageViewHolder).target, it)
}
- is AttachmentInfo.Video -> {
+ is AttachmentInfo.Video -> {
attachmentSourceProvider?.loadVideo((holder as VideoViewHolder).target, it)
}
// else -> {
diff --git a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeDirection.kt b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeDirection.kt
index 7948f37ae8..7816a5a2cc 100644
--- a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeDirection.kt
+++ b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeDirection.kt
@@ -27,12 +27,12 @@ sealed class SwipeDirection {
companion object {
fun fromAngle(angle: Double): SwipeDirection {
return when (angle) {
- in 0.0..45.0 -> Right
- in 45.0..135.0 -> Up
+ in 0.0..45.0 -> Right
+ in 45.0..135.0 -> Up
in 135.0..225.0 -> Left
in 225.0..315.0 -> Down
in 315.0..360.0 -> Right
- else -> NotDetected
+ else -> NotDetected
}
}
}
diff --git a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeDirectionDetector.kt b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeDirectionDetector.kt
index 6575248b2d..7b72637c06 100644
--- a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeDirectionDetector.kt
+++ b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeDirectionDetector.kt
@@ -33,7 +33,7 @@ class SwipeDirectionDetector(
fun handleTouchEvent(event: MotionEvent) {
when (event.action) {
- MotionEvent.ACTION_DOWN -> {
+ MotionEvent.ACTION_DOWN -> {
startX = event.x
startY = event.y
}
@@ -45,7 +45,7 @@ class SwipeDirectionDetector(
startX = startY
isDetected = false
}
- MotionEvent.ACTION_MOVE -> if (!isDetected && getEventDistance(event) > touchSlop) {
+ MotionEvent.ACTION_MOVE -> if (!isDetected && getEventDistance(event) > touchSlop) {
isDetected = true
onDirectionDetected(getDirection(startX, startY, event.x, event.y))
}
diff --git a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeToDismissHandler.kt b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeToDismissHandler.kt
index ca2c28b498..7a83ee28d4 100644
--- a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeToDismissHandler.kt
+++ b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeToDismissHandler.kt
@@ -44,7 +44,7 @@ class SwipeToDismissHandler(
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View, event: MotionEvent): Boolean {
when (event.action) {
- MotionEvent.ACTION_DOWN -> {
+ MotionEvent.ACTION_DOWN -> {
if (swipeView.hitRect.contains(event.x.toInt(), event.y.toInt())) {
isTracking = true
}
@@ -58,7 +58,7 @@ class SwipeToDismissHandler(
}
return true
}
- MotionEvent.ACTION_MOVE -> {
+ MotionEvent.ACTION_MOVE -> {
if (isTracking) {
val translationY = event.y - startY
swipeView.translationY = translationY
@@ -66,7 +66,7 @@ class SwipeToDismissHandler(
}
return true
}
- else -> {
+ else -> {
return false
}
}
@@ -79,8 +79,8 @@ class SwipeToDismissHandler(
private fun onTrackingEnd(parentHeight: Int) {
val animateTo = when {
swipeView.translationY < -translationLimit -> -parentHeight.toFloat()
- swipeView.translationY > translationLimit -> parentHeight.toFloat()
- else -> 0f
+ swipeView.translationY > translationLimit -> parentHeight.toFloat()
+ else -> 0f
}
if (animateTo != 0f && !shouldAnimateDismiss()) {
diff --git a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoViewHolder.kt b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoViewHolder.kt
index 12213a8786..92d28d26c9 100644
--- a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoViewHolder.kt
+++ b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/VideoViewHolder.kt
@@ -146,7 +146,7 @@ class VideoViewHolder constructor(itemView: View) :
wasPaused = true
views.videoView.pause()
}
- is AttachmentCommands.SeekTo -> {
+ is AttachmentCommands.SeekTo -> {
val duration = views.videoView.duration
if (duration > 0) {
val seekDuration = duration * (commands.percentProgress / 100f)
diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt
index 9f8093f801..24b9f2ec26 100644
--- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt
+++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt
@@ -43,7 +43,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
text(async.error.localizedMessage?.toEpoxyCharSequence())
}
}
- else -> {
+ else -> {
async.invoke()?.let {
buildRec(it, 0, "")
}
@@ -98,7 +98,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
}
}
}
- is JSonViewerArray -> {
+ is JSonViewerArray -> {
if (model.isExpanded) {
open(id, model.key, model.index, depth, false, model)
model.items.forEach {
@@ -137,7 +137,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
}
}
}
- is JSonViewerLeaf -> {
+ is JSonViewerLeaf -> {
valueItem {
id(id)
depth(depth)
@@ -172,12 +172,12 @@ internal class JSonViewerEpoxyController(private val context: Context) :
private fun valueToSpan(leaf: JSonViewerLeaf): Span {
val host = this
return when (leaf.type) {
- JSONType.STRING -> {
+ JSONType.STRING -> {
span("\"${leaf.stringRes}\"") {
textColor = host.styleProvider.stringColor
}
}
- JSONType.NUMBER -> {
+ JSONType.NUMBER -> {
span(leaf.stringRes) {
textColor = host.styleProvider.numberColor
}
@@ -187,7 +187,7 @@ internal class JSonViewerEpoxyController(private val context: Context) :
textColor = host.styleProvider.booleanColor
}
}
- JSONType.NULL -> {
+ JSONType.NULL -> {
span("null") {
textColor = host.styleProvider.booleanColor
}
diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt
index 6940e79e3f..2492b5454c 100644
--- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt
+++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt
@@ -82,7 +82,7 @@ internal object ModelParser {
}
parent.addChild(objectComposed)
}
- is JSONArray -> {
+ is JSONArray -> {
val objectComposed = JSonViewerArray(key, index, obj)
.apply { isExpanded = initialOpenDepth == -1 || depth <= initialOpenDepth }
objectComposed.depth = depth
@@ -91,25 +91,25 @@ internal object ModelParser {
}
parent.addChild(objectComposed)
}
- is String -> {
+ is String -> {
JSonViewerLeaf(key, index, obj, JSONType.STRING).let {
it.depth = depth
parent.addChild(it)
}
}
- is Number -> {
+ is Number -> {
JSonViewerLeaf(key, index, obj.toString(), JSONType.NUMBER).let {
it.depth = depth
parent.addChild(it)
}
}
- is Boolean -> {
+ is Boolean -> {
JSonViewerLeaf(key, index, obj.toString(), JSONType.BOOLEAN).let {
it.depth = depth
parent.addChild(it)
}
}
- else -> {
+ else -> {
if (obj == JSONObject.NULL) {
JSonViewerLeaf(key, index, "null", JSONType.NULL).let {
it.depth = depth
diff --git a/library/multipicker/src/main/java/im/vector/lib/multipicker/FilePicker.kt b/library/multipicker/src/main/java/im/vector/lib/multipicker/FilePicker.kt
index 13ef5aa637..928fdf894c 100644
--- a/library/multipicker/src/main/java/im/vector/lib/multipicker/FilePicker.kt
+++ b/library/multipicker/src/main/java/im/vector/lib/multipicker/FilePicker.kt
@@ -48,7 +48,7 @@ class FilePicker : Picker() {
type.isMimeTypeVideo() -> selectedUri.toMultiPickerVideoType(context)
type.isMimeTypeImage() -> selectedUri.toMultiPickerImageType(context)
type.isMimeTypeAudio() -> selectedUri.toMultiPickerAudioType(context)
- else -> {
+ else -> {
// Other files
context.contentResolver.query(selectedUri, null, null, null, null)
?.use { cursor ->
diff --git a/library/multipicker/src/main/java/im/vector/lib/multipicker/MultiPicker.kt b/library/multipicker/src/main/java/im/vector/lib/multipicker/MultiPicker.kt
index e7883c9e53..9377345886 100644
--- a/library/multipicker/src/main/java/im/vector/lib/multipicker/MultiPicker.kt
+++ b/library/multipicker/src/main/java/im/vector/lib/multipicker/MultiPicker.kt
@@ -31,15 +31,15 @@ class MultiPicker private constructor() {
@Suppress("UNCHECKED_CAST")
fun get(type: MultiPicker): T {
return when (type) {
- IMAGE -> ImagePicker() as T
- VIDEO -> VideoPicker() as T
- MEDIA -> MediaPicker() as T
- FILE -> FilePicker() as T
- AUDIO -> AudioPicker() as T
- CONTACT -> ContactPicker() as T
- CAMERA -> CameraPicker() as T
+ IMAGE -> ImagePicker() as T
+ VIDEO -> VideoPicker() as T
+ MEDIA -> MediaPicker() as T
+ FILE -> FilePicker() as T
+ AUDIO -> AudioPicker() as T
+ CONTACT -> ContactPicker() as T
+ CAMERA -> CameraPicker() as T
CAMERA_VIDEO -> CameraVideoPicker() as T
- else -> throw IllegalArgumentException("Unsupported type $type")
+ else -> throw IllegalArgumentException("Unsupported type $type")
}
}
}
diff --git a/library/opusencoder/.gitignore b/library/opusencoder/.gitignore
new file mode 100644
index 0000000000..ff535c85f5
--- /dev/null
+++ b/library/opusencoder/.gitignore
@@ -0,0 +1,10 @@
+*.iml
+.gradle
+/local.properties
+/.idea
+.DS_Store
+/build
+/captures
+*.cxx
+app/.cxx/*
+.externalNativeBuild
\ No newline at end of file
diff --git a/library/opusencoder/build.gradle b/library/opusencoder/build.gradle
new file mode 100644
index 0000000000..a825bb98bc
--- /dev/null
+++ b/library/opusencoder/build.gradle
@@ -0,0 +1,40 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+android {
+ ndkVersion "21.3.6528147"
+
+ compileSdkVersion 31
+
+ buildToolsVersion "31.0.0"
+
+ defaultConfig {
+ minSdkVersion 18
+ targetSdkVersion 31
+ versionCode 1
+ versionName "1.0"
+
+ externalNativeBuild {
+ ndk {
+ abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
+ }
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ externalNativeBuild {
+ cmake {
+ path "src/main/cpp/CMakeLists.txt"
+ }
+ }
+}
+
+dependencies {
+ implementation libs.androidx.annotation
+}
diff --git a/library/opusencoder/src/main/AndroidManifest.xml b/library/opusencoder/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..4dd3413820
--- /dev/null
+++ b/library/opusencoder/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/library/opusencoder/src/main/cpp/CMakeLists.txt b/library/opusencoder/src/main/cpp/CMakeLists.txt
new file mode 100644
index 0000000000..c261af8b90
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/CMakeLists.txt
@@ -0,0 +1,61 @@
+# For more information about using CMake with Android Studio, read the
+# documentation: https://d.android.com/studio/projects/add-native-code.html
+
+# Sets the minimum version of CMake required to build the native library.
+
+cmake_minimum_required(VERSION 3.4.1)
+set(CMAKE_CXX_STANDARD 14)
+
+# Creates and names a library, sets it as either STATIC
+# or SHARED, and provides the relative paths to its source code.
+# You can define multiple libraries, and CMake builds them for you.
+# Gradle automatically packages shared libraries with your APK.
+
+set(distribution_OPUS_DIR ${CMAKE_SOURCE_DIR}/opus)
+
+add_library(lib_opus SHARED IMPORTED)
+set_target_properties(lib_opus PROPERTIES IMPORTED_LOCATION
+ ${distribution_OPUS_DIR}/libs/${ANDROID_ABI}/libopus.so)
+
+add_library(lib_opusenc SHARED IMPORTED)
+set_target_properties(lib_opusenc PROPERTIES IMPORTED_LOCATION
+ ${distribution_OPUS_DIR}/libs/${ANDROID_ABI}/libopusenc.so)
+
+add_library( # Sets the name of the library.
+ opuscodec
+
+ # Sets the library as a shared library.
+ SHARED
+
+ # Provides a relative path to your source file(s).
+ codec/CodecOggOpus.cpp
+ opuscodec.cpp)
+
+target_include_directories(opuscodec PRIVATE
+ ${distribution_OPUS_DIR}/include)
+
+# Searches for a specified prebuilt library and stores the path as a
+# variable. Because CMake includes system libraries in the search path by
+# default, you only need to specify the name of the public NDK library
+# you want to add. CMake verifies that the library exists before
+# completing its build.
+
+find_library( # Sets the name of the path variable.
+ log-lib
+
+ # Specifies the name of the NDK library that
+ # you want CMake to locate.
+ log )
+
+# Specifies libraries CMake should link to your target library. You
+# can link multiple libraries, such as libraries you define in this
+# build script, prebuilt third-party libraries, or system libraries.
+
+target_link_libraries( # Specifies the target library.
+ opuscodec
+ android
+ lib_opusenc
+ lib_opus
+ # Links the target library to the log library
+ # included in the NDK.
+ ${log-lib} )
diff --git a/library/opusencoder/src/main/cpp/codec/CodecOggOpus.cpp b/library/opusencoder/src/main/cpp/codec/CodecOggOpus.cpp
new file mode 100644
index 0000000000..d167c69cbf
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/codec/CodecOggOpus.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CodecOggOpus.h"
+#include "../utils/Logger.h"
+
+int ret;
+
+int CodecOggOpus::encoderInit(char* filePath, int sampleRate) {
+ // Create default, empty comment header
+ comments = ope_comments_create();
+ // Mono audio
+ int numChannels = 1;
+ // Channel Mapping Family 0, used for mono/stereo streams
+ int family = 0;
+ // Create encoder to encode PCM chunks and write the result to a file with the OggOpus framing
+ encoder = ope_encoder_create_file(filePath, comments, sampleRate, numChannels, family, &ret);
+ if (ret != OPE_OK) {
+ LOGE(TAG, "Creation of OggOpusEnc failed.");
+ return ret;
+ }
+ return OPE_OK;
+}
+
+int CodecOggOpus::setBitrate(int bitrate) {
+ ret = ope_encoder_ctl(encoder, OPUS_SET_BITRATE_REQUEST, bitrate);
+ if (ret != OPE_OK) {
+ LOGE(TAG, "Could not set bitrate.");
+ return ret;
+ }
+ return OPE_OK;
+}
+
+int CodecOggOpus::writeFrame(short* frame, int samplesPerChannel) {
+ // Encode the raw PCM-16 buffer to Opus and write it to the ogg file
+ return ope_encoder_write(encoder, frame, samplesPerChannel);
+}
+
+void CodecOggOpus::encoderRelease() {
+ // Finish any pending encode/write operations
+ ope_encoder_drain(encoder);
+ // De-init the encoder instance
+ ope_encoder_destroy(encoder);
+ // De-init the comment header struct
+ ope_comments_destroy(comments);
+}
+
+CodecOggOpus::~CodecOggOpus() {
+ encoderRelease();
+}
diff --git a/library/opusencoder/src/main/cpp/codec/CodecOggOpus.h b/library/opusencoder/src/main/cpp/codec/CodecOggOpus.h
new file mode 100644
index 0000000000..f1035434c5
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/codec/CodecOggOpus.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ELEMENT_ANDROID_CODECOGGOPUS_H
+#define ELEMENT_ANDROID_CODECOGGOPUS_H
+
+#include
+/**
+ * This class is a wrapper around libopusenc, used to encode and write Opus frames into an Ogg file.
+ *
+ * The usual flow would be:
+ *
+ * 1. Use encoderInit to initialize the internal encoder with the sample rate and the path to write the encoded frames to.
+ * 2. (Optional) set the bitrate to use.
+ * 3. While recording, read PCM-16 chunks from the recorder, feed them to the encoder using writeFrame.
+ * 4. When finished, call encoderRelease to free some resources.
+ */
+class CodecOggOpus {
+
+private:
+ const char *TAG = "CodecOggOpus";
+
+ OggOpusEnc* encoder;
+ OggOpusComments* comments;
+
+public:
+ int encoderInit(char* filePath, int sampleRate);
+
+ int setBitrate(int bitrate);
+
+ int writeFrame(short *frame, int samplesPerChannel);
+
+ void encoderRelease();
+
+ ~CodecOggOpus();
+};
+
+
+#endif //ELEMENT_ANDROID_CODECOGGOPUS_H
diff --git a/library/opusencoder/src/main/cpp/opus/include/opus.h b/library/opusencoder/src/main/cpp/opus/include/opus.h
new file mode 100644
index 0000000000..d282f21d25
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/opus/include/opus.h
@@ -0,0 +1,981 @@
+/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
+ Written by Jean-Marc Valin and Koen Vos */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file opus.h
+ * @brief Opus reference implementation API
+ */
+
+#ifndef OPUS_H
+#define OPUS_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @mainpage Opus
+ *
+ * The Opus codec is designed for interactive speech and audio transmission over the Internet.
+ * It is designed by the IETF Codec Working Group and incorporates technology from
+ * Skype's SILK codec and Xiph.Org's CELT codec.
+ *
+ * The Opus codec is designed to handle a wide range of interactive audio applications,
+ * including Voice over IP, videoconferencing, in-game chat, and even remote live music
+ * performances. It can scale from low bit-rate narrowband speech to very high quality
+ * stereo music. Its main features are:
+
+ * @li Sampling rates from 8 to 48 kHz
+ * @li Bit-rates from 6 kb/s to 510 kb/s
+ * @li Support for both constant bit-rate (CBR) and variable bit-rate (VBR)
+ * @li Audio bandwidth from narrowband to full-band
+ * @li Support for speech and music
+ * @li Support for mono and stereo
+ * @li Support for multichannel (up to 255 channels)
+ * @li Frame sizes from 2.5 ms to 60 ms
+ * @li Good loss robustness and packet loss concealment (PLC)
+ * @li Floating point and fixed-point implementation
+ *
+ * Documentation sections:
+ * @li @ref opus_encoder
+ * @li @ref opus_decoder
+ * @li @ref opus_repacketizer
+ * @li @ref opus_multistream
+ * @li @ref opus_libinfo
+ * @li @ref opus_custom
+ */
+
+/** @defgroup opus_encoder Opus Encoder
+ * @{
+ *
+ * @brief This page describes the process and functions used to encode Opus.
+ *
+ * Since Opus is a stateful codec, the encoding process starts with creating an encoder
+ * state. This can be done with:
+ *
+ * @code
+ * int error;
+ * OpusEncoder *enc;
+ * enc = opus_encoder_create(Fs, channels, application, &error);
+ * @endcode
+ *
+ * From this point, @c enc can be used for encoding an audio stream. An encoder state
+ * @b must @b not be used for more than one stream at the same time. Similarly, the encoder
+ * state @b must @b not be re-initialized for each frame.
+ *
+ * While opus_encoder_create() allocates memory for the state, it's also possible
+ * to initialize pre-allocated memory:
+ *
+ * @code
+ * int size;
+ * int error;
+ * OpusEncoder *enc;
+ * size = opus_encoder_get_size(channels);
+ * enc = malloc(size);
+ * error = opus_encoder_init(enc, Fs, channels, application);
+ * @endcode
+ *
+ * where opus_encoder_get_size() returns the required size for the encoder state. Note that
+ * future versions of this code may change the size, so no assuptions should be made about it.
+ *
+ * The encoder state is always continuous in memory and only a shallow copy is sufficient
+ * to copy it (e.g. memcpy())
+ *
+ * It is possible to change some of the encoder's settings using the opus_encoder_ctl()
+ * interface. All these settings already default to the recommended value, so they should
+ * only be changed when necessary. The most common settings one may want to change are:
+ *
+ * @code
+ * opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate));
+ * opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
+ * opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal_type));
+ * @endcode
+ *
+ * where
+ *
+ * @arg bitrate is in bits per second (b/s)
+ * @arg complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest
+ * @arg signal_type is either OPUS_AUTO (default), OPUS_SIGNAL_VOICE, or OPUS_SIGNAL_MUSIC
+ *
+ * See @ref opus_encoderctls and @ref opus_genericctls for a complete list of parameters that can be set or queried. Most parameters can be set or changed at any time during a stream.
+ *
+ * To encode a frame, opus_encode() or opus_encode_float() must be called with exactly one frame (2.5, 5, 10, 20, 40 or 60 ms) of audio data:
+ * @code
+ * len = opus_encode(enc, audio_frame, frame_size, packet, max_packet);
+ * @endcode
+ *
+ * where
+ *
+ * - audio_frame is the audio data in opus_int16 (or float for opus_encode_float())
+ * - frame_size is the duration of the frame in samples (per channel)
+ * - packet is the byte array to which the compressed data is written
+ * - max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended).
+ * Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.
+ *
+ *
+ * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet.
+ * The return value can be negative, which indicates that an error has occurred. If the return value
+ * is 2 bytes or less, then the packet does not need to be transmitted (DTX).
+ *
+ * Once the encoder state if no longer needed, it can be destroyed with
+ *
+ * @code
+ * opus_encoder_destroy(enc);
+ * @endcode
+ *
+ * If the encoder was created with opus_encoder_init() rather than opus_encoder_create(),
+ * then no action is required aside from potentially freeing the memory that was manually
+ * allocated for it (calling free(enc) for the example above)
+ *
+ */
+
+/** Opus encoder state.
+ * This contains the complete state of an Opus encoder.
+ * It is position independent and can be freely copied.
+ * @see opus_encoder_create,opus_encoder_init
+ */
+typedef struct OpusEncoder OpusEncoder;
+
+/** Gets the size of an OpusEncoder
structure.
+ * @param[in] channels int: Number of channels.
+ * This must be 1 or 2.
+ * @returns The size in bytes.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);
+
+/**
+ */
+
+/** Allocates and initializes an encoder state.
+ * There are three coding modes:
+ *
+ * @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice
+ * signals. It enhances the input signal by high-pass filtering and
+ * emphasizing formants and harmonics. Optionally it includes in-band
+ * forward error correction to protect against packet loss. Use this
+ * mode for typical VoIP applications. Because of the enhancement,
+ * even at high bitrates the output may sound different from the input.
+ *
+ * @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most
+ * non-voice signals like music. Use this mode for music and mixed
+ * (music/voice) content, broadcast, and applications requiring less
+ * than 15 ms of coding delay.
+ *
+ * @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that
+ * disables the speech-optimized mode in exchange for slightly reduced delay.
+ * This mode can only be set on an newly initialized or freshly reset encoder
+ * because it changes the codec delay.
+ *
+ * This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution).
+ * @param [in] Fs opus_int32: Sampling rate of input signal (Hz)
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param [in] channels int: Number of channels (1 or 2) in input signal
+ * @param [in] application int: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ * @param [out] error int*: @ref opus_errorcodes
+ * @note Regardless of the sampling rate and number channels selected, the Opus encoder
+ * can switch to a lower audio bandwidth or number of channels if the bitrate
+ * selected is too low. This also means that it is safe to always use 48 kHz stereo input
+ * and let the encoder optimize the encoding.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
+ opus_int32 Fs,
+ int channels,
+ int application,
+ int *error
+);
+
+/** Initializes a previously allocated encoder state
+ * The memory pointed to by st must be at least the size returned by opus_encoder_get_size().
+ * This is intended for applications which use their own allocator instead of malloc.
+ * @see opus_encoder_create(),opus_encoder_get_size()
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @param [in] st OpusEncoder*: Encoder state
+ * @param [in] Fs opus_int32: Sampling rate of input signal (Hz)
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param [in] channels int: Number of channels (1 or 2) in input signal
+ * @param [in] application int: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ * @retval #OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_EXPORT int opus_encoder_init(
+ OpusEncoder *st,
+ opus_int32 Fs,
+ int channels,
+ int application
+) OPUS_ARG_NONNULL(1);
+
+/** Encodes an Opus frame.
+ * @param [in] st OpusEncoder*: Encoder state
+ * @param [in] pcm opus_int16*: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16)
+ * @param [in] frame_size int: Number of samples per channel in the
+ * input signal.
+ * This must be an Opus frame size for
+ * the encoder's sampling rate.
+ * For example, at 48 kHz the permitted
+ * values are 120, 240, 480, 960, 1920,
+ * and 2880.
+ * Passing in a duration of less than
+ * 10 ms (480 samples at 48 kHz) will
+ * prevent the encoder from using the LPC
+ * or hybrid modes.
+ * @param [out] data unsigned char*: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes opus_int32: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode(
+ OpusEncoder *st,
+ const opus_int16 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes an Opus frame from floating point input.
+ * @param [in] st OpusEncoder*: Encoder state
+ * @param [in] pcm float*: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0.
+ * Samples with a range beyond +/-1.0 are supported but will
+ * be clipped by decoders using the integer API and should
+ * only be used if it is known that the far end supports
+ * extended dynamic range.
+ * length is frame_size*channels*sizeof(float)
+ * @param [in] frame_size int: Number of samples per channel in the
+ * input signal.
+ * This must be an Opus frame size for
+ * the encoder's sampling rate.
+ * For example, at 48 kHz the permitted
+ * values are 120, 240, 480, 960, 1920,
+ * and 2880.
+ * Passing in a duration of less than
+ * 10 ms (480 samples at 48 kHz) will
+ * prevent the encoder from using the LPC
+ * or hybrid modes.
+ * @param [out] data unsigned char*: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes opus_int32: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float(
+ OpusEncoder *st,
+ const float *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Frees an OpusEncoder
allocated by opus_encoder_create().
+ * @param[in] st OpusEncoder*: State to be freed.
+ */
+OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);
+
+/** Perform a CTL function on an Opus encoder.
+ *
+ * Generally the request and subsequent arguments are generated
+ * by a convenience macro.
+ * @param st OpusEncoder*: Encoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls or
+ * @ref opus_encoderctls.
+ * @see opus_genericctls
+ * @see opus_encoderctls
+ */
+OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+/**@}*/
+
+/** @defgroup opus_decoder Opus Decoder
+ * @{
+ *
+ * @brief This page describes the process and functions used to decode Opus.
+ *
+ * The decoding process also starts with creating a decoder
+ * state. This can be done with:
+ * @code
+ * int error;
+ * OpusDecoder *dec;
+ * dec = opus_decoder_create(Fs, channels, &error);
+ * @endcode
+ * where
+ * @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000
+ * @li channels is the number of channels (1 or 2)
+ * @li error will hold the error code in case of failure (or #OPUS_OK on success)
+ * @li the return value is a newly created decoder state to be used for decoding
+ *
+ * While opus_decoder_create() allocates memory for the state, it's also possible
+ * to initialize pre-allocated memory:
+ * @code
+ * int size;
+ * int error;
+ * OpusDecoder *dec;
+ * size = opus_decoder_get_size(channels);
+ * dec = malloc(size);
+ * error = opus_decoder_init(dec, Fs, channels);
+ * @endcode
+ * where opus_decoder_get_size() returns the required size for the decoder state. Note that
+ * future versions of this code may change the size, so no assuptions should be made about it.
+ *
+ * The decoder state is always continuous in memory and only a shallow copy is sufficient
+ * to copy it (e.g. memcpy())
+ *
+ * To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data:
+ * @code
+ * frame_size = opus_decode(dec, packet, len, decoded, max_size, 0);
+ * @endcode
+ * where
+ *
+ * @li packet is the byte array containing the compressed data
+ * @li len is the exact number of bytes contained in the packet
+ * @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float())
+ * @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array
+ *
+ * opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet.
+ * If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio
+ * buffer is too small to hold the decoded audio.
+ *
+ * Opus is a stateful codec with overlapping blocks and as a result Opus
+ * packets are not coded independently of each other. Packets must be
+ * passed into the decoder serially and in the correct order for a correct
+ * decode. Lost packets can be replaced with loss concealment by calling
+ * the decoder with a null pointer and zero length for the missing packet.
+ *
+ * A single codec state may only be accessed from a single thread at
+ * a time and any required locking must be performed by the caller. Separate
+ * streams must be decoded with separate decoder states and can be decoded
+ * in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
+ * defined.
+ *
+ */
+
+/** Opus decoder state.
+ * This contains the complete state of an Opus decoder.
+ * It is position independent and can be freely copied.
+ * @see opus_decoder_create,opus_decoder_init
+ */
+typedef struct OpusDecoder OpusDecoder;
+
+/** Gets the size of an OpusDecoder
structure.
+ * @param [in] channels int: Number of channels.
+ * This must be 1 or 2.
+ * @returns The size in bytes.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels);
+
+/** Allocates and initializes a decoder state.
+ * @param [in] Fs opus_int32: Sample rate to decode at (Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param [in] channels int: Number of channels (1 or 2) to decode
+ * @param [out] error int*: #OPUS_OK Success or @ref opus_errorcodes
+ *
+ * Internally Opus stores data at 48000 Hz, so that should be the default
+ * value for Fs. However, the decoder can efficiently decode to buffers
+ * at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use
+ * data at the full sample rate, or knows the compressed data doesn't
+ * use the full frequency range, it can request decoding at a reduced
+ * rate. Likewise, the decoder is capable of filling in either mono or
+ * interleaved stereo pcm buffers, at the caller's request.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create(
+ opus_int32 Fs,
+ int channels,
+ int *error
+);
+
+/** Initializes a previously allocated decoder state.
+ * The state must be at least the size returned by opus_decoder_get_size().
+ * This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @param [in] st OpusDecoder*: Decoder state.
+ * @param [in] Fs opus_int32: Sampling rate to decode to (Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param [in] channels int: Number of channels (1 or 2) to decode
+ * @retval #OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_EXPORT int opus_decoder_init(
+ OpusDecoder *st,
+ opus_int32 Fs,
+ int channels
+) OPUS_ARG_NONNULL(1);
+
+/** Decode an Opus packet.
+ * @param [in] st OpusDecoder*: Decoder state
+ * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss
+ * @param [in] len opus_int32: Number of bytes in payload*
+ * @param [out] pcm opus_int16*: Output signal (interleaved if 2 channels). length
+ * is frame_size*channels*sizeof(opus_int16)
+ * @param [in] frame_size Number of samples per channel of available space in \a pcm.
+ * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
+ * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
+ * then frame_size needs to be exactly the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
+ * FEC cases, frame_size must be a multiple of 2.5 ms.
+ * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be
+ * decoded. If no such data is available, the frame is decoded as if it were lost.
+ * @returns Number of decoded samples or @ref opus_errorcodes
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
+ OpusDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int16 *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode an Opus packet with floating point output.
+ * @param [in] st OpusDecoder*: Decoder state
+ * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss
+ * @param [in] len opus_int32: Number of bytes in payload
+ * @param [out] pcm float*: Output signal (interleaved if 2 channels). length
+ * is frame_size*channels*sizeof(float)
+ * @param [in] frame_size Number of samples per channel of available space in \a pcm.
+ * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
+ * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
+ * then frame_size needs to be exactly the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
+ * FEC cases, frame_size must be a multiple of 2.5 ms.
+ * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be
+ * decoded. If no such data is available the frame is decoded as if it were lost.
+ * @returns Number of decoded samples or @ref opus_errorcodes
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float(
+ OpusDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ float *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on an Opus decoder.
+ *
+ * Generally the request and subsequent arguments are generated
+ * by a convenience macro.
+ * @param st OpusDecoder*: Decoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls or
+ * @ref opus_decoderctls.
+ * @see opus_genericctls
+ * @see opus_decoderctls
+ */
+OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/** Frees an OpusDecoder
allocated by opus_decoder_create().
+ * @param[in] st OpusDecoder*: State to be freed.
+ */
+OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
+
+/** Parse an opus packet into one or more frames.
+ * Opus_decode will perform this operation internally so most applications do
+ * not need to use this function.
+ * This function does not copy the frames, the returned pointers are pointers into
+ * the input packet.
+ * @param [in] data char*: Opus packet to be parsed
+ * @param [in] len opus_int32: size of data
+ * @param [out] out_toc char*: TOC pointer
+ * @param [out] frames char*[48] encapsulated frames
+ * @param [out] size opus_int16[48] sizes of the encapsulated frames
+ * @param [out] payload_offset int*: returns the position of the payload within the packet (in bytes)
+ * @returns number of frames
+ */
+OPUS_EXPORT int opus_packet_parse(
+ const unsigned char *data,
+ opus_int32 len,
+ unsigned char *out_toc,
+ const unsigned char *frames[48],
+ opus_int16 size[48],
+ int *payload_offset
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5);
+
+/** Gets the bandwidth of an Opus packet.
+ * @param [in] data char*: Opus packet
+ * @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass)
+ * @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass)
+ * @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass)
+ * @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass)
+ * @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass)
+ * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of samples per frame from an Opus packet.
+ * @param [in] data char*: Opus packet.
+ * This must contain at least one byte of
+ * data.
+ * @param [in] Fs opus_int32: Sampling rate in Hz.
+ * This must be a multiple of 400, or
+ * inaccurate results will be returned.
+ * @returns Number of samples per frame.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of channels from an Opus packet.
+ * @param [in] data char*: Opus packet
+ * @returns Number of channels
+ * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of frames in an Opus packet.
+ * @param [in] packet char*: Opus packet
+ * @param [in] len opus_int32: Length of packet
+ * @returns Number of frames
+ * @retval OPUS_BAD_ARG Insufficient data was passed to the function
+ * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of samples of an Opus packet.
+ * @param [in] packet char*: Opus packet
+ * @param [in] len opus_int32: Length of packet
+ * @param [in] Fs opus_int32: Sampling rate in Hz.
+ * This must be a multiple of 400, or
+ * inaccurate results will be returned.
+ * @returns Number of samples
+ * @retval OPUS_BAD_ARG Insufficient data was passed to the function
+ * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of samples of an Opus packet.
+ * @param [in] dec OpusDecoder*: Decoder state
+ * @param [in] packet char*: Opus packet
+ * @param [in] len opus_int32: Length of packet
+ * @returns Number of samples
+ * @retval OPUS_BAD_ARG Insufficient data was passed to the function
+ * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+
+/** Applies soft-clipping to bring a float signal within the [-1,1] range. If
+ * the signal is already in that range, nothing is done. If there are values
+ * outside of [-1,1], then the signal is clipped as smoothly as possible to
+ * both fit in the range and avoid creating excessive distortion in the
+ * process.
+ * @param [in,out] pcm float*: Input PCM and modified PCM
+ * @param [in] frame_size int Number of samples per channel to process
+ * @param [in] channels int: Number of channels
+ * @param [in,out] softclip_mem float*: State memory for the soft clipping process (one float per channel, initialized to zero)
+ */
+OPUS_EXPORT void opus_pcm_soft_clip(float *pcm, int frame_size, int channels, float *softclip_mem);
+
+
+/**@}*/
+
+/** @defgroup opus_repacketizer Repacketizer
+ * @{
+ *
+ * The repacketizer can be used to merge multiple Opus packets into a single
+ * packet or alternatively to split Opus packets that have previously been
+ * merged. Splitting valid Opus packets is always guaranteed to succeed,
+ * whereas merging valid packets only succeeds if all frames have the same
+ * mode, bandwidth, and frame size, and when the total duration of the merged
+ * packet is no more than 120 ms. The 120 ms limit comes from the
+ * specification and limits decoder memory requirements at a point where
+ * framing overhead becomes negligible.
+ *
+ * The repacketizer currently only operates on elementary Opus
+ * streams. It will not manipualte multistream packets successfully, except in
+ * the degenerate case where they consist of data from a single stream.
+ *
+ * The repacketizing process starts with creating a repacketizer state, either
+ * by calling opus_repacketizer_create() or by allocating the memory yourself,
+ * e.g.,
+ * @code
+ * OpusRepacketizer *rp;
+ * rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size());
+ * if (rp != NULL)
+ * opus_repacketizer_init(rp);
+ * @endcode
+ *
+ * Then the application should submit packets with opus_repacketizer_cat(),
+ * extract new packets with opus_repacketizer_out() or
+ * opus_repacketizer_out_range(), and then reset the state for the next set of
+ * input packets via opus_repacketizer_init().
+ *
+ * For example, to split a sequence of packets into individual frames:
+ * @code
+ * unsigned char *data;
+ * int len;
+ * while (get_next_packet(&data, &len))
+ * {
+ * unsigned char out[1276];
+ * opus_int32 out_len;
+ * int nb_frames;
+ * int err;
+ * int i;
+ * err = opus_repacketizer_cat(rp, data, len);
+ * if (err != OPUS_OK)
+ * {
+ * release_packet(data);
+ * return err;
+ * }
+ * nb_frames = opus_repacketizer_get_nb_frames(rp);
+ * for (i = 0; i < nb_frames; i++)
+ * {
+ * out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out));
+ * if (out_len < 0)
+ * {
+ * release_packet(data);
+ * return (int)out_len;
+ * }
+ * output_next_packet(out, out_len);
+ * }
+ * opus_repacketizer_init(rp);
+ * release_packet(data);
+ * }
+ * @endcode
+ *
+ * Alternatively, to combine a sequence of frames into packets that each
+ * contain up to TARGET_DURATION_MS
milliseconds of data:
+ * @code
+ * // The maximum number of packets with duration TARGET_DURATION_MS occurs
+ * // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5)
+ * // packets.
+ * unsigned char *data[(TARGET_DURATION_MS*2/5)+1];
+ * opus_int32 len[(TARGET_DURATION_MS*2/5)+1];
+ * int nb_packets;
+ * unsigned char out[1277*(TARGET_DURATION_MS*2/2)];
+ * opus_int32 out_len;
+ * int prev_toc;
+ * nb_packets = 0;
+ * while (get_next_packet(data+nb_packets, len+nb_packets))
+ * {
+ * int nb_frames;
+ * int err;
+ * nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]);
+ * if (nb_frames < 1)
+ * {
+ * release_packets(data, nb_packets+1);
+ * return nb_frames;
+ * }
+ * nb_frames += opus_repacketizer_get_nb_frames(rp);
+ * // If adding the next packet would exceed our target, or it has an
+ * // incompatible TOC sequence, output the packets we already have before
+ * // submitting it.
+ * // N.B., The nb_packets > 0 check ensures we've submitted at least one
+ * // packet since the last call to opus_repacketizer_init(). Otherwise a
+ * // single packet longer than TARGET_DURATION_MS would cause us to try to
+ * // output an (invalid) empty packet. It also ensures that prev_toc has
+ * // been set to a valid value. Additionally, len[nb_packets] > 0 is
+ * // guaranteed by the call to opus_packet_get_nb_frames() above, so the
+ * // reference to data[nb_packets][0] should be valid.
+ * if (nb_packets > 0 && (
+ * ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) ||
+ * opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames >
+ * TARGET_DURATION_MS*48))
+ * {
+ * out_len = opus_repacketizer_out(rp, out, sizeof(out));
+ * if (out_len < 0)
+ * {
+ * release_packets(data, nb_packets+1);
+ * return (int)out_len;
+ * }
+ * output_next_packet(out, out_len);
+ * opus_repacketizer_init(rp);
+ * release_packets(data, nb_packets);
+ * data[0] = data[nb_packets];
+ * len[0] = len[nb_packets];
+ * nb_packets = 0;
+ * }
+ * err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]);
+ * if (err != OPUS_OK)
+ * {
+ * release_packets(data, nb_packets+1);
+ * return err;
+ * }
+ * prev_toc = data[nb_packets][0];
+ * nb_packets++;
+ * }
+ * // Output the final, partial packet.
+ * if (nb_packets > 0)
+ * {
+ * out_len = opus_repacketizer_out(rp, out, sizeof(out));
+ * release_packets(data, nb_packets);
+ * if (out_len < 0)
+ * return (int)out_len;
+ * output_next_packet(out, out_len);
+ * }
+ * @endcode
+ *
+ * An alternate way of merging packets is to simply call opus_repacketizer_cat()
+ * unconditionally until it fails. At that point, the merged packet can be
+ * obtained with opus_repacketizer_out() and the input packet for which
+ * opus_repacketizer_cat() needs to be re-added to a newly reinitialized
+ * repacketizer state.
+ */
+
+typedef struct OpusRepacketizer OpusRepacketizer;
+
+/** Gets the size of an OpusRepacketizer
structure.
+ * @returns The size in bytes.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void);
+
+/** (Re)initializes a previously allocated repacketizer state.
+ * The state must be at least the size returned by opus_repacketizer_get_size().
+ * This can be used for applications which use their own allocator instead of
+ * malloc().
+ * It must also be called to reset the queue of packets waiting to be
+ * repacketized, which is necessary if the maximum packet duration of 120 ms
+ * is reached or if you wish to submit packets with a different Opus
+ * configuration (coding mode, audio bandwidth, frame size, or channel count).
+ * Failure to do so will prevent a new packet from being added with
+ * opus_repacketizer_cat().
+ * @see opus_repacketizer_create
+ * @see opus_repacketizer_get_size
+ * @see opus_repacketizer_cat
+ * @param rp OpusRepacketizer*: The repacketizer state to
+ * (re)initialize.
+ * @returns A pointer to the same repacketizer state that was passed in.
+ */
+OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
+
+/** Allocates memory and initializes the new repacketizer with
+ * opus_repacketizer_init().
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void);
+
+/** Frees an OpusRepacketizer
allocated by
+ * opus_repacketizer_create().
+ * @param[in] rp OpusRepacketizer*: State to be freed.
+ */
+OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp);
+
+/** Add a packet to the current repacketizer state.
+ * This packet must match the configuration of any packets already submitted
+ * for repacketization since the last call to opus_repacketizer_init().
+ * This means that it must have the same coding mode, audio bandwidth, frame
+ * size, and channel count.
+ * This can be checked in advance by examining the top 6 bits of the first
+ * byte of the packet, and ensuring they match the top 6 bits of the first
+ * byte of any previously submitted packet.
+ * The total duration of audio in the repacketizer state also must not exceed
+ * 120 ms, the maximum duration of a single packet, after adding this packet.
+ *
+ * The contents of the current repacketizer state can be extracted into new
+ * packets using opus_repacketizer_out() or opus_repacketizer_out_range().
+ *
+ * In order to add a packet with a different configuration or to add more
+ * audio beyond 120 ms, you must clear the repacketizer state by calling
+ * opus_repacketizer_init().
+ * If a packet is too large to add to the current repacketizer state, no part
+ * of it is added, even if it contains multiple frames, some of which might
+ * fit.
+ * If you wish to be able to add parts of such packets, you should first use
+ * another repacketizer to split the packet into pieces and add them
+ * individually.
+ * @see opus_repacketizer_out_range
+ * @see opus_repacketizer_out
+ * @see opus_repacketizer_init
+ * @param rp OpusRepacketizer*: The repacketizer state to which to
+ * add the packet.
+ * @param[in] data const unsigned char*: The packet data.
+ * The application must ensure
+ * this pointer remains valid
+ * until the next call to
+ * opus_repacketizer_init() or
+ * opus_repacketizer_destroy().
+ * @param len opus_int32: The number of bytes in the packet data.
+ * @returns An error code indicating whether or not the operation succeeded.
+ * @retval #OPUS_OK The packet's contents have been added to the repacketizer
+ * state.
+ * @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence,
+ * the packet's TOC sequence was not compatible
+ * with previously submitted packets (because
+ * the coding mode, audio bandwidth, frame size,
+ * or channel count did not match), or adding
+ * this packet would increase the total amount of
+ * audio stored in the repacketizer state to more
+ * than 120 ms.
+ */
+OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+
+
+/** Construct a new packet from data previously submitted to the repacketizer
+ * state via opus_repacketizer_cat().
+ * @param rp OpusRepacketizer*: The repacketizer state from which to
+ * construct the new packet.
+ * @param begin int: The index of the first frame in the current
+ * repacketizer state to include in the output.
+ * @param end int: One past the index of the last frame in the
+ * current repacketizer state to include in the
+ * output.
+ * @param[out] data const unsigned char*: The buffer in which to
+ * store the output packet.
+ * @param maxlen opus_int32: The maximum number of bytes to store in
+ * the output buffer. In order to guarantee
+ * success, this should be at least
+ * 1276
for a single frame,
+ * or for multiple frames,
+ * 1277*(end-begin)
.
+ * However, 1*(end-begin)
plus
+ * the size of all packet data submitted to
+ * the repacketizer since the last call to
+ * opus_repacketizer_init() or
+ * opus_repacketizer_create() is also
+ * sufficient, and possibly much smaller.
+ * @returns The total size of the output packet on success, or an error code
+ * on failure.
+ * @retval #OPUS_BAD_ARG [begin,end)
was an invalid range of
+ * frames (begin < 0, begin >= end, or end >
+ * opus_repacketizer_get_nb_frames()).
+ * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
+ * complete output packet.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Return the total number of frames contained in packet data submitted to
+ * the repacketizer state so far via opus_repacketizer_cat() since the last
+ * call to opus_repacketizer_init() or opus_repacketizer_create().
+ * This defines the valid range of packets that can be extracted with
+ * opus_repacketizer_out_range() or opus_repacketizer_out().
+ * @param rp OpusRepacketizer*: The repacketizer state containing the
+ * frames.
+ * @returns The total number of frames contained in the packet data submitted
+ * to the repacketizer state.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
+
+/** Construct a new packet from data previously submitted to the repacketizer
+ * state via opus_repacketizer_cat().
+ * This is a convenience routine that returns all the data submitted so far
+ * in a single packet.
+ * It is equivalent to calling
+ * @code
+ * opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp),
+ * data, maxlen)
+ * @endcode
+ * @param rp OpusRepacketizer*: The repacketizer state from which to
+ * construct the new packet.
+ * @param[out] data const unsigned char*: The buffer in which to
+ * store the output packet.
+ * @param maxlen opus_int32: The maximum number of bytes to store in
+ * the output buffer. In order to guarantee
+ * success, this should be at least
+ * 1277*opus_repacketizer_get_nb_frames(rp)
.
+ * However,
+ * 1*opus_repacketizer_get_nb_frames(rp)
+ * plus the size of all packet data
+ * submitted to the repacketizer since the
+ * last call to opus_repacketizer_init() or
+ * opus_repacketizer_create() is also
+ * sufficient, and possibly much smaller.
+ * @returns The total size of the output packet on success, or an error code
+ * on failure.
+ * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
+ * complete output packet.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1);
+
+/** Pads a given Opus packet to a larger size (possibly changing the TOC sequence).
+ * @param[in,out] data const unsigned char*: The buffer containing the
+ * packet to pad.
+ * @param len opus_int32: The size of the packet.
+ * This must be at least 1.
+ * @param new_len opus_int32: The desired size of the packet after padding.
+ * This must be at least as large as len.
+ * @returns an error code
+ * @retval #OPUS_OK \a on success.
+ * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
+ * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+ */
+OPUS_EXPORT int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len);
+
+/** Remove all padding from a given Opus packet and rewrite the TOC sequence to
+ * minimize space usage.
+ * @param[in,out] data const unsigned char*: The buffer containing the
+ * packet to strip.
+ * @param len opus_int32: The size of the packet.
+ * This must be at least 1.
+ * @returns The new size of the output packet on success, or an error code
+ * on failure.
+ * @retval #OPUS_BAD_ARG \a len was less than 1.
+ * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len);
+
+/** Pads a given Opus multi-stream packet to a larger size (possibly changing the TOC sequence).
+ * @param[in,out] data const unsigned char*: The buffer containing the
+ * packet to pad.
+ * @param len opus_int32: The size of the packet.
+ * This must be at least 1.
+ * @param new_len opus_int32: The desired size of the packet after padding.
+ * This must be at least 1.
+ * @param nb_streams opus_int32: The number of streams (not channels) in the packet.
+ * This must be at least as large as len.
+ * @returns an error code
+ * @retval #OPUS_OK \a on success.
+ * @retval #OPUS_BAD_ARG \a len was less than 1.
+ * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+ */
+OPUS_EXPORT int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams);
+
+/** Remove all padding from a given Opus multi-stream packet and rewrite the TOC sequence to
+ * minimize space usage.
+ * @param[in,out] data const unsigned char*: The buffer containing the
+ * packet to strip.
+ * @param len opus_int32: The size of the packet.
+ * This must be at least 1.
+ * @param nb_streams opus_int32: The number of streams (not channels) in the packet.
+ * This must be at least 1.
+ * @returns The new size of the output packet on success, or an error code
+ * on failure.
+ * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
+ * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_H */
diff --git a/library/opusencoder/src/main/cpp/opus/include/opus_custom.h b/library/opusencoder/src/main/cpp/opus/include/opus_custom.h
new file mode 100644
index 0000000000..41f36bf2fb
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/opus/include/opus_custom.h
@@ -0,0 +1,342 @@
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2008-2012 Gregory Maxwell
+ Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ @file opus_custom.h
+ @brief Opus-Custom reference implementation API
+ */
+
+#ifndef OPUS_CUSTOM_H
+#define OPUS_CUSTOM_H
+
+#include "opus_defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef CUSTOM_MODES
+# define OPUS_CUSTOM_EXPORT OPUS_EXPORT
+# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT
+#else
+# define OPUS_CUSTOM_EXPORT
+# ifdef OPUS_BUILD
+# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE
+# else
+# define OPUS_CUSTOM_EXPORT_STATIC
+# endif
+#endif
+
+/** @defgroup opus_custom Opus Custom
+ * @{
+ * Opus Custom is an optional part of the Opus specification and
+ * reference implementation which uses a distinct API from the regular
+ * API and supports frame sizes that are not normally supported.\ Use
+ * of Opus Custom is discouraged for all but very special applications
+ * for which a frame size different from 2.5, 5, 10, or 20 ms is needed
+ * (for either complexity or latency reasons) and where interoperability
+ * is less important.
+ *
+ * In addition to the interoperability limitations the use of Opus custom
+ * disables a substantial chunk of the codec and generally lowers the
+ * quality available at a given bitrate. Normally when an application needs
+ * a different frame size from the codec it should buffer to match the
+ * sizes but this adds a small amount of delay which may be important
+ * in some very low latency applications. Some transports (especially
+ * constant rate RF transports) may also work best with frames of
+ * particular durations.
+ *
+ * Libopus only supports custom modes if they are enabled at compile time.
+ *
+ * The Opus Custom API is similar to the regular API but the
+ * @ref opus_encoder_create and @ref opus_decoder_create calls take
+ * an additional mode parameter which is a structure produced by
+ * a call to @ref opus_custom_mode_create. Both the encoder and decoder
+ * must create a mode using the same sample rate (fs) and frame size
+ * (frame size) so these parameters must either be signaled out of band
+ * or fixed in a particular implementation.
+ *
+ * Similar to regular Opus the custom modes support on the fly frame size
+ * switching, but the sizes available depend on the particular frame size in
+ * use. For some initial frame sizes on a single on the fly size is available.
+ */
+
+/** Contains the state of an encoder. One encoder state is needed
+ for each stream. It is initialized once at the beginning of the
+ stream. Do *not* re-initialize the state for every frame.
+ @brief Encoder state
+ */
+typedef struct OpusCustomEncoder OpusCustomEncoder;
+
+/** State of the decoder. One decoder state is needed for each stream.
+ It is initialized once at the beginning of the stream. Do *not*
+ re-initialize the state for every frame.
+ @brief Decoder state
+ */
+typedef struct OpusCustomDecoder OpusCustomDecoder;
+
+/** The mode contains all the information necessary to create an
+ encoder. Both the encoder and decoder need to be initialized
+ with exactly the same mode, otherwise the output will be
+ corrupted.
+ @brief Mode configuration
+ */
+typedef struct OpusCustomMode OpusCustomMode;
+
+/** Creates a new mode struct. This will be passed to an encoder or
+ * decoder. The mode MUST NOT BE DESTROYED until the encoders and
+ * decoders that use it are destroyed as well.
+ * @param [in] Fs int: Sampling rate (8000 to 96000 Hz)
+ * @param [in] frame_size int: Number of samples (per channel) to encode in each
+ * packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes)
+ * @param [out] error int*: Returned error code (if NULL, no error will be returned)
+ * @return A newly created mode
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error);
+
+/** Destroys a mode struct. Only call this after all encoders and
+ * decoders using this mode are destroyed as well.
+ * @param [in] mode OpusCustomMode*: Mode to be freed.
+ */
+OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode);
+
+
+#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C)
+
+/* Encoder */
+/** Gets the size of an OpusCustomEncoder structure.
+ * @param [in] mode OpusCustomMode *: Mode configuration
+ * @param [in] channels int: Number of channels
+ * @returns size
+ */
+OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size(
+ const OpusCustomMode *mode,
+ int channels
+) OPUS_ARG_NONNULL(1);
+
+# ifdef CUSTOM_MODES
+/** Initializes a previously allocated encoder state
+ * The memory pointed to by st must be the size returned by opus_custom_encoder_get_size.
+ * This is intended for applications which use their own allocator instead of malloc.
+ * @see opus_custom_encoder_create(),opus_custom_encoder_get_size()
+ * To reset a previously initialized state use the OPUS_RESET_STATE CTL.
+ * @param [in] st OpusCustomEncoder*: Encoder state
+ * @param [in] mode OpusCustomMode *: Contains all the information about the characteristics of
+ * the stream (must be the same characteristics as used for the
+ * decoder)
+ * @param [in] channels int: Number of channels
+ * @return OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_CUSTOM_EXPORT int opus_custom_encoder_init(
+ OpusCustomEncoder *st,
+ const OpusCustomMode *mode,
+ int channels
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+# endif
+#endif
+
+
+/** Creates a new encoder state. Each stream needs its own encoder
+ * state (can't be shared across simultaneous streams).
+ * @param [in] mode OpusCustomMode*: Contains all the information about the characteristics of
+ * the stream (must be the same characteristics as used for the
+ * decoder)
+ * @param [in] channels int: Number of channels
+ * @param [out] error int*: Returns an error code
+ * @return Newly created encoder state.
+*/
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create(
+ const OpusCustomMode *mode,
+ int channels,
+ int *error
+) OPUS_ARG_NONNULL(1);
+
+
+/** Destroys a an encoder state.
+ * @param[in] st OpusCustomEncoder*: State to be freed.
+ */
+OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
+
+/** Encodes a frame of audio.
+ * @param [in] st OpusCustomEncoder*: Encoder state
+ * @param [in] pcm float*: PCM audio in float format, with a normal range of +/-1.0.
+ * Samples with a range beyond +/-1.0 are supported but will
+ * be clipped by decoders using the integer API and should
+ * only be used if it is known that the far end supports
+ * extended dynamic range. There must be exactly
+ * frame_size samples per channel.
+ * @param [in] frame_size int: Number of samples per frame of input signal
+ * @param [out] compressed char *: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
+ * @param [in] maxCompressedBytes int: Maximum number of bytes to use for compressing the frame
+ * (can change from one frame to another)
+ * @return Number of bytes written to "compressed".
+ * If negative, an error has occurred (see error codes). It is IMPORTANT that
+ * the length returned be somehow transmitted to the decoder. Otherwise, no
+ * decoding is possible.
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float(
+ OpusCustomEncoder *st,
+ const float *pcm,
+ int frame_size,
+ unsigned char *compressed,
+ int maxCompressedBytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a frame of audio.
+ * @param [in] st OpusCustomEncoder*: Encoder state
+ * @param [in] pcm opus_int16*: PCM audio in signed 16-bit format (native endian).
+ * There must be exactly frame_size samples per channel.
+ * @param [in] frame_size int: Number of samples per frame of input signal
+ * @param [out] compressed char *: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
+ * @param [in] maxCompressedBytes int: Maximum number of bytes to use for compressing the frame
+ * (can change from one frame to another)
+ * @return Number of bytes written to "compressed".
+ * If negative, an error has occurred (see error codes). It is IMPORTANT that
+ * the length returned be somehow transmitted to the decoder. Otherwise, no
+ * decoding is possible.
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
+ OpusCustomEncoder *st,
+ const opus_int16 *pcm,
+ int frame_size,
+ unsigned char *compressed,
+ int maxCompressedBytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on an Opus custom encoder.
+ *
+ * Generally the request and subsequent arguments are generated
+ * by a convenience macro.
+ * @see opus_encoderctls
+ */
+OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
+
+
+#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C)
+/* Decoder */
+
+/** Gets the size of an OpusCustomDecoder structure.
+ * @param [in] mode OpusCustomMode *: Mode configuration
+ * @param [in] channels int: Number of channels
+ * @returns size
+ */
+OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size(
+ const OpusCustomMode *mode,
+ int channels
+) OPUS_ARG_NONNULL(1);
+
+/** Initializes a previously allocated decoder state
+ * The memory pointed to by st must be the size returned by opus_custom_decoder_get_size.
+ * This is intended for applications which use their own allocator instead of malloc.
+ * @see opus_custom_decoder_create(),opus_custom_decoder_get_size()
+ * To reset a previously initialized state use the OPUS_RESET_STATE CTL.
+ * @param [in] st OpusCustomDecoder*: Decoder state
+ * @param [in] mode OpusCustomMode *: Contains all the information about the characteristics of
+ * the stream (must be the same characteristics as used for the
+ * encoder)
+ * @param [in] channels int: Number of channels
+ * @return OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init(
+ OpusCustomDecoder *st,
+ const OpusCustomMode *mode,
+ int channels
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+
+#endif
+
+
+/** Creates a new decoder state. Each stream needs its own decoder state (can't
+ * be shared across simultaneous streams).
+ * @param [in] mode OpusCustomMode: Contains all the information about the characteristics of the
+ * stream (must be the same characteristics as used for the encoder)
+ * @param [in] channels int: Number of channels
+ * @param [out] error int*: Returns an error code
+ * @return Newly created decoder state.
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create(
+ const OpusCustomMode *mode,
+ int channels,
+ int *error
+) OPUS_ARG_NONNULL(1);
+
+/** Destroys a an decoder state.
+ * @param[in] st OpusCustomDecoder*: State to be freed.
+ */
+OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);
+
+/** Decode an opus custom frame with floating point output
+ * @param [in] st OpusCustomDecoder*: Decoder state
+ * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss
+ * @param [in] len int: Number of bytes in payload
+ * @param [out] pcm float*: Output signal (interleaved if 2 channels). length
+ * is frame_size*channels*sizeof(float)
+ * @param [in] frame_size Number of samples per channel of available space in *pcm.
+ * @returns Number of decoded samples or @ref opus_errorcodes
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float(
+ OpusCustomDecoder *st,
+ const unsigned char *data,
+ int len,
+ float *pcm,
+ int frame_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode an opus custom frame
+ * @param [in] st OpusCustomDecoder*: Decoder state
+ * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss
+ * @param [in] len int: Number of bytes in payload
+ * @param [out] pcm opus_int16*: Output signal (interleaved if 2 channels). length
+ * is frame_size*channels*sizeof(opus_int16)
+ * @param [in] frame_size Number of samples per channel of available space in *pcm.
+ * @returns Number of decoded samples or @ref opus_errorcodes
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
+ OpusCustomDecoder *st,
+ const unsigned char *data,
+ int len,
+ opus_int16 *pcm,
+ int frame_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on an Opus custom decoder.
+ *
+ * Generally the request and subsequent arguments are generated
+ * by a convenience macro.
+ * @see opus_genericctls
+ */
+OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_CUSTOM_H */
diff --git a/library/opusencoder/src/main/cpp/opus/include/opus_defines.h b/library/opusencoder/src/main/cpp/opus/include/opus_defines.h
new file mode 100644
index 0000000000..fbf5d0eb74
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/opus/include/opus_defines.h
@@ -0,0 +1,788 @@
+/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
+ Written by Jean-Marc Valin and Koen Vos */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file opus_defines.h
+ * @brief Opus reference implementation constants
+ */
+
+#ifndef OPUS_DEFINES_H
+#define OPUS_DEFINES_H
+
+#include "opus_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup opus_errorcodes Error codes
+ * @{
+ */
+/** No error @hideinitializer*/
+#define OPUS_OK 0
+/** One or more invalid/out of range arguments @hideinitializer*/
+#define OPUS_BAD_ARG -1
+/** Not enough bytes allocated in the buffer @hideinitializer*/
+#define OPUS_BUFFER_TOO_SMALL -2
+/** An internal error was detected @hideinitializer*/
+#define OPUS_INTERNAL_ERROR -3
+/** The compressed data passed is corrupted @hideinitializer*/
+#define OPUS_INVALID_PACKET -4
+/** Invalid/unsupported request number @hideinitializer*/
+#define OPUS_UNIMPLEMENTED -5
+/** An encoder or decoder structure is invalid or already freed @hideinitializer*/
+#define OPUS_INVALID_STATE -6
+/** Memory allocation has failed @hideinitializer*/
+#define OPUS_ALLOC_FAIL -7
+/**@}*/
+
+/** @cond OPUS_INTERNAL_DOC */
+/**Export control for opus functions */
+
+#ifndef OPUS_EXPORT
+# if defined(WIN32)
+# if defined(OPUS_BUILD) && defined(DLL_EXPORT)
+# define OPUS_EXPORT __declspec(dllexport)
+# else
+# define OPUS_EXPORT
+# endif
+# elif defined(__GNUC__) && defined(OPUS_BUILD)
+# define OPUS_EXPORT __attribute__ ((visibility ("default")))
+# else
+# define OPUS_EXPORT
+# endif
+#endif
+
+# if !defined(OPUS_GNUC_PREREQ)
+# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
+# define OPUS_GNUC_PREREQ(_maj,_min) \
+ ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
+# else
+# define OPUS_GNUC_PREREQ(_maj,_min) 0
+# endif
+# endif
+
+#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
+# if OPUS_GNUC_PREREQ(3,0)
+# define OPUS_RESTRICT __restrict__
+# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
+# define OPUS_RESTRICT __restrict
+# else
+# define OPUS_RESTRICT
+# endif
+#else
+# define OPUS_RESTRICT restrict
+#endif
+
+#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
+# if OPUS_GNUC_PREREQ(2,7)
+# define OPUS_INLINE __inline__
+# elif (defined(_MSC_VER))
+# define OPUS_INLINE __inline
+# else
+# define OPUS_INLINE
+# endif
+#else
+# define OPUS_INLINE inline
+#endif
+
+/**Warning attributes for opus functions
+ * NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out
+ * some paranoid null checks. */
+#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
+# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
+#else
+# define OPUS_WARN_UNUSED_RESULT
+#endif
+#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
+# define OPUS_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
+#else
+# define OPUS_ARG_NONNULL(_x)
+#endif
+
+/** These are the actual Encoder CTL ID numbers.
+ * They should not be used directly by applications.
+ * In general, SETs should be even and GETs should be odd.*/
+#define OPUS_SET_APPLICATION_REQUEST 4000
+#define OPUS_GET_APPLICATION_REQUEST 4001
+#define OPUS_SET_BITRATE_REQUEST 4002
+#define OPUS_GET_BITRATE_REQUEST 4003
+#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004
+#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005
+#define OPUS_SET_VBR_REQUEST 4006
+#define OPUS_GET_VBR_REQUEST 4007
+#define OPUS_SET_BANDWIDTH_REQUEST 4008
+#define OPUS_GET_BANDWIDTH_REQUEST 4009
+#define OPUS_SET_COMPLEXITY_REQUEST 4010
+#define OPUS_GET_COMPLEXITY_REQUEST 4011
+#define OPUS_SET_INBAND_FEC_REQUEST 4012
+#define OPUS_GET_INBAND_FEC_REQUEST 4013
+#define OPUS_SET_PACKET_LOSS_PERC_REQUEST 4014
+#define OPUS_GET_PACKET_LOSS_PERC_REQUEST 4015
+#define OPUS_SET_DTX_REQUEST 4016
+#define OPUS_GET_DTX_REQUEST 4017
+#define OPUS_SET_VBR_CONSTRAINT_REQUEST 4020
+#define OPUS_GET_VBR_CONSTRAINT_REQUEST 4021
+#define OPUS_SET_FORCE_CHANNELS_REQUEST 4022
+#define OPUS_GET_FORCE_CHANNELS_REQUEST 4023
+#define OPUS_SET_SIGNAL_REQUEST 4024
+#define OPUS_GET_SIGNAL_REQUEST 4025
+#define OPUS_GET_LOOKAHEAD_REQUEST 4027
+/* #define OPUS_RESET_STATE 4028 */
+#define OPUS_GET_SAMPLE_RATE_REQUEST 4029
+#define OPUS_GET_FINAL_RANGE_REQUEST 4031
+#define OPUS_GET_PITCH_REQUEST 4033
+#define OPUS_SET_GAIN_REQUEST 4034
+#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */
+#define OPUS_SET_LSB_DEPTH_REQUEST 4036
+#define OPUS_GET_LSB_DEPTH_REQUEST 4037
+#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039
+#define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040
+#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041
+#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042
+#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043
+/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
+#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
+#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
+
+/** Defines for the presence of extended APIs. */
+#define OPUS_HAVE_OPUS_PROJECTION_H
+
+/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
+#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
+#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
+#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
+#define __opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr)))
+/** @endcond */
+
+/** @defgroup opus_ctlvalues Pre-defined values for CTL interface
+ * @see opus_genericctls, opus_encoderctls
+ * @{
+ */
+/* Values for the various encoder CTLs */
+#define OPUS_AUTO -1000 /**opus_int32: Allowed values: 0-10, inclusive.
+ *
+ * @hideinitializer */
+#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x)
+/** Gets the encoder's complexity configuration.
+ * @see OPUS_SET_COMPLEXITY
+ * @param[out] x opus_int32 *: Returns a value in the range 0-10,
+ * inclusive.
+ * @hideinitializer */
+#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the bitrate in the encoder.
+ * Rates from 500 to 512000 bits per second are meaningful, as well as the
+ * special values #OPUS_AUTO and #OPUS_BITRATE_MAX.
+ * The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much
+ * rate as it can, which is useful for controlling the rate by adjusting the
+ * output buffer size.
+ * @see OPUS_GET_BITRATE
+ * @param[in] x opus_int32: Bitrate in bits per second. The default
+ * is determined based on the number of
+ * channels and the input sampling rate.
+ * @hideinitializer */
+#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x)
+/** Gets the encoder's bitrate configuration.
+ * @see OPUS_SET_BITRATE
+ * @param[out] x opus_int32 *: Returns the bitrate in bits per second.
+ * The default is determined based on the
+ * number of channels and the input
+ * sampling rate.
+ * @hideinitializer */
+#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x)
+
+/** Enables or disables variable bitrate (VBR) in the encoder.
+ * The configured bitrate may not be met exactly because frames must
+ * be an integer number of bytes in length.
+ * @see OPUS_GET_VBR
+ * @see OPUS_SET_VBR_CONSTRAINT
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - 0
- Hard CBR. For LPC/hybrid modes at very low bit-rate, this can
+ * cause noticeable quality degradation.
+ * - 1
- VBR (default). The exact type of VBR is controlled by
+ * #OPUS_SET_VBR_CONSTRAINT.
+ *
+ * @hideinitializer */
+#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x)
+/** Determine if variable bitrate (VBR) is enabled in the encoder.
+ * @see OPUS_SET_VBR
+ * @see OPUS_GET_VBR_CONSTRAINT
+ * @param[out] x opus_int32 *: Returns one of the following values:
+ *
+ * - 0
- Hard CBR.
+ * - 1
- VBR (default). The exact type of VBR may be retrieved via
+ * #OPUS_GET_VBR_CONSTRAINT.
+ *
+ * @hideinitializer */
+#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x)
+
+/** Enables or disables constrained VBR in the encoder.
+ * This setting is ignored when the encoder is in CBR mode.
+ * @warning Only the MDCT mode of Opus currently heeds the constraint.
+ * Speech mode ignores it completely, hybrid mode may fail to obey it
+ * if the LPC layer uses more bitrate than the constraint would have
+ * permitted.
+ * @see OPUS_GET_VBR_CONSTRAINT
+ * @see OPUS_SET_VBR
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - 0
- Unconstrained VBR.
+ * - 1
- Constrained VBR (default). This creates a maximum of one
+ * frame of buffering delay assuming a transport with a
+ * serialization speed of the nominal bitrate.
+ *
+ * @hideinitializer */
+#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x)
+/** Determine if constrained VBR is enabled in the encoder.
+ * @see OPUS_SET_VBR_CONSTRAINT
+ * @see OPUS_GET_VBR
+ * @param[out] x opus_int32 *: Returns one of the following values:
+ *
+ * - 0
- Unconstrained VBR.
+ * - 1
- Constrained VBR (default).
+ *
+ * @hideinitializer */
+#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures mono/stereo forcing in the encoder.
+ * This can force the encoder to produce packets encoded as either mono or
+ * stereo, regardless of the format of the input audio. This is useful when
+ * the caller knows that the input signal is currently a mono source embedded
+ * in a stereo stream.
+ * @see OPUS_GET_FORCE_CHANNELS
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - #OPUS_AUTO
- Not forced (default)
+ * - 1
- Forced mono
+ * - 2
- Forced stereo
+ *
+ * @hideinitializer */
+#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, __opus_check_int(x)
+/** Gets the encoder's forced channel configuration.
+ * @see OPUS_SET_FORCE_CHANNELS
+ * @param[out] x opus_int32 *:
+ *
+ * - #OPUS_AUTO
- Not forced (default)
+ * - 1
- Forced mono
+ * - 2
- Forced stereo
+ *
+ * @hideinitializer */
+#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the maximum bandpass that the encoder will select automatically.
+ * Applications should normally use this instead of #OPUS_SET_BANDWIDTH
+ * (leaving that set to the default, #OPUS_AUTO). This allows the
+ * application to set an upper bound based on the type of input it is
+ * providing, but still gives the encoder the freedom to reduce the bandpass
+ * when the bitrate becomes too low, for better overall quality.
+ * @see OPUS_GET_MAX_BANDWIDTH
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - OPUS_BANDWIDTH_NARROWBAND
- 4 kHz passband
+ * - OPUS_BANDWIDTH_MEDIUMBAND
- 6 kHz passband
+ * - OPUS_BANDWIDTH_WIDEBAND
- 8 kHz passband
+ * - OPUS_BANDWIDTH_SUPERWIDEBAND
- 12 kHz passband
+ * - OPUS_BANDWIDTH_FULLBAND
- 20 kHz passband (default)
+ *
+ * @hideinitializer */
+#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, __opus_check_int(x)
+
+/** Gets the encoder's configured maximum allowed bandpass.
+ * @see OPUS_SET_MAX_BANDWIDTH
+ * @param[out] x opus_int32 *: Allowed values:
+ *
+ * - #OPUS_BANDWIDTH_NARROWBAND
- 4 kHz passband
+ * - #OPUS_BANDWIDTH_MEDIUMBAND
- 6 kHz passband
+ * - #OPUS_BANDWIDTH_WIDEBAND
- 8 kHz passband
+ * - #OPUS_BANDWIDTH_SUPERWIDEBAND
- 12 kHz passband
+ * - #OPUS_BANDWIDTH_FULLBAND
- 20 kHz passband (default)
+ *
+ * @hideinitializer */
+#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
+
+/** Sets the encoder's bandpass to a specific value.
+ * This prevents the encoder from automatically selecting the bandpass based
+ * on the available bitrate. If an application knows the bandpass of the input
+ * audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH
+ * instead, which still gives the encoder the freedom to reduce the bandpass
+ * when the bitrate becomes too low, for better overall quality.
+ * @see OPUS_GET_BANDWIDTH
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - #OPUS_AUTO
- (default)
+ * - #OPUS_BANDWIDTH_NARROWBAND
- 4 kHz passband
+ * - #OPUS_BANDWIDTH_MEDIUMBAND
- 6 kHz passband
+ * - #OPUS_BANDWIDTH_WIDEBAND
- 8 kHz passband
+ * - #OPUS_BANDWIDTH_SUPERWIDEBAND
- 12 kHz passband
+ * - #OPUS_BANDWIDTH_FULLBAND
- 20 kHz passband
+ *
+ * @hideinitializer */
+#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x)
+
+/** Configures the type of signal being encoded.
+ * This is a hint which helps the encoder's mode selection.
+ * @see OPUS_GET_SIGNAL
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - #OPUS_AUTO
- (default)
+ * - #OPUS_SIGNAL_VOICE
- Bias thresholds towards choosing LPC or Hybrid modes.
+ * - #OPUS_SIGNAL_MUSIC
- Bias thresholds towards choosing MDCT modes.
+ *
+ * @hideinitializer */
+#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured signal type.
+ * @see OPUS_SET_SIGNAL
+ * @param[out] x opus_int32 *: Returns one of the following values:
+ *
+ * - #OPUS_AUTO
- (default)
+ * - #OPUS_SIGNAL_VOICE
- Bias thresholds towards choosing LPC or Hybrid modes.
+ * - #OPUS_SIGNAL_MUSIC
- Bias thresholds towards choosing MDCT modes.
+ *
+ * @hideinitializer */
+#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x)
+
+
+/** Configures the encoder's intended application.
+ * The initial value is a mandatory argument to the encoder_create function.
+ * @see OPUS_GET_APPLICATION
+ * @param[in] x opus_int32: Returns one of the following values:
+ *
+ * - #OPUS_APPLICATION_VOIP
+ * - Process signal for improved speech intelligibility.
+ * - #OPUS_APPLICATION_AUDIO
+ * - Favor faithfulness to the original input.
+ * - #OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ * - Configure the minimum possible coding delay by disabling certain modes
+ * of operation.
+ *
+ * @hideinitializer */
+#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured application.
+ * @see OPUS_SET_APPLICATION
+ * @param[out] x opus_int32 *: Returns one of the following values:
+ *
+ * - #OPUS_APPLICATION_VOIP
+ * - Process signal for improved speech intelligibility.
+ * - #OPUS_APPLICATION_AUDIO
+ * - Favor faithfulness to the original input.
+ * - #OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ * - Configure the minimum possible coding delay by disabling certain modes
+ * of operation.
+ *
+ * @hideinitializer */
+#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x)
+
+/** Gets the total samples of delay added by the entire codec.
+ * This can be queried by the encoder and then the provided number of samples can be
+ * skipped on from the start of the decoder's output to provide time aligned input
+ * and output. From the perspective of a decoding application the real data begins this many
+ * samples late.
+ *
+ * The decoder contribution to this delay is identical for all decoders, but the
+ * encoder portion of the delay may vary from implementation to implementation,
+ * version to version, or even depend on the encoder's initial configuration.
+ * Applications needing delay compensation should call this CTL rather than
+ * hard-coding a value.
+ * @param[out] x opus_int32 *: Number of lookahead samples
+ * @hideinitializer */
+#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the encoder's use of inband forward error correction (FEC).
+ * @note This is only applicable to the LPC layer
+ * @see OPUS_GET_INBAND_FEC
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - 0
- Disable inband FEC (default).
+ * - 1
- Enable inband FEC.
+ *
+ * @hideinitializer */
+#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
+/** Gets encoder's configured use of inband forward error correction.
+ * @see OPUS_SET_INBAND_FEC
+ * @param[out] x opus_int32 *: Returns one of the following values:
+ *
+ * - 0
- Inband FEC disabled (default).
+ * - 1
- Inband FEC enabled.
+ *
+ * @hideinitializer */
+#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the encoder's expected packet loss percentage.
+ * Higher values trigger progressively more loss resistant behavior in the encoder
+ * at the expense of quality at a given bitrate in the absence of packet loss, but
+ * greater quality under loss.
+ * @see OPUS_GET_PACKET_LOSS_PERC
+ * @param[in] x opus_int32: Loss percentage in the range 0-100, inclusive (default: 0).
+ * @hideinitializer */
+#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured packet loss percentage.
+ * @see OPUS_SET_PACKET_LOSS_PERC
+ * @param[out] x opus_int32 *: Returns the configured loss percentage
+ * in the range 0-100, inclusive (default: 0).
+ * @hideinitializer */
+#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the encoder's use of discontinuous transmission (DTX).
+ * @note This is only applicable to the LPC layer
+ * @see OPUS_GET_DTX
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - 0
- Disable DTX (default).
+ * - 1
- Enabled DTX.
+ *
+ * @hideinitializer */
+#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x)
+/** Gets encoder's configured use of discontinuous transmission.
+ * @see OPUS_SET_DTX
+ * @param[out] x opus_int32 *: Returns one of the following values:
+ *
+ * - 0
- DTX disabled (default).
+ * - 1
- DTX enabled.
+ *
+ * @hideinitializer */
+#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x)
+/** Configures the depth of signal being encoded.
+ *
+ * This is a hint which helps the encoder identify silence and near-silence.
+ * It represents the number of significant bits of linear intensity below
+ * which the signal contains ignorable quantization or other noise.
+ *
+ * For example, OPUS_SET_LSB_DEPTH(14) would be an appropriate setting
+ * for G.711 u-law input. OPUS_SET_LSB_DEPTH(16) would be appropriate
+ * for 16-bit linear pcm input with opus_encode_float().
+ *
+ * When using opus_encode() instead of opus_encode_float(), or when libopus
+ * is compiled for fixed-point, the encoder uses the minimum of the value
+ * set here and the value 16.
+ *
+ * @see OPUS_GET_LSB_DEPTH
+ * @param[in] x opus_int32: Input precision in bits, between 8 and 24
+ * (default: 24).
+ * @hideinitializer */
+#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured signal depth.
+ * @see OPUS_SET_LSB_DEPTH
+ * @param[out] x opus_int32 *: Input precision in bits, between 8 and
+ * 24 (default: 24).
+ * @hideinitializer */
+#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the encoder's use of variable duration frames.
+ * When variable duration is enabled, the encoder is free to use a shorter frame
+ * size than the one requested in the opus_encode*() call.
+ * It is then the user's responsibility
+ * to verify how much audio was encoded by checking the ToC byte of the encoded
+ * packet. The part of the audio that was not encoded needs to be resent to the
+ * encoder for the next call. Do not use this option unless you really
+ * know what you are doing.
+ * @see OPUS_GET_EXPERT_FRAME_DURATION
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - OPUS_FRAMESIZE_ARG
- Select frame size from the argument (default).
+ * - OPUS_FRAMESIZE_2_5_MS
- Use 2.5 ms frames.
+ * - OPUS_FRAMESIZE_5_MS
- Use 5 ms frames.
+ * - OPUS_FRAMESIZE_10_MS
- Use 10 ms frames.
+ * - OPUS_FRAMESIZE_20_MS
- Use 20 ms frames.
+ * - OPUS_FRAMESIZE_40_MS
- Use 40 ms frames.
+ * - OPUS_FRAMESIZE_60_MS
- Use 60 ms frames.
+ * - OPUS_FRAMESIZE_80_MS
- Use 80 ms frames.
+ * - OPUS_FRAMESIZE_100_MS
- Use 100 ms frames.
+ * - OPUS_FRAMESIZE_120_MS
- Use 120 ms frames.
+ *
+ * @hideinitializer */
+#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured use of variable duration frames.
+ * @see OPUS_SET_EXPERT_FRAME_DURATION
+ * @param[out] x opus_int32 *: Returns one of the following values:
+ *
+ * - OPUS_FRAMESIZE_ARG
- Select frame size from the argument (default).
+ * - OPUS_FRAMESIZE_2_5_MS
- Use 2.5 ms frames.
+ * - OPUS_FRAMESIZE_5_MS
- Use 5 ms frames.
+ * - OPUS_FRAMESIZE_10_MS
- Use 10 ms frames.
+ * - OPUS_FRAMESIZE_20_MS
- Use 20 ms frames.
+ * - OPUS_FRAMESIZE_40_MS
- Use 40 ms frames.
+ * - OPUS_FRAMESIZE_60_MS
- Use 60 ms frames.
+ * - OPUS_FRAMESIZE_80_MS
- Use 80 ms frames.
+ * - OPUS_FRAMESIZE_100_MS
- Use 100 ms frames.
+ * - OPUS_FRAMESIZE_120_MS
- Use 120 ms frames.
+ *
+ * @hideinitializer */
+#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x)
+
+/** If set to 1, disables almost all use of prediction, making frames almost
+ * completely independent. This reduces quality.
+ * @see OPUS_GET_PREDICTION_DISABLED
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - 0
- Enable prediction (default).
+ * - 1
- Disable prediction.
+ *
+ * @hideinitializer */
+#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured prediction status.
+ * @see OPUS_SET_PREDICTION_DISABLED
+ * @param[out] x opus_int32 *: Returns one of the following values:
+ *
+ * - 0
- Prediction enabled (default).
+ * - 1
- Prediction disabled.
+ *
+ * @hideinitializer */
+#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x)
+
+/**@}*/
+
+/** @defgroup opus_genericctls Generic CTLs
+ *
+ * These macros are used with the \c opus_decoder_ctl and
+ * \c opus_encoder_ctl calls to generate a particular
+ * request.
+ *
+ * When called on an \c OpusDecoder they apply to that
+ * particular decoder instance. When called on an
+ * \c OpusEncoder they apply to the corresponding setting
+ * on that encoder instance, if present.
+ *
+ * Some usage examples:
+ *
+ * @code
+ * int ret;
+ * opus_int32 pitch;
+ * ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch));
+ * if (ret == OPUS_OK) return ret;
+ *
+ * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
+ * opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE);
+ *
+ * opus_int32 enc_bw, dec_bw;
+ * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw));
+ * opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw));
+ * if (enc_bw != dec_bw) {
+ * printf("packet bandwidth mismatch!\n");
+ * }
+ * @endcode
+ *
+ * @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls
+ * @{
+ */
+
+/** Resets the codec state to be equivalent to a freshly initialized state.
+ * This should be called when switching streams in order to prevent
+ * the back to back decoding from giving different results from
+ * one at a time decoding.
+ * @hideinitializer */
+#define OPUS_RESET_STATE 4028
+
+/** Gets the final state of the codec's entropy coder.
+ * This is used for testing purposes,
+ * The encoder and decoder state should be identical after coding a payload
+ * (assuming no data corruption or software bugs)
+ *
+ * @param[out] x opus_uint32 *: Entropy coder state
+ *
+ * @hideinitializer */
+#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x)
+
+/** Gets the encoder's configured bandpass or the decoder's last bandpass.
+ * @see OPUS_SET_BANDWIDTH
+ * @param[out] x opus_int32 *: Returns one of the following values:
+ *
+ * - #OPUS_AUTO
- (default)
+ * - #OPUS_BANDWIDTH_NARROWBAND
- 4 kHz passband
+ * - #OPUS_BANDWIDTH_MEDIUMBAND
- 6 kHz passband
+ * - #OPUS_BANDWIDTH_WIDEBAND
- 8 kHz passband
+ * - #OPUS_BANDWIDTH_SUPERWIDEBAND
- 12 kHz passband
+ * - #OPUS_BANDWIDTH_FULLBAND
- 20 kHz passband
+ *
+ * @hideinitializer */
+#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
+
+/** Gets the sampling rate the encoder or decoder was initialized with.
+ * This simply returns the Fs
value passed to opus_encoder_init()
+ * or opus_decoder_init().
+ * @param[out] x opus_int32 *: Sampling rate of encoder or decoder.
+ * @hideinitializer
+ */
+#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
+
+/** If set to 1, disables the use of phase inversion for intensity stereo,
+ * improving the quality of mono downmixes, but slightly reducing normal
+ * stereo quality. Disabling phase inversion in the decoder does not comply
+ * with RFC 6716, although it does not cause any interoperability issue and
+ * is expected to become part of the Opus standard once RFC 6716 is updated
+ * by draft-ietf-codec-opus-update.
+ * @see OPUS_GET_PHASE_INVERSION_DISABLED
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - 0
- Enable phase inversion (default).
+ * - 1
- Disable phase inversion.
+ *
+ * @hideinitializer */
+#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured phase inversion status.
+ * @see OPUS_SET_PHASE_INVERSION_DISABLED
+ * @param[out] x opus_int32 *: Returns one of the following values:
+ *
+ * - 0
- Stereo phase inversion enabled (default).
+ * - 1
- Stereo phase inversion disabled.
+ *
+ * @hideinitializer */
+#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x)
+
+/**@}*/
+
+/** @defgroup opus_decoderctls Decoder related CTLs
+ * @see opus_genericctls, opus_encoderctls, opus_decoder
+ * @{
+ */
+
+/** Configures decoder gain adjustment.
+ * Scales the decoded output by a factor specified in Q8 dB units.
+ * This has a maximum range of -32768 to 32767 inclusive, and returns
+ * OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment.
+ * This setting survives decoder reset.
+ *
+ * gain = pow(10, x/(20.0*256))
+ *
+ * @param[in] x opus_int32: Amount to scale PCM signal by in Q8 dB units.
+ * @hideinitializer */
+#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x)
+/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN
+ *
+ * @param[out] x opus_int32 *: Amount to scale PCM signal by in Q8 dB units.
+ * @hideinitializer */
+#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x)
+
+/** Gets the duration (in samples) of the last packet successfully decoded or concealed.
+ * @param[out] x opus_int32 *: Number of samples (at current sampling rate).
+ * @hideinitializer */
+#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x)
+
+/** Gets the pitch of the last decoded frame, if available.
+ * This can be used for any post-processing algorithm requiring the use of pitch,
+ * e.g. time stretching/shortening. If the last frame was not voiced, or if the
+ * pitch was not coded in the frame, then zero is returned.
+ *
+ * This CTL is only implemented for decoder instances.
+ *
+ * @param[out] x opus_int32 *: pitch period at 48 kHz (or 0 if not available)
+ *
+ * @hideinitializer */
+#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x)
+
+/**@}*/
+
+/** @defgroup opus_libinfo Opus library information functions
+ * @{
+ */
+
+/** Converts an opus error code into a human readable string.
+ *
+ * @param[in] error int: Error number
+ * @returns Error string
+ */
+OPUS_EXPORT const char *opus_strerror(int error);
+
+/** Gets the libopus version string.
+ *
+ * Applications may look for the substring "-fixed" in the version string to
+ * determine whether they have a fixed-point or floating-point build at
+ * runtime.
+ *
+ * @returns Version string
+ */
+OPUS_EXPORT const char *opus_get_version_string(void);
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_DEFINES_H */
diff --git a/library/opusencoder/src/main/cpp/opus/include/opus_multistream.h b/library/opusencoder/src/main/cpp/opus/include/opus_multistream.h
new file mode 100644
index 0000000000..babcee6905
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/opus/include/opus_multistream.h
@@ -0,0 +1,660 @@
+/* Copyright (c) 2011 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file opus_multistream.h
+ * @brief Opus reference implementation multistream API
+ */
+
+#ifndef OPUS_MULTISTREAM_H
+#define OPUS_MULTISTREAM_H
+
+#include "opus.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond OPUS_INTERNAL_DOC */
+
+/** Macros to trigger compilation errors when the wrong types are provided to a
+ * CTL. */
+/**@{*/
+#define __opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr)))
+#define __opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr)))
+/**@}*/
+
+/** These are the actual encoder and decoder CTL ID numbers.
+ * They should not be used directly by applications.
+ * In general, SETs should be even and GETs should be odd.*/
+/**@{*/
+#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120
+#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122
+/**@}*/
+
+/** @endcond */
+
+/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs
+ *
+ * These are convenience macros that are specific to the
+ * opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl()
+ * interface.
+ * The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and
+ * @ref opus_decoderctls may be applied to a multistream encoder or decoder as
+ * well.
+ * In addition, you may retrieve the encoder or decoder state for an specific
+ * stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or
+ * #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually.
+ */
+/**@{*/
+
+/** Gets the encoder state for an individual stream of a multistream encoder.
+ * @param[in] x opus_int32: The index of the stream whose encoder you
+ * wish to retrieve.
+ * This must be non-negative and less than
+ * the streams
parameter used
+ * to initialize the encoder.
+ * @param[out] y OpusEncoder**: Returns a pointer to the given
+ * encoder state.
+ * @retval OPUS_BAD_ARG The index of the requested stream was out of range.
+ * @hideinitializer
+ */
+#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, __opus_check_int(x), __opus_check_encstate_ptr(y)
+
+/** Gets the decoder state for an individual stream of a multistream decoder.
+ * @param[in] x opus_int32: The index of the stream whose decoder you
+ * wish to retrieve.
+ * This must be non-negative and less than
+ * the streams
parameter used
+ * to initialize the decoder.
+ * @param[out] y OpusDecoder**: Returns a pointer to the given
+ * decoder state.
+ * @retval OPUS_BAD_ARG The index of the requested stream was out of range.
+ * @hideinitializer
+ */
+#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, __opus_check_int(x), __opus_check_decstate_ptr(y)
+
+/**@}*/
+
+/** @defgroup opus_multistream Opus Multistream API
+ * @{
+ *
+ * The multistream API allows individual Opus streams to be combined into a
+ * single packet, enabling support for up to 255 channels. Unlike an
+ * elementary Opus stream, the encoder and decoder must negotiate the channel
+ * configuration before the decoder can successfully interpret the data in the
+ * packets produced by the encoder. Some basic information, such as packet
+ * duration, can be computed without any special negotiation.
+ *
+ * The format for multistream Opus packets is defined in
+ * RFC 7845
+ * and is based on the self-delimited Opus framing described in Appendix B of
+ * RFC 6716.
+ * Normal Opus packets are just a degenerate case of multistream Opus packets,
+ * and can be encoded or decoded with the multistream API by setting
+ * streams
to 1
when initializing the encoder or
+ * decoder.
+ *
+ * Multistream Opus streams can contain up to 255 elementary Opus streams.
+ * These may be either "uncoupled" or "coupled", indicating that the decoder
+ * is configured to decode them to either 1 or 2 channels, respectively.
+ * The streams are ordered so that all coupled streams appear at the
+ * beginning.
+ *
+ * A mapping
table defines which decoded channel i
+ * should be used for each input/output (I/O) channel j
. This table is
+ * typically provided as an unsigned char array.
+ * Let i = mapping[j]
be the index for I/O channel j
.
+ * If i < 2*coupled_streams
, then I/O channel j
is
+ * encoded as the left channel of stream (i/2)
if i
+ * is even, or as the right channel of stream (i/2)
if
+ * i
is odd. Otherwise, I/O channel j
is encoded as
+ * mono in stream (i - coupled_streams)
, unless it has the special
+ * value 255, in which case it is omitted from the encoding entirely (the
+ * decoder will reproduce it as silence). Each value i
must either
+ * be the special value 255 or be less than streams + coupled_streams
.
+ *
+ * The output channels specified by the encoder
+ * should use the
+ * Vorbis
+ * channel ordering. A decoder may wish to apply an additional permutation
+ * to the mapping the encoder used to achieve a different output channel
+ * order (e.g. for outputing in WAV order).
+ *
+ * Each multistream packet contains an Opus packet for each stream, and all of
+ * the Opus packets in a single multistream packet must have the same
+ * duration. Therefore the duration of a multistream packet can be extracted
+ * from the TOC sequence of the first stream, which is located at the
+ * beginning of the packet, just like an elementary Opus stream:
+ *
+ * @code
+ * int nb_samples;
+ * int nb_frames;
+ * nb_frames = opus_packet_get_nb_frames(data, len);
+ * if (nb_frames < 1)
+ * return nb_frames;
+ * nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames;
+ * @endcode
+ *
+ * The general encoding and decoding process proceeds exactly the same as in
+ * the normal @ref opus_encoder and @ref opus_decoder APIs.
+ * See their documentation for an overview of how to use the corresponding
+ * multistream functions.
+ */
+
+/** Opus multistream encoder state.
+ * This contains the complete state of a multistream Opus encoder.
+ * It is position independent and can be freely copied.
+ * @see opus_multistream_encoder_create
+ * @see opus_multistream_encoder_init
+ */
+typedef struct OpusMSEncoder OpusMSEncoder;
+
+/** Opus multistream decoder state.
+ * This contains the complete state of a multistream Opus decoder.
+ * It is position independent and can be freely copied.
+ * @see opus_multistream_decoder_create
+ * @see opus_multistream_decoder_init
+ */
+typedef struct OpusMSDecoder OpusMSDecoder;
+
+/**\name Multistream encoder functions */
+/**@{*/
+
+/** Gets the size of an OpusMSEncoder structure.
+ * @param streams int: The total number of streams to encode from the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams int: Number of coupled (2 channel) streams
+ * to encode.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * encoded channels (streams +
+ * coupled_streams
) must be no
+ * more than 255.
+ * @returns The size in bytes on success, or a negative error code
+ * (see @ref opus_errorcodes) on error.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size(
+ int streams,
+ int coupled_streams
+);
+
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size(
+ int channels,
+ int mapping_family
+);
+
+
+/** Allocates and initializes a multistream encoder state.
+ * Call opus_multistream_encoder_destroy() to release
+ * this object when finished.
+ * @param Fs opus_int32: Sampling rate of the input signal (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels int: Number of channels in the input signal.
+ * This must be at most 255.
+ * It may be greater than the number of
+ * coded channels (streams +
+ * coupled_streams
).
+ * @param streams int: The total number of streams to encode from the
+ * input.
+ * This must be no more than the number of channels.
+ * @param coupled_streams int: Number of coupled (2 channel) streams
+ * to encode.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * encoded channels (streams +
+ * coupled_streams
) must be no
+ * more than the number of input channels.
+ * @param[in] mapping const unsigned char[channels]
: Mapping from
+ * encoded channels to input channels, as described in
+ * @ref opus_multistream. As an extra constraint, the
+ * multistream encoder does not allow encoding coupled
+ * streams for which one channel is unused since this
+ * is never a good idea.
+ * @param application int: The target encoder application.
+ * This must be one of the following:
+ *
+ * - #OPUS_APPLICATION_VOIP
+ * - Process signal for improved speech intelligibility.
+ * - #OPUS_APPLICATION_AUDIO
+ * - Favor faithfulness to the original input.
+ * - #OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ * - Configure the minimum possible coding delay by disabling certain modes
+ * of operation.
+ *
+ * @param[out] error int *: Returns #OPUS_OK on success, or an error
+ * code (see @ref opus_errorcodes) on
+ * failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create(
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ const unsigned char *mapping,
+ int application,
+ int *error
+) OPUS_ARG_NONNULL(5);
+
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create(
+ opus_int32 Fs,
+ int channels,
+ int mapping_family,
+ int *streams,
+ int *coupled_streams,
+ unsigned char *mapping,
+ int application,
+ int *error
+) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
+
+/** Initialize a previously allocated multistream encoder state.
+ * The memory pointed to by \a st must be at least the size returned by
+ * opus_multistream_encoder_get_size().
+ * This is intended for applications which use their own allocator instead of
+ * malloc.
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @see opus_multistream_encoder_create
+ * @see opus_multistream_encoder_get_size
+ * @param st OpusMSEncoder*: Multistream encoder state to initialize.
+ * @param Fs opus_int32: Sampling rate of the input signal (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels int: Number of channels in the input signal.
+ * This must be at most 255.
+ * It may be greater than the number of
+ * coded channels (streams +
+ * coupled_streams
).
+ * @param streams int: The total number of streams to encode from the
+ * input.
+ * This must be no more than the number of channels.
+ * @param coupled_streams int: Number of coupled (2 channel) streams
+ * to encode.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * encoded channels (streams +
+ * coupled_streams
) must be no
+ * more than the number of input channels.
+ * @param[in] mapping const unsigned char[channels]
: Mapping from
+ * encoded channels to input channels, as described in
+ * @ref opus_multistream. As an extra constraint, the
+ * multistream encoder does not allow encoding coupled
+ * streams for which one channel is unused since this
+ * is never a good idea.
+ * @param application int: The target encoder application.
+ * This must be one of the following:
+ *
+ * - #OPUS_APPLICATION_VOIP
+ * - Process signal for improved speech intelligibility.
+ * - #OPUS_APPLICATION_AUDIO
+ * - Favor faithfulness to the original input.
+ * - #OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ * - Configure the minimum possible coding delay by disabling certain modes
+ * of operation.
+ *
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+ * on failure.
+ */
+OPUS_EXPORT int opus_multistream_encoder_init(
+ OpusMSEncoder *st,
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ const unsigned char *mapping,
+ int application
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+
+OPUS_EXPORT int opus_multistream_surround_encoder_init(
+ OpusMSEncoder *st,
+ opus_int32 Fs,
+ int channels,
+ int mapping_family,
+ int *streams,
+ int *coupled_streams,
+ unsigned char *mapping,
+ int application
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7);
+
+/** Encodes a multistream Opus frame.
+ * @param st OpusMSEncoder*: Multistream encoder state.
+ * @param[in] pcm const opus_int16*: The input signal as interleaved
+ * samples.
+ * This must contain
+ * frame_size*channels
+ * samples.
+ * @param frame_size int: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data unsigned char*: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes opus_int32: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode(
+ OpusMSEncoder *st,
+ const opus_int16 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a multistream Opus frame from floating point input.
+ * @param st OpusMSEncoder*: Multistream encoder state.
+ * @param[in] pcm const float*: The input signal as interleaved
+ * samples with a normal range of
+ * +/-1.0.
+ * Samples with a range beyond +/-1.0
+ * are supported but will be clipped by
+ * decoders using the integer API and
+ * should only be used if it is known
+ * that the far end supports extended
+ * dynamic range.
+ * This must contain
+ * frame_size*channels
+ * samples.
+ * @param frame_size int: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data unsigned char*: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes opus_int32: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float(
+ OpusMSEncoder *st,
+ const float *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Frees an OpusMSEncoder
allocated by
+ * opus_multistream_encoder_create().
+ * @param st OpusMSEncoder*: Multistream encoder state to be freed.
+ */
+OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st);
+
+/** Perform a CTL function on a multistream Opus encoder.
+ *
+ * Generally the request and subsequent arguments are generated by a
+ * convenience macro.
+ * @param st OpusMSEncoder*: Multistream encoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls,
+ * @ref opus_encoderctls, or @ref opus_multistream_ctls.
+ * @see opus_genericctls
+ * @see opus_encoderctls
+ * @see opus_multistream_ctls
+ */
+OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/**@}*/
+
+/**\name Multistream decoder functions */
+/**@{*/
+
+/** Gets the size of an OpusMSDecoder
structure.
+ * @param streams int: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams int: Number streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (streams +
+ * coupled_streams
) must be no
+ * more than 255.
+ * @returns The size in bytes on success, or a negative error code
+ * (see @ref opus_errorcodes) on error.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size(
+ int streams,
+ int coupled_streams
+);
+
+/** Allocates and initializes a multistream decoder state.
+ * Call opus_multistream_decoder_destroy() to release
+ * this object when finished.
+ * @param Fs opus_int32: Sampling rate to decode at (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels int: Number of channels to output.
+ * This must be at most 255.
+ * It may be different from the number of coded
+ * channels (streams +
+ * coupled_streams
).
+ * @param streams int: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams int: Number of streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (streams +
+ * coupled_streams
) must be no
+ * more than 255.
+ * @param[in] mapping const unsigned char[channels]
: Mapping from
+ * coded channels to output channels, as described in
+ * @ref opus_multistream.
+ * @param[out] error int *: Returns #OPUS_OK on success, or an error
+ * code (see @ref opus_errorcodes) on
+ * failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create(
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ const unsigned char *mapping,
+ int *error
+) OPUS_ARG_NONNULL(5);
+
+/** Intialize a previously allocated decoder state object.
+ * The memory pointed to by \a st must be at least the size returned by
+ * opus_multistream_encoder_get_size().
+ * This is intended for applications which use their own allocator instead of
+ * malloc.
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @see opus_multistream_decoder_create
+ * @see opus_multistream_deocder_get_size
+ * @param st OpusMSEncoder*: Multistream encoder state to initialize.
+ * @param Fs opus_int32: Sampling rate to decode at (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels int: Number of channels to output.
+ * This must be at most 255.
+ * It may be different from the number of coded
+ * channels (streams +
+ * coupled_streams
).
+ * @param streams int: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams int: Number of streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (streams +
+ * coupled_streams
) must be no
+ * more than 255.
+ * @param[in] mapping const unsigned char[channels]
: Mapping from
+ * coded channels to output channels, as described in
+ * @ref opus_multistream.
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+ * on failure.
+ */
+OPUS_EXPORT int opus_multistream_decoder_init(
+ OpusMSDecoder *st,
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ const unsigned char *mapping
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+
+/** Decode a multistream Opus packet.
+ * @param st OpusMSDecoder*: Multistream decoder state.
+ * @param[in] data const unsigned char*: Input payload.
+ * Use a NULL
+ * pointer to indicate packet
+ * loss.
+ * @param len opus_int32: Number of bytes in payload.
+ * @param[out] pcm opus_int16*: Output signal, with interleaved
+ * samples.
+ * This must contain room for
+ * frame_size*channels
+ * samples.
+ * @param frame_size int: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * must be a multiple of 2.5 ms.
+ * @param decode_fec int: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode(
+ OpusMSDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int16 *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode a multistream Opus packet with floating point output.
+ * @param st OpusMSDecoder*: Multistream decoder state.
+ * @param[in] data const unsigned char*: Input payload.
+ * Use a NULL
+ * pointer to indicate packet
+ * loss.
+ * @param len opus_int32: Number of bytes in payload.
+ * @param[out] pcm opus_int16*: Output signal, with interleaved
+ * samples.
+ * This must contain room for
+ * frame_size*channels
+ * samples.
+ * @param frame_size int: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * must be a multiple of 2.5 ms.
+ * @param decode_fec int: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float(
+ OpusMSDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ float *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on a multistream Opus decoder.
+ *
+ * Generally the request and subsequent arguments are generated by a
+ * convenience macro.
+ * @param st OpusMSDecoder*: Multistream decoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls,
+ * @ref opus_decoderctls, or @ref opus_multistream_ctls.
+ * @see opus_genericctls
+ * @see opus_decoderctls
+ * @see opus_multistream_ctls
+ */
+OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/** Frees an OpusMSDecoder
allocated by
+ * opus_multistream_decoder_create().
+ * @param st OpusMSDecoder: Multistream decoder state to be freed.
+ */
+OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st);
+
+/**@}*/
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_MULTISTREAM_H */
diff --git a/library/opusencoder/src/main/cpp/opus/include/opus_projection.h b/library/opusencoder/src/main/cpp/opus/include/opus_projection.h
new file mode 100644
index 0000000000..9dabf4e85c
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/opus/include/opus_projection.h
@@ -0,0 +1,568 @@
+/* Copyright (c) 2017 Google Inc.
+ Written by Andrew Allen */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file opus_projection.h
+ * @brief Opus projection reference API
+ */
+
+#ifndef OPUS_PROJECTION_H
+#define OPUS_PROJECTION_H
+
+#include "opus_multistream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond OPUS_INTERNAL_DOC */
+
+/** These are the actual encoder and decoder CTL ID numbers.
+ * They should not be used directly by applications.c
+ * In general, SETs should be even and GETs should be odd.*/
+/**@{*/
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST 6001
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST 6003
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST 6005
+/**@}*/
+
+
+/** @endcond */
+
+/** @defgroup opus_projection_ctls Projection specific encoder and decoder CTLs
+ *
+ * These are convenience macros that are specific to the
+ * opus_projection_encoder_ctl() and opus_projection_decoder_ctl()
+ * interface.
+ * The CTLs from @ref opus_genericctls, @ref opus_encoderctls,
+ * @ref opus_decoderctls, and @ref opus_multistream_ctls may be applied to a
+ * projection encoder or decoder as well.
+ */
+/**@{*/
+
+/** Gets the gain (in dB. S7.8-format) of the demixing matrix from the encoder.
+ * @param[out] x opus_int32 *: Returns the gain (in dB. S7.8-format)
+ * of the demixing matrix.
+ * @hideinitializer
+ */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST, __opus_check_int_ptr(x)
+
+
+/** Gets the size in bytes of the demixing matrix from the encoder.
+ * @param[out] x opus_int32 *: Returns the size in bytes of the
+ * demixing matrix.
+ * @hideinitializer
+ */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, __opus_check_int_ptr(x)
+
+
+/** Copies the demixing matrix to the supplied pointer location.
+ * @param[out] x unsigned char *: Returns the demixing matrix to the
+ * supplied pointer location.
+ * @param y opus_int32: The size in bytes of the reserved memory at the
+ * pointer location.
+ * @hideinitializer
+ */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX(x,y) OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, x, __opus_check_int(y)
+
+
+/**@}*/
+
+/** Opus projection encoder state.
+ * This contains the complete state of a projection Opus encoder.
+ * It is position independent and can be freely copied.
+ * @see opus_projection_ambisonics_encoder_create
+ */
+typedef struct OpusProjectionEncoder OpusProjectionEncoder;
+
+
+/** Opus projection decoder state.
+ * This contains the complete state of a projection Opus decoder.
+ * It is position independent and can be freely copied.
+ * @see opus_projection_decoder_create
+ * @see opus_projection_decoder_init
+ */
+typedef struct OpusProjectionDecoder OpusProjectionDecoder;
+
+
+/**\name Projection encoder functions */
+/**@{*/
+
+/** Gets the size of an OpusProjectionEncoder structure.
+ * @param channels int: The total number of input channels to encode.
+ * This must be no more than 255.
+ * @param mapping_family int: The mapping family to use for selecting
+ * the appropriate projection.
+ * @returns The size in bytes on success, or a negative error code
+ * (see @ref opus_errorcodes) on error.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_ambisonics_encoder_get_size(
+ int channels,
+ int mapping_family
+);
+
+
+/** Allocates and initializes a projection encoder state.
+ * Call opus_projection_encoder_destroy() to release
+ * this object when finished.
+ * @param Fs opus_int32: Sampling rate of the input signal (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels int: Number of channels in the input signal.
+ * This must be at most 255.
+ * It may be greater than the number of
+ * coded channels (streams +
+ * coupled_streams
).
+ * @param mapping_family int: The mapping family to use for selecting
+ * the appropriate projection.
+ * @param[out] streams int *: The total number of streams that will
+ * be encoded from the input.
+ * @param[out] coupled_streams int *: Number of coupled (2 channel)
+ * streams that will be encoded from the input.
+ * @param application int: The target encoder application.
+ * This must be one of the following:
+ *
+ * - #OPUS_APPLICATION_VOIP
+ * - Process signal for improved speech intelligibility.
+ * - #OPUS_APPLICATION_AUDIO
+ * - Favor faithfulness to the original input.
+ * - #OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ * - Configure the minimum possible coding delay by disabling certain modes
+ * of operation.
+ *
+ * @param[out] error int *: Returns #OPUS_OK on success, or an error
+ * code (see @ref opus_errorcodes) on
+ * failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionEncoder *opus_projection_ambisonics_encoder_create(
+ opus_int32 Fs,
+ int channels,
+ int mapping_family,
+ int *streams,
+ int *coupled_streams,
+ int application,
+ int *error
+) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5);
+
+
+/** Initialize a previously allocated projection encoder state.
+ * The memory pointed to by \a st must be at least the size returned by
+ * opus_projection_ambisonics_encoder_get_size().
+ * This is intended for applications which use their own allocator instead of
+ * malloc.
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @see opus_projection_ambisonics_encoder_create
+ * @see opus_projection_ambisonics_encoder_get_size
+ * @param st OpusProjectionEncoder*: Projection encoder state to initialize.
+ * @param Fs opus_int32: Sampling rate of the input signal (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels int: Number of channels in the input signal.
+ * This must be at most 255.
+ * It may be greater than the number of
+ * coded channels (streams +
+ * coupled_streams
).
+ * @param streams int: The total number of streams to encode from the
+ * input.
+ * This must be no more than the number of channels.
+ * @param coupled_streams int: Number of coupled (2 channel) streams
+ * to encode.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * encoded channels (streams +
+ * coupled_streams
) must be no
+ * more than the number of input channels.
+ * @param application int: The target encoder application.
+ * This must be one of the following:
+ *
+ * - #OPUS_APPLICATION_VOIP
+ * - Process signal for improved speech intelligibility.
+ * - #OPUS_APPLICATION_AUDIO
+ * - Favor faithfulness to the original input.
+ * - #OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ * - Configure the minimum possible coding delay by disabling certain modes
+ * of operation.
+ *
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+ * on failure.
+ */
+OPUS_EXPORT int opus_projection_ambisonics_encoder_init(
+ OpusProjectionEncoder *st,
+ opus_int32 Fs,
+ int channels,
+ int mapping_family,
+ int *streams,
+ int *coupled_streams,
+ int application
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
+
+
+/** Encodes a projection Opus frame.
+ * @param st OpusProjectionEncoder*: Projection encoder state.
+ * @param[in] pcm const opus_int16*: The input signal as interleaved
+ * samples.
+ * This must contain
+ * frame_size*channels
+ * samples.
+ * @param frame_size int: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data unsigned char*: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes opus_int32: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode(
+ OpusProjectionEncoder *st,
+ const opus_int16 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+
+/** Encodes a projection Opus frame from floating point input.
+ * @param st OpusProjectionEncoder*: Projection encoder state.
+ * @param[in] pcm const float*: The input signal as interleaved
+ * samples with a normal range of
+ * +/-1.0.
+ * Samples with a range beyond +/-1.0
+ * are supported but will be clipped by
+ * decoders using the integer API and
+ * should only be used if it is known
+ * that the far end supports extended
+ * dynamic range.
+ * This must contain
+ * frame_size*channels
+ * samples.
+ * @param frame_size int: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data unsigned char*: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes opus_int32: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode_float(
+ OpusProjectionEncoder *st,
+ const float *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+
+/** Frees an OpusProjectionEncoder
allocated by
+ * opus_projection_ambisonics_encoder_create().
+ * @param st OpusProjectionEncoder*: Projection encoder state to be freed.
+ */
+OPUS_EXPORT void opus_projection_encoder_destroy(OpusProjectionEncoder *st);
+
+
+/** Perform a CTL function on a projection Opus encoder.
+ *
+ * Generally the request and subsequent arguments are generated by a
+ * convenience macro.
+ * @param st OpusProjectionEncoder*: Projection encoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls,
+ * @ref opus_encoderctls, @ref opus_multistream_ctls, or
+ * @ref opus_projection_ctls
+ * @see opus_genericctls
+ * @see opus_encoderctls
+ * @see opus_multistream_ctls
+ * @see opus_projection_ctls
+ */
+OPUS_EXPORT int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+
+/**@}*/
+
+/**\name Projection decoder functions */
+/**@{*/
+
+/** Gets the size of an OpusProjectionDecoder
structure.
+ * @param channels int: The total number of output channels.
+ * This must be no more than 255.
+ * @param streams int: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams int: Number streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (streams +
+ * coupled_streams
) must be no
+ * more than 255.
+ * @returns The size in bytes on success, or a negative error code
+ * (see @ref opus_errorcodes) on error.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_decoder_get_size(
+ int channels,
+ int streams,
+ int coupled_streams
+);
+
+
+/** Allocates and initializes a projection decoder state.
+ * Call opus_projection_decoder_destroy() to release
+ * this object when finished.
+ * @param Fs opus_int32: Sampling rate to decode at (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels int: Number of channels to output.
+ * This must be at most 255.
+ * It may be different from the number of coded
+ * channels (streams +
+ * coupled_streams
).
+ * @param streams int: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams int: Number of streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (streams +
+ * coupled_streams
) must be no
+ * more than 255.
+ * @param[in] demixing_matrix const unsigned char[demixing_matrix_size]: Demixing matrix
+ * that mapping from coded channels to output channels,
+ * as described in @ref opus_projection and
+ * @ref opus_projection_ctls.
+ * @param demixing_matrix_size opus_int32: The size in bytes of the
+ * demixing matrix, as
+ * described in @ref
+ * opus_projection_ctls.
+ * @param[out] error int *: Returns #OPUS_OK on success, or an error
+ * code (see @ref opus_errorcodes) on
+ * failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionDecoder *opus_projection_decoder_create(
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ unsigned char *demixing_matrix,
+ opus_int32 demixing_matrix_size,
+ int *error
+) OPUS_ARG_NONNULL(5);
+
+
+/** Intialize a previously allocated projection decoder state object.
+ * The memory pointed to by \a st must be at least the size returned by
+ * opus_projection_decoder_get_size().
+ * This is intended for applications which use their own allocator instead of
+ * malloc.
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @see opus_projection_decoder_create
+ * @see opus_projection_deocder_get_size
+ * @param st OpusProjectionDecoder*: Projection encoder state to initialize.
+ * @param Fs opus_int32: Sampling rate to decode at (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels int: Number of channels to output.
+ * This must be at most 255.
+ * It may be different from the number of coded
+ * channels (streams +
+ * coupled_streams
).
+ * @param streams int: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams int: Number of streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (streams +
+ * coupled_streams
) must be no
+ * more than 255.
+ * @param[in] demixing_matrix const unsigned char[demixing_matrix_size]: Demixing matrix
+ * that mapping from coded channels to output channels,
+ * as described in @ref opus_projection and
+ * @ref opus_projection_ctls.
+ * @param demixing_matrix_size opus_int32: The size in bytes of the
+ * demixing matrix, as
+ * described in @ref
+ * opus_projection_ctls.
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+ * on failure.
+ */
+OPUS_EXPORT int opus_projection_decoder_init(
+ OpusProjectionDecoder *st,
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ unsigned char *demixing_matrix,
+ opus_int32 demixing_matrix_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+
+
+/** Decode a projection Opus packet.
+ * @param st OpusProjectionDecoder*: Projection decoder state.
+ * @param[in] data const unsigned char*: Input payload.
+ * Use a NULL
+ * pointer to indicate packet
+ * loss.
+ * @param len opus_int32: Number of bytes in payload.
+ * @param[out] pcm opus_int16*: Output signal, with interleaved
+ * samples.
+ * This must contain room for
+ * frame_size*channels
+ * samples.
+ * @param frame_size int: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * must be a multiple of 2.5 ms.
+ * @param decode_fec int: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode(
+ OpusProjectionDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int16 *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+
+/** Decode a projection Opus packet with floating point output.
+ * @param st OpusProjectionDecoder*: Projection decoder state.
+ * @param[in] data const unsigned char*: Input payload.
+ * Use a NULL
+ * pointer to indicate packet
+ * loss.
+ * @param len opus_int32: Number of bytes in payload.
+ * @param[out] pcm opus_int16*: Output signal, with interleaved
+ * samples.
+ * This must contain room for
+ * frame_size*channels
+ * samples.
+ * @param frame_size int: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * must be a multiple of 2.5 ms.
+ * @param decode_fec int: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode_float(
+ OpusProjectionDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ float *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+
+/** Perform a CTL function on a projection Opus decoder.
+ *
+ * Generally the request and subsequent arguments are generated by a
+ * convenience macro.
+ * @param st OpusProjectionDecoder*: Projection decoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls,
+ * @ref opus_decoderctls, @ref opus_multistream_ctls, or
+ * @ref opus_projection_ctls.
+ * @see opus_genericctls
+ * @see opus_decoderctls
+ * @see opus_multistream_ctls
+ * @see opus_projection_ctls
+ */
+OPUS_EXPORT int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+
+/** Frees an OpusProjectionDecoder
allocated by
+ * opus_projection_decoder_create().
+ * @param st OpusProjectionDecoder: Projection decoder state to be freed.
+ */
+OPUS_EXPORT void opus_projection_decoder_destroy(OpusProjectionDecoder *st);
+
+
+/**@}*/
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_PROJECTION_H */
diff --git a/library/opusencoder/src/main/cpp/opus/include/opus_types.h b/library/opusencoder/src/main/cpp/opus/include/opus_types.h
new file mode 100644
index 0000000000..7cf675580f
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/opus/include/opus_types.h
@@ -0,0 +1,166 @@
+/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */
+/* Modified by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/* opus_types.h based on ogg_types.h from libogg */
+
+/**
+ @file opus_types.h
+ @brief Opus reference implementation types
+*/
+#ifndef OPUS_TYPES_H
+#define OPUS_TYPES_H
+
+#define opus_int int /* used for counters etc; at least 16 bits */
+#define opus_int64 long long
+#define opus_int8 signed char
+
+#define opus_uint unsigned int /* used for counters etc; at least 16 bits */
+#define opus_uint64 unsigned long long
+#define opus_uint8 unsigned char
+
+/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
+#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
+#include
+# undef opus_int64
+# undef opus_int8
+# undef opus_uint64
+# undef opus_uint8
+ typedef int8_t opus_int8;
+ typedef uint8_t opus_uint8;
+ typedef int16_t opus_int16;
+ typedef uint16_t opus_uint16;
+ typedef int32_t opus_int32;
+ typedef uint32_t opus_uint32;
+ typedef int64_t opus_int64;
+ typedef uint64_t opus_uint64;
+#elif defined(_WIN32)
+
+# if defined(__CYGWIN__)
+# include <_G_config.h>
+ typedef _G_int32_t opus_int32;
+ typedef _G_uint32_t opus_uint32;
+ typedef _G_int16 opus_int16;
+ typedef _G_uint16 opus_uint16;
+# elif defined(__MINGW32__)
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+# elif defined(__MWERKS__)
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+# else
+ /* MSVC/Borland */
+ typedef __int32 opus_int32;
+ typedef unsigned __int32 opus_uint32;
+ typedef __int16 opus_int16;
+ typedef unsigned __int16 opus_uint16;
+# endif
+
+#elif defined(__MACOS__)
+
+# include
+ typedef SInt16 opus_int16;
+ typedef UInt16 opus_uint16;
+ typedef SInt32 opus_int32;
+ typedef UInt32 opus_uint32;
+
+#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
+
+# include
+ typedef int16_t opus_int16;
+ typedef u_int16_t opus_uint16;
+ typedef int32_t opus_int32;
+ typedef u_int32_t opus_uint32;
+
+#elif defined(__BEOS__)
+
+ /* Be */
+# include
+ typedef int16 opus_int16;
+ typedef u_int16 opus_uint16;
+ typedef int32_t opus_int32;
+ typedef u_int32_t opus_uint32;
+
+#elif defined (__EMX__)
+
+ /* OS/2 GCC */
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+
+#elif defined (DJGPP)
+
+ /* DJGPP */
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+
+#elif defined(R5900)
+
+ /* PS2 EE */
+ typedef int opus_int32;
+ typedef unsigned opus_uint32;
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+
+#elif defined(__SYMBIAN32__)
+
+ /* Symbian GCC */
+ typedef signed short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef signed int opus_int32;
+ typedef unsigned int opus_uint32;
+
+#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef long opus_int32;
+ typedef unsigned long opus_uint32;
+
+#elif defined(CONFIG_TI_C6X)
+
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+
+#else
+
+ /* Give up, take a reasonable guess */
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+
+#endif
+
+#endif /* OPUS_TYPES_H */
diff --git a/library/opusencoder/src/main/cpp/opus/include/opusenc.h b/library/opusencoder/src/main/cpp/opus/include/opusenc.h
new file mode 100644
index 0000000000..ca1a5efe8e
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/opus/include/opusenc.h
@@ -0,0 +1,358 @@
+/* Copyright (c) 2017 Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#if !defined(_opusenc_h)
+# define _opusenc_h (1)
+
+/**\mainpage
+ \section Introduction
+
+ This is the documentation for the libopusenc C API.
+
+ The libopusenc package provides a convenient high-level API for
+ encoding Ogg Opus files.
+
+ \section Organization
+
+ The main API is divided into several sections:
+ - \ref encoding
+ - \ref comments
+ - \ref encoder_ctl
+ - \ref callbacks
+ - \ref error_codes
+
+ \section Overview
+
+ The libopusfile API provides an easy way to encode Ogg Opus files using
+ libopus.
+*/
+
+# if defined(__cplusplus)
+extern "C" {
+# endif
+
+#include
+
+#ifndef OPE_EXPORT
+# if defined(WIN32)
+# if defined(OPE_BUILD) && defined(DLL_EXPORT)
+# define OPE_EXPORT __declspec(dllexport)
+# else
+# define OPE_EXPORT
+# endif
+# elif defined(__GNUC__) && defined(OPE_BUILD)
+# define OPE_EXPORT __attribute__ ((visibility ("default")))
+# else
+# define OPE_EXPORT
+# endif
+#endif
+
+/**\defgroup error_codes Error Codes*/
+/*@{*/
+/**\name List of possible error codes
+ Many of the functions in this library return a negative error code when a
+ function fails.
+ This list provides a brief explanation of the common errors.
+ See each individual function for more details on what a specific error code
+ means in that context.*/
+/*@{*/
+
+
+/* Bump this when we change the API. */
+/** API version for this header. Can be used to check for features at compile time. */
+#define OPE_API_VERSION 0
+
+#define OPE_OK 0
+/* Based on the relevant libopus code minus 10. */
+#define OPE_BAD_ARG -11
+#define OPE_INTERNAL_ERROR -13
+#define OPE_UNIMPLEMENTED -15
+#define OPE_ALLOC_FAIL -17
+
+/* Specific to libopusenc. */
+#define OPE_CANNOT_OPEN -30
+#define OPE_TOO_LATE -31
+#define OPE_UNRECOVERABLE -32
+#define OPE_INVALID_PICTURE -33
+#define OPE_INVALID_ICON -34
+/*@}*/
+/*@}*/
+
+
+/* These are the "raw" request values -- they should usually not be used. */
+#define OPE_SET_DECISION_DELAY_REQUEST 14000
+#define OPE_GET_DECISION_DELAY_REQUEST 14001
+#define OPE_SET_MUXING_DELAY_REQUEST 14002
+#define OPE_GET_MUXING_DELAY_REQUEST 14003
+#define OPE_SET_COMMENT_PADDING_REQUEST 14004
+#define OPE_GET_COMMENT_PADDING_REQUEST 14005
+#define OPE_SET_SERIALNO_REQUEST 14006
+#define OPE_GET_SERIALNO_REQUEST 14007
+#define OPE_SET_PACKET_CALLBACK_REQUEST 14008
+/*#define OPE_GET_PACKET_CALLBACK_REQUEST 14009*/
+#define OPE_SET_HEADER_GAIN_REQUEST 14010
+#define OPE_GET_HEADER_GAIN_REQUEST 14011
+
+/**\defgroup encoder_ctl Encoding Options*/
+/*@{*/
+
+/**\name Control parameters
+
+ Macros for setting encoder options.*/
+/*@{*/
+
+#define OPE_SET_DECISION_DELAY(x) OPE_SET_DECISION_DELAY_REQUEST, __opus_check_int(x)
+#define OPE_GET_DECISION_DELAY(x) OPE_GET_DECISION_DELAY_REQUEST, __opus_check_int_ptr(x)
+#define OPE_SET_MUXING_DELAY(x) OPE_SET_MUXING_DELAY_REQUEST, __opus_check_int(x)
+#define OPE_GET_MUXING_DELAY(x) OPE_GET_MUXING_DELAY_REQUEST, __opus_check_int_ptr(x)
+#define OPE_SET_COMMENT_PADDING(x) OPE_SET_COMMENT_PADDING_REQUEST, __opus_check_int(x)
+#define OPE_GET_COMMENT_PADDING(x) OPE_GET_COMMENT_PADDING_REQUEST, __opus_check_int_ptr(x)
+#define OPE_SET_SERIALNO(x) OPE_SET_SERIALNO_REQUEST, __opus_check_int(x)
+#define OPE_GET_SERIALNO(x) OPE_GET_SERIALNO_REQUEST, __opus_check_int_ptr(x)
+/* FIXME: Add type-checking macros to these. */
+#define OPE_SET_PACKET_CALLBACK(x,u) OPE_SET_PACKET_CALLBACK_REQUEST, (x), (u)
+/*#define OPE_GET_PACKET_CALLBACK(x,u) OPE_GET_PACKET_CALLBACK_REQUEST, (x), (u)*/
+#define OPE_SET_HEADER_GAIN(x,u) OPE_SET_HEADER_GAIN_REQUEST, __opus_check_int(x)
+#define OPE_GET_HEADER_GAIN(x,u) OPE_GET_HEADER_GAIN_REQUEST, __opus_check_int_ptr(x)
+/*@}*/
+/*@}*/
+
+/**\defgroup callbacks Callback Functions */
+/*@{*/
+
+/**\name Callback functions
+
+ These are the callbacks that can be implemented for an encoder.*/
+/*@{*/
+
+/** Called for writing a page. */
+typedef int (*ope_write_func)(void *user_data, const unsigned char *ptr, opus_int32 len);
+
+/** Called for closing a stream. */
+typedef int (*ope_close_func)(void *user_data);
+
+/** Called on every packet encoded (including header). */
+typedef int (*ope_packet_func)(void *user_data, const unsigned char *packet_ptr, opus_int32 packet_len, opus_uint32 flags);
+
+/** Callback functions for accessing the stream. */
+typedef struct {
+ /** Callback for writing to the stream. */
+ ope_write_func write;
+ /** Callback for closing the stream. */
+ ope_close_func close;
+} OpusEncCallbacks;
+/*@}*/
+/*@}*/
+
+/** Opaque comments struct. */
+typedef struct OggOpusComments OggOpusComments;
+
+/** Opaque encoder struct. */
+typedef struct OggOpusEnc OggOpusEnc;
+
+/**\defgroup comments Comments Handling */
+/*@{*/
+
+/**\name Functions for handling comments
+
+ These functions make it possible to add comments and pictures to Ogg Opus files.*/
+/*@{*/
+
+/** Create a new comments object.
+ \return Newly-created comments object. */
+OPE_EXPORT OggOpusComments *ope_comments_create(void);
+
+/** Create a deep copy of a comments object.
+ \param comments Comments object to copy
+ \return Deep copy of input. */
+OPE_EXPORT OggOpusComments *ope_comments_copy(OggOpusComments *comments);
+
+/** Destroys a comments object.
+ \param comments Comments object to destroy*/
+OPE_EXPORT void ope_comments_destroy(OggOpusComments *comments);
+
+/** Add a comment.
+ \param[in,out] comments Where to add the comments
+ \param tag Tag for the comment (must not contain = char)
+ \param val Value for the tag
+ \return Error code
+ */
+OPE_EXPORT int ope_comments_add(OggOpusComments *comments, const char *tag, const char *val);
+
+/** Add a comment as a single tag=value string.
+ \param[in,out] comments Where to add the comments
+ \param tag_and_val string of the form tag=value (must contain = char)
+ \return Error code
+ */
+OPE_EXPORT int ope_comments_add_string(OggOpusComments *comments, const char *tag_and_val);
+
+/** Add a picture.
+ \param[in,out] comments Where to add the comments
+ \param filename File name for the picture
+ \param picture_type Type of picture (-1 for default)
+ \param description Description (NULL means no comment)
+ \return Error code
+ */
+OPE_EXPORT int ope_comments_add_picture(OggOpusComments *comments, const char *filename, int picture_type, const char *description);
+
+/*@}*/
+/*@}*/
+
+/**\defgroup encoding Encoding */
+/*@{*/
+
+/**\name Functions for encoding Ogg Opus files
+
+ These functions make it possible to encode Ogg Opus files.*/
+/*@{*/
+
+/** Create a new OggOpus file.
+ \param path Path where to create the file
+ \param comments Comments associated with the stream
+ \param rate Input sampling rate (48 kHz is faster)
+ \param channels Number of channels
+ \param family Mapping family (0 for mono/stereo, 1 for surround)
+ \param[out] error Error code (NULL if no error is to be returned)
+ \return Newly-created encoder.
+ */
+OPE_EXPORT OggOpusEnc *ope_encoder_create_file(const char *path, OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error);
+
+/** Create a new OggOpus stream to be handled using callbacks
+ \param callbacks Callback functions
+ \param user_data Pointer to be associated with the stream and passed to the callbacks
+ \param comments Comments associated with the stream
+ \param rate Input sampling rate (48 kHz is faster)
+ \param channels Number of channels
+ \param family Mapping family (0 for mono/stereo, 1 for surround)
+ \param[out] error Error code (NULL if no error is to be returned)
+ \return Newly-created encoder.
+ */
+OPE_EXPORT OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void *user_data,
+ OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error);
+
+/** Create a new OggOpus stream to be used along with.ope_encoder_get_page().
+ This is mostly useful for muxing with other streams.
+ \param comments Comments associated with the stream
+ \param rate Input sampling rate (48 kHz is faster)
+ \param channels Number of channels
+ \param family Mapping family (0 for mono/stereo, 1 for surround)
+ \param[out] error Error code (NULL if no error is to be returned)
+ \return Newly-created encoder.
+ */
+OPE_EXPORT OggOpusEnc *ope_encoder_create_pull(OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error);
+
+/** Add/encode any number of float samples to the stream.
+ \param[in,out] enc Encoder
+ \param pcm Floating-point PCM values in the +/-1 range (interleaved if multiple channels)
+ \param samples_per_channel Number of samples for each channel
+ \return Error code*/
+OPE_EXPORT int ope_encoder_write_float(OggOpusEnc *enc, const float *pcm, int samples_per_channel);
+
+/** Add/encode any number of 16-bit linear samples to the stream.
+ \param[in,out] enc Encoder
+ \param pcm Linear 16-bit PCM values in the [-32768,32767] range (interleaved if multiple channels)
+ \param samples_per_channel Number of samples for each channel
+ \return Error code*/
+OPE_EXPORT int ope_encoder_write(OggOpusEnc *enc, const opus_int16 *pcm, int samples_per_channel);
+
+/** Get the next page from the stream (only if using ope_encoder_create_pull()).
+ \param[in,out] enc Encoder
+ \param[out] page Next available encoded page
+ \param[out] len Size (in bytes) of the page returned
+ \param flush If non-zero, forces a flush of the page (if any data avaiable)
+ \return 1 if there is a page available, 0 if not. */
+OPE_EXPORT int ope_encoder_get_page(OggOpusEnc *enc, unsigned char **page, opus_int32 *len, int flush);
+
+/** Finalizes the stream, but does not deallocate the object.
+ \param[in,out] enc Encoder
+ \return Error code
+ */
+OPE_EXPORT int ope_encoder_drain(OggOpusEnc *enc);
+
+/** Deallocates the obect. Make sure to ope_drain() first.
+ \param[in,out] enc Encoder
+ */
+OPE_EXPORT void ope_encoder_destroy(OggOpusEnc *enc);
+
+/** Ends the stream and create a new stream within the same file.
+ \param[in,out] enc Encoder
+ \param comments Comments associated with the stream
+ \return Error code
+ */
+OPE_EXPORT int ope_encoder_chain_current(OggOpusEnc *enc, OggOpusComments *comments);
+
+/** Ends the stream and create a new file.
+ \param[in,out] enc Encoder
+ \param path Path where to write the new file
+ \param comments Comments associated with the stream
+ \return Error code
+ */
+OPE_EXPORT int ope_encoder_continue_new_file(OggOpusEnc *enc, const char *path, OggOpusComments *comments);
+
+/** Ends the stream and create a new file (callback-based).
+ \param[in,out] enc Encoder
+ \param user_data Pointer to be associated with the new stream and passed to the callbacks
+ \param comments Comments associated with the stream
+ \return Error code
+ */
+OPE_EXPORT int ope_encoder_continue_new_callbacks(OggOpusEnc *enc, void *user_data, OggOpusComments *comments);
+
+/** Write out the header now rather than wait for audio to begin.
+ \param[in,out] enc Encoder
+ \return Error code
+ */
+OPE_EXPORT int ope_encoder_flush_header(OggOpusEnc *enc);
+
+/** Sets encoder options.
+ \param[in,out] enc Encoder
+ \param request Use a request macro
+ \return Error code
+ */
+OPE_EXPORT int ope_encoder_ctl(OggOpusEnc *enc, int request, ...);
+
+/** Converts a libopusenc error code into a human readable string.
+ *
+ * @param error Error number
+ * @returns Error string
+ */
+OPE_EXPORT const char *ope_strerror(int error);
+
+/** Returns a string representing the version of libopusenc being used at run time.
+ \return A string describing the version of this library */
+OPE_EXPORT const char *ope_get_version_string(void);
+
+/** ABI version for this header. Can be used to check for features at run time.
+ \return An integer representing the ABI version */
+OPE_EXPORT int ope_get_abi_version(void);
+
+/*@}*/
+/*@}*/
+
+# if defined(__cplusplus)
+}
+# endif
+
+#endif
diff --git a/library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopus.so b/library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopus.so
new file mode 100755
index 0000000000..466c1df13a
Binary files /dev/null and b/library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopus.so differ
diff --git a/library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopusenc.so b/library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopusenc.so
new file mode 100755
index 0000000000..9389efd919
Binary files /dev/null and b/library/opusencoder/src/main/cpp/opus/libs/arm64-v8a/libopusenc.so differ
diff --git a/library/opusencoder/src/main/cpp/opus/libs/armeabi-v7a/libopus.so b/library/opusencoder/src/main/cpp/opus/libs/armeabi-v7a/libopus.so
new file mode 100755
index 0000000000..d4bb6d427e
Binary files /dev/null and b/library/opusencoder/src/main/cpp/opus/libs/armeabi-v7a/libopus.so differ
diff --git a/library/opusencoder/src/main/cpp/opus/libs/armeabi-v7a/libopusenc.so b/library/opusencoder/src/main/cpp/opus/libs/armeabi-v7a/libopusenc.so
new file mode 100755
index 0000000000..655f296d90
Binary files /dev/null and b/library/opusencoder/src/main/cpp/opus/libs/armeabi-v7a/libopusenc.so differ
diff --git a/library/opusencoder/src/main/cpp/opus/libs/x86/libopus.so b/library/opusencoder/src/main/cpp/opus/libs/x86/libopus.so
new file mode 100755
index 0000000000..0acf14474b
Binary files /dev/null and b/library/opusencoder/src/main/cpp/opus/libs/x86/libopus.so differ
diff --git a/library/opusencoder/src/main/cpp/opus/libs/x86/libopusenc.so b/library/opusencoder/src/main/cpp/opus/libs/x86/libopusenc.so
new file mode 100755
index 0000000000..f862ea15f7
Binary files /dev/null and b/library/opusencoder/src/main/cpp/opus/libs/x86/libopusenc.so differ
diff --git a/library/opusencoder/src/main/cpp/opus/libs/x86_64/libopus.so b/library/opusencoder/src/main/cpp/opus/libs/x86_64/libopus.so
new file mode 100755
index 0000000000..1480c8c586
Binary files /dev/null and b/library/opusencoder/src/main/cpp/opus/libs/x86_64/libopus.so differ
diff --git a/library/opusencoder/src/main/cpp/opus/libs/x86_64/libopusenc.so b/library/opusencoder/src/main/cpp/opus/libs/x86_64/libopusenc.so
new file mode 100755
index 0000000000..f744374fe0
Binary files /dev/null and b/library/opusencoder/src/main/cpp/opus/libs/x86_64/libopusenc.so differ
diff --git a/library/opusencoder/src/main/cpp/opuscodec.cpp b/library/opusencoder/src/main/cpp/opuscodec.cpp
new file mode 100644
index 0000000000..51bd656c5d
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/opuscodec.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include "codec/CodecOggOpus.h"
+
+CodecOggOpus oggCodec;
+
+extern "C"
+JNIEXPORT jint JNICALL Java_im_vector_opusencoder_OggOpusEncoder_init(JNIEnv *env, jobject thiz, jstring file_path, jint sample_rate) {
+ char *path = (char*) env->GetStringUTFChars(file_path, 0);
+ return oggCodec.encoderInit(path, sample_rate);
+}
+
+extern "C"
+JNIEXPORT jint JNICALL Java_im_vector_opusencoder_OggOpusEncoder_writeFrame(JNIEnv *env, jobject thiz, jshortArray shorts, jint samples_per_channel) {
+ jshort *nativeShorts = env->GetShortArrayElements(shorts, 0);
+ return oggCodec.writeFrame((short *) nativeShorts, samples_per_channel);
+}
+
+extern "C"
+JNIEXPORT jint JNICALL Java_im_vector_opusencoder_OggOpusEncoder_setBitrate(JNIEnv *env, jobject thiz, jint bitrate) {
+ return oggCodec.setBitrate(bitrate);
+}
+
+extern "C"
+JNIEXPORT void JNICALL Java_im_vector_opusencoder_OggOpusEncoder_encoderRelease(JNIEnv *env, jobject thiz) {
+ oggCodec.encoderRelease();
+}
diff --git a/library/opusencoder/src/main/cpp/utils/Logger.h b/library/opusencoder/src/main/cpp/utils/Logger.h
new file mode 100644
index 0000000000..9efdc51d41
--- /dev/null
+++ b/library/opusencoder/src/main/cpp/utils/Logger.h
@@ -0,0 +1,11 @@
+#ifndef ANDROIDOPUSENCODER_LOGGER_H
+#define ANDROIDOPUSENCODER_LOGGER_H
+#include
+
+
+#define LOGE(tag, ...) __android_log_print(ANDROID_LOG_ERROR, tag, __VA_ARGS__)
+#define LOGW(tag, ...) __android_log_print(ANDROID_LOG_WARN, tag, __VA_ARGS__)
+#define LOGI(tag, ...) __android_log_print(ANDROID_LOG_INFO, tag, __VA_ARGS__)
+#define LOGD(tag, ...) __android_log_print(ANDROID_LOG_DEBUG, tag, __VA_ARGS__)
+
+#endif //ANDROIDOPUSENCODER_LOGGER_H
diff --git a/library/opusencoder/src/main/java/im/vector/opusencoder/OggOpusEncoder.kt b/library/opusencoder/src/main/java/im/vector/opusencoder/OggOpusEncoder.kt
new file mode 100644
index 0000000000..8af11f8516
--- /dev/null
+++ b/library/opusencoder/src/main/java/im/vector/opusencoder/OggOpusEncoder.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.opusencoder
+
+import android.util.Log
+import androidx.annotation.IntRange
+import im.vector.opusencoder.configuration.SampleRate
+
+/**
+ * JNI bridge to CodecOggOpus in the native opuscodec library.
+ */
+class OggOpusEncoder {
+
+ companion object {
+
+ private const val TAG = "OggOpusEncoder"
+
+ init {
+ try {
+ System.loadLibrary("opuscodec")
+ } catch (e: Exception) {
+ Log.e(TAG, "Couldn't load opus library: $e")
+ }
+ }
+ }
+
+ fun init(filePath: String, sampleRate: SampleRate): Int {
+ return init(filePath, sampleRate.value)
+ }
+ private external fun init(filePath: String, sampleRate: Int): Int
+
+ external fun setBitrate(@IntRange(from = 500, to = 512000) bitrate: Int): Int
+
+ fun encode(shorts: ShortArray, samplesPerChannel: Int): Int {
+ return writeFrame(shorts, samplesPerChannel)
+ }
+ private external fun writeFrame(shorts: ShortArray, samplesPerChannel: Int): Int
+
+ fun release() {
+ encoderRelease()
+ }
+ private external fun encoderRelease()
+}
diff --git a/library/opusencoder/src/main/java/im/vector/opusencoder/configuration/SampleRate.kt b/library/opusencoder/src/main/java/im/vector/opusencoder/configuration/SampleRate.kt
new file mode 100644
index 0000000000..e1a8f10725
--- /dev/null
+++ b/library/opusencoder/src/main/java/im/vector/opusencoder/configuration/SampleRate.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.opusencoder.configuration
+
+/**
+ * Sampling rate of the input signal in Hz.
+ */
+sealed class SampleRate private constructor(val value: Int) {
+ object Rate8khz : SampleRate(8000)
+ object Rate12kHz : SampleRate(12000)
+ object Rate16kHz : SampleRate(16000)
+ object Rate24KHz : SampleRate(24000)
+ object Rate48kHz : SampleRate(48000)
+}
diff --git a/library/ui-styles/build.gradle b/library/ui-styles/build.gradle
index 75ae46f151..b96e8ad76c 100644
--- a/library/ui-styles/build.gradle
+++ b/library/ui-styles/build.gradle
@@ -53,8 +53,6 @@ dependencies {
implementation libs.google.material
// Pref theme
implementation libs.androidx.preferenceKtx
- // PFLockScreen attrs
- implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta12'
// dialpad dimen
implementation 'im.dlg:android-dialer:1.2.5'
}
diff --git a/library/ui-styles/src/main/res/drawable/lockscreen_background.xml b/library/ui-styles/src/main/res/drawable/lockscreen_background.xml
new file mode 100644
index 0000000000..5688c433f7
--- /dev/null
+++ b/library/ui-styles/src/main/res/drawable/lockscreen_background.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/library/ui-styles/src/main/res/drawable/lockscreen_circle_background.xml b/library/ui-styles/src/main/res/drawable/lockscreen_circle_background.xml
new file mode 100644
index 0000000000..87fa99063c
--- /dev/null
+++ b/library/ui-styles/src/main/res/drawable/lockscreen_circle_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/ui-styles/src/main/res/drawable/lockscreen_circle_code_empty.xml b/library/ui-styles/src/main/res/drawable/lockscreen_circle_code_empty.xml
new file mode 100644
index 0000000000..abde6087e0
--- /dev/null
+++ b/library/ui-styles/src/main/res/drawable/lockscreen_circle_code_empty.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/drawable/lockscreen_circle_code_fill.xml b/library/ui-styles/src/main/res/drawable/lockscreen_circle_code_fill.xml
new file mode 100644
index 0000000000..e3f1082324
--- /dev/null
+++ b/library/ui-styles/src/main/res/drawable/lockscreen_circle_code_fill.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/drawable/lockscreen_circle_key_selector.xml b/library/ui-styles/src/main/res/drawable/lockscreen_circle_key_selector.xml
new file mode 100644
index 0000000000..3fdebfbbe0
--- /dev/null
+++ b/library/ui-styles/src/main/res/drawable/lockscreen_circle_key_selector.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/ui-styles/src/main/res/drawable/lockscreen_code_selector.xml b/library/ui-styles/src/main/res/drawable/lockscreen_code_selector.xml
new file mode 100644
index 0000000000..5de4957a3b
--- /dev/null
+++ b/library/ui-styles/src/main/res/drawable/lockscreen_code_selector.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/drawable/lockscreen_delete.xml b/library/ui-styles/src/main/res/drawable/lockscreen_delete.xml
new file mode 100644
index 0000000000..e1d70e8f41
--- /dev/null
+++ b/library/ui-styles/src/main/res/drawable/lockscreen_delete.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/library/ui-styles/src/main/res/drawable/lockscreen_fingerprint.xml b/library/ui-styles/src/main/res/drawable/lockscreen_fingerprint.xml
new file mode 100644
index 0000000000..7f0abe850a
--- /dev/null
+++ b/library/ui-styles/src/main/res/drawable/lockscreen_fingerprint.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/library/ui-styles/src/main/res/drawable/lockscreen_side_button_background.xml b/library/ui-styles/src/main/res/drawable/lockscreen_side_button_background.xml
new file mode 100644
index 0000000000..b205b2d91c
--- /dev/null
+++ b/library/ui-styles/src/main/res/drawable/lockscreen_side_button_background.xml
@@ -0,0 +1,29 @@
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+ -
+
+
+
+ -
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/drawable/lockscreen_touch_selector.xml b/library/ui-styles/src/main/res/drawable/lockscreen_touch_selector.xml
new file mode 100644
index 0000000000..141f2ac698
--- /dev/null
+++ b/library/ui-styles/src/main/res/drawable/lockscreen_touch_selector.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/values-land/lockscreen_default_dimen.xml b/library/ui-styles/src/main/res/values-land/lockscreen_default_dimen.xml
new file mode 100644
index 0000000000..2ae3ca0689
--- /dev/null
+++ b/library/ui-styles/src/main/res/values-land/lockscreen_default_dimen.xml
@@ -0,0 +1,5 @@
+
+
+ 60dp
+ 15dp
+
diff --git a/library/ui-styles/src/main/res/values/dimens_font.xml b/library/ui-styles/src/main/res/values/dimens_font.xml
index 1b5a826acb..ad8f012a16 100644
--- a/library/ui-styles/src/main/res/values/dimens_font.xml
+++ b/library/ui-styles/src/main/res/values/dimens_font.xml
@@ -7,7 +7,8 @@
14sp
12sp
10sp
+ 8sp
14sp
-
\ No newline at end of file
+
diff --git a/library/ui-styles/src/main/res/values/lockscreen_attr.xml b/library/ui-styles/src/main/res/values/lockscreen_attr.xml
new file mode 100644
index 0000000000..64e77d3c4e
--- /dev/null
+++ b/library/ui-styles/src/main/res/values/lockscreen_attr.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/values/lockscreen_default_colors.xml b/library/ui-styles/src/main/res/values/lockscreen_default_colors.xml
new file mode 100644
index 0000000000..eb9115d636
--- /dev/null
+++ b/library/ui-styles/src/main/res/values/lockscreen_default_colors.xml
@@ -0,0 +1,8 @@
+
+
+ #ffffff
+ #66ffffff
+ #42000000
+ #f4511e
+ #009688
+
diff --git a/library/ui-styles/src/main/res/values/lockscreen_default_dimens.xml b/library/ui-styles/src/main/res/values/lockscreen_default_dimens.xml
new file mode 100644
index 0000000000..7d30f179a6
--- /dev/null
+++ b/library/ui-styles/src/main/res/values/lockscreen_default_dimens.xml
@@ -0,0 +1,7 @@
+
+
+ 70dp
+ 25dp
+ 10dp
+ 5dp
+
diff --git a/library/ui-styles/src/main/res/values/lockscreen_default_strings.xml b/library/ui-styles/src/main/res/values/lockscreen_default_strings.xml
new file mode 100644
index 0000000000..f0d7a75851
--- /dev/null
+++ b/library/ui-styles/src/main/res/values/lockscreen_default_strings.xml
@@ -0,0 +1,17 @@
+
+ Cancel
+ Use pin
+ Sign in
+ Next
+ Forgot?
+ Input pin code or use biometric authentication
+ Fingerprint not recognized. Try again
+ Fingerprint recognized
+
+ Confirm fingerprint to continue
+ Touch sensor
+ Fingerprint icon
+ Confirm PIN
+ Logo
+
+
diff --git a/library/ui-styles/src/main/res/values/lockscreen_default_styles.xml b/library/ui-styles/src/main/res/values/lockscreen_default_styles.xml
new file mode 100644
index 0000000000..dba92df0bb
--- /dev/null
+++ b/library/ui-styles/src/main/res/values/lockscreen_default_styles.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/values/styles_bottom_sheet.xml b/library/ui-styles/src/main/res/values/styles_bottom_sheet.xml
index cf7e5698c0..85cbd1444c 100644
--- a/library/ui-styles/src/main/res/values/styles_bottom_sheet.xml
+++ b/library/ui-styles/src/main/res/values/styles_bottom_sheet.xml
@@ -4,10 +4,13 @@
-
\ No newline at end of file
+
diff --git a/library/ui-styles/src/main/res/values/styles_location.xml b/library/ui-styles/src/main/res/values/styles_location.xml
index 9d9fc862f6..6777450a63 100644
--- a/library/ui-styles/src/main/res/values/styles_location.xml
+++ b/library/ui-styles/src/main/res/values/styles_location.xml
@@ -40,4 +40,9 @@
- center
+
+
diff --git a/library/ui-styles/src/main/res/values/styles_pin_code.xml b/library/ui-styles/src/main/res/values/styles_pin_code.xml
index cb22863694..8459778e29 100644
--- a/library/ui-styles/src/main/res/values/styles_pin_code.xml
+++ b/library/ui-styles/src/main/res/values/styles_pin_code.xml
@@ -22,13 +22,13 @@
diff --git a/library/ui-styles/src/main/res/values/styles_text_view.xml b/library/ui-styles/src/main/res/values/styles_text_view.xml
index 34cdd01daa..4006c577dd 100644
--- a/library/ui-styles/src/main/res/values/styles_text_view.xml
+++ b/library/ui-styles/src/main/res/values/styles_text_view.xml
@@ -59,4 +59,9 @@
-->
-
\ No newline at end of file
+
+
+
diff --git a/library/ui-styles/src/main/res/values/text_appearances.xml b/library/ui-styles/src/main/res/values/text_appearances.xml
index bef921d862..61f5515c89 100644
--- a/library/ui-styles/src/main/res/values/text_appearances.xml
+++ b/library/ui-styles/src/main/res/values/text_appearances.xml
@@ -87,4 +87,11 @@
- 0.02
+
+
diff --git a/library/ui-styles/src/main/res/values/theme_dark.xml b/library/ui-styles/src/main/res/values/theme_dark.xml
index 44c5311748..75a00088c2 100644
--- a/library/ui-styles/src/main/res/values/theme_dark.xml
+++ b/library/ui-styles/src/main/res/values/theme_dark.xml
@@ -111,14 +111,14 @@
- @style/PreferenceThemeOverlay.v14.Material
- - @style/PinCodeScreenStyle
- - @style/PinCodeKeyButtonStyle
- - @style/PinCodeTitleStyle
- - @style/PinCodeHintStyle
- - @style/PinCodeDotsViewStyle
- - @style/PinCodeDeleteButtonStyle
- - @style/PinCodeFingerprintButtonStyle
- - @style/PinCodeNextButtonStyle
+ - @style/PinCodeScreenStyle
+ - @style/PinCodeKeyButtonStyle
+ - @style/PinCodeTitleStyle
+ - @style/PinCodeHintStyle
+ - @style/PinCodeDotsViewStyle
+ - @style/PinCodeDeleteButtonStyle
+ - @style/PinCodeFingerprintButtonStyle
+ - @style/PinCodeNextButtonStyle
- #FF465561
diff --git a/library/ui-styles/src/main/res/values/theme_light.xml b/library/ui-styles/src/main/res/values/theme_light.xml
index a139c0a895..2d65834867 100644
--- a/library/ui-styles/src/main/res/values/theme_light.xml
+++ b/library/ui-styles/src/main/res/values/theme_light.xml
@@ -111,14 +111,14 @@
- @style/PreferenceThemeOverlay.v14.Material
- - @style/PinCodeScreenStyle
- - @style/PinCodeKeyButtonStyle
- - @style/PinCodeTitleStyle
- - @style/PinCodeHintStyle
- - @style/PinCodeDotsViewStyle
- - @style/PinCodeDeleteButtonStyle
- - @style/PinCodeFingerprintButtonStyle
- - @style/PinCodeNextButtonStyle
+ - @style/PinCodeScreenStyle
+ - @style/PinCodeKeyButtonStyle
+ - @style/PinCodeTitleStyle
+ - @style/PinCodeHintStyle
+ - @style/PinCodeDotsViewStyle
+ - @style/PinCodeDeleteButtonStyle
+ - @style/PinCodeFingerprintButtonStyle
+ - @style/PinCodeNextButtonStyle
- #FFEEEEEE
diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt
index 90546756b8..7ac81b2d86 100644
--- a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt
+++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt
@@ -18,7 +18,7 @@ package org.matrix.android.sdk.flow
import androidx.lifecycle.asFlow
import kotlinx.coroutines.flow.Flow
-import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.getStateEvent
@@ -67,17 +67,17 @@ class FlowRoom(private val room: Room) {
}
}
- fun liveStateEvent(eventType: String, stateKey: QueryStringValue): Flow> {
+ fun liveStateEvent(eventType: String, stateKey: QueryStateEventValue): Flow> {
return room.stateService().getStateEventLive(eventType, stateKey).asFlow()
.startWith(room.coroutineDispatchers.io) {
room.getStateEvent(eventType, stateKey).toOptional()
}
}
- fun liveStateEvents(eventTypes: Set): Flow> {
- return room.stateService().getStateEventsLive(eventTypes).asFlow()
+ fun liveStateEvents(eventTypes: Set, stateKey: QueryStateEventValue): Flow> {
+ return room.stateService().getStateEventsLive(eventTypes, stateKey).asFlow()
.startWith(room.coroutineDispatchers.io) {
- room.stateService().getStateEvents(eventTypes)
+ room.stateService().getStateEvents(eventTypes, stateKey)
}
}
diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt
index 2839e6ab61..cc73e099b6 100644
--- a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt
+++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt
@@ -19,7 +19,7 @@ package org.matrix.android.sdk.flow
import androidx.lifecycle.asFlow
import androidx.paging.PagedList
import kotlinx.coroutines.flow.Flow
-import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
@@ -88,7 +88,7 @@ class FlowSession(private val session: Session) {
}
fun liveSyncState(): Flow {
- return session.getSyncStateLive().asFlow()
+ return session.syncService().getSyncStateLive().asFlow()
}
fun livePushers(): Flow> {
@@ -179,7 +179,7 @@ class FlowSession(private val session: Session) {
fun liveRoomWidgets(
roomId: String,
- widgetId: QueryStringValue,
+ widgetId: QueryStateEventValue,
widgetTypes: Set? = null,
excludedTypes: Set? = null
): Flow> {
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index 3829063836..d15113f5f2 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -5,6 +5,10 @@ apply plugin: 'kotlin-parcelize'
apply plugin: 'realm-android'
apply plugin: "org.jetbrains.dokka"
+if (project.hasProperty("coverage")) {
+ apply plugin: 'jacoco'
+}
+
buildscript {
repositories {
// Do not use `mavenCentral()`, it prevents Dependabot from working properly
@@ -56,7 +60,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
- buildConfigField "String", "SDK_VERSION", "\"1.4.20\""
+ buildConfigField "String", "SDK_VERSION", "\"1.4.27\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
@@ -74,6 +78,9 @@ android {
buildTypes {
debug {
+ if (project.hasProperty("coverage")) {
+ testCoverageEnabled = coverage.enableTestCoverage
+ }
// Set to true to log privacy or sensible data, such as token
buildConfigField "boolean", "LOG_PRIVATE_DATA", project.property("vector.debugPrivateData")
// Set to BODY instead of NONE to enable logging
@@ -151,7 +158,7 @@ dependencies {
// - https://github.com/square/okhttp/issues/3278
// - https://github.com/square/okhttp/issues/4455
// - https://github.com/square/okhttp/issues/3146
- implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.3"))
+ implementation(platform("com.squareup.okhttp3:okhttp-bom:4.10.0"))
implementation 'com.squareup.okhttp3:okhttp'
implementation 'com.squareup.okhttp3:logging-interceptor'
@@ -175,7 +182,7 @@ dependencies {
implementation libs.androidx.work
// olm lib is now hosted in MavenCentral
- implementation 'org.matrix.android:olm-sdk:3.2.11'
+ implementation 'org.matrix.android:olm-sdk:3.2.12'
// DI
implementation libs.dagger.dagger
@@ -192,7 +199,7 @@ dependencies {
implementation libs.apache.commonsImaging
// Phone number https://github.com/google/libphonenumber
- implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.49'
+ implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.51'
testImplementation libs.tests.junit
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/InstrumentedTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/InstrumentedTest.kt
index a763766821..f08f0a28ed 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/InstrumentedTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/InstrumentedTest.kt
@@ -19,10 +19,14 @@ package org.matrix.android.sdk
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import org.junit.Rule
+import org.matrix.android.sdk.common.RetryTestRule
import org.matrix.android.sdk.test.shared.createTimberTestRule
interface InstrumentedTest {
+ @Rule
+ fun retryTestRule() = RetryTestRule(3)
+
@Rule
fun timberTestRule() = createTimberTestRule()
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/securestorage/TestBuildVersionSdkIntProvider.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/TestBuildVersionSdkIntProvider.kt
similarity index 78%
rename from matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/securestorage/TestBuildVersionSdkIntProvider.kt
rename to matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/TestBuildVersionSdkIntProvider.kt
index b08c88fb24..d0d64491ef 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/securestorage/TestBuildVersionSdkIntProvider.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/TestBuildVersionSdkIntProvider.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 The Matrix.org Foundation C.I.C.
+ * Copyright 2022 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package org.matrix.android.sdk.internal.session.securestorage
+package org.matrix.android.sdk
-import org.matrix.android.sdk.internal.util.system.BuildVersionSdkIntProvider
+import org.matrix.android.sdk.api.util.BuildVersionSdkIntProvider
class TestBuildVersionSdkIntProvider : BuildVersionSdkIntProvider {
var value: Int = 0
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtilsTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/securestorage/SecretStoringUtilsTest.kt
similarity index 62%
rename from matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtilsTest.kt
rename to matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/securestorage/SecretStoringUtilsTest.kt
index 6bcd12742b..14f985243c 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtilsTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/securestorage/SecretStoringUtilsTest.kt
@@ -14,40 +14,57 @@
* limitations under the License.
*/
-package org.matrix.android.sdk.internal.session.securestorage
+package org.matrix.android.sdk.api.securestorage
import android.os.Build
+import android.util.Base64
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import io.mockk.clearAllMocks
+import io.mockk.every
+import io.mockk.spyk
+import org.amshove.kluent.invoking
import org.amshove.kluent.shouldBeEqualTo
+import org.amshove.kluent.shouldBeInstanceOf
+import org.amshove.kluent.shouldNotThrow
+import org.amshove.kluent.shouldThrow
+import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
-import org.matrix.android.sdk.InstrumentedTest
-import org.matrix.android.sdk.api.util.fromBase64
-import org.matrix.android.sdk.api.util.toBase64NoPadding
+import org.matrix.android.sdk.TestBuildVersionSdkIntProvider
import java.io.ByteArrayOutputStream
+import java.security.KeyStore
+import java.security.KeyStoreException
import java.util.UUID
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
-class SecretStoringUtilsTest : InstrumentedTest {
+class SecretStoringUtilsTest {
+ private val context = InstrumentationRegistry.getInstrumentation().targetContext
private val buildVersionSdkIntProvider = TestBuildVersionSdkIntProvider()
- private val secretStoringUtils = SecretStoringUtils(context(), buildVersionSdkIntProvider)
+ private val keyStore = spyk(KeyStore.getInstance("AndroidKeyStore")).also { it.load(null) }
+ private val secretStoringUtils = SecretStoringUtils(context, keyStore, buildVersionSdkIntProvider)
companion object {
const val TEST_STR = "This is something I want to store safely!"
}
+ @Before
+ fun setup() {
+ clearAllMocks()
+ }
+
@Test
fun testStringNominalCaseApi21() {
val alias = generateAlias()
buildVersionSdkIntProvider.value = Build.VERSION_CODES.LOLLIPOP
// Encrypt
- val encrypted = secretStoringUtils.securelyStoreString(TEST_STR, alias)
+ val encrypted = secretStoringUtils.securelyStoreBytes(TEST_STR.toByteArray(), alias)
// Decrypt
- val decrypted = secretStoringUtils.loadSecureSecret(encrypted, alias)
+ val decrypted = String(secretStoringUtils.loadSecureSecretBytes(encrypted, alias))
decrypted shouldBeEqualTo TEST_STR
secretStoringUtils.safeDeleteKey(alias)
}
@@ -57,9 +74,9 @@ class SecretStoringUtilsTest : InstrumentedTest {
val alias = generateAlias()
buildVersionSdkIntProvider.value = Build.VERSION_CODES.M
// Encrypt
- val encrypted = secretStoringUtils.securelyStoreString(TEST_STR, alias)
+ val encrypted = secretStoringUtils.securelyStoreBytes(TEST_STR.toByteArray(), alias)
// Decrypt
- val decrypted = secretStoringUtils.loadSecureSecret(encrypted, alias)
+ val decrypted = String(secretStoringUtils.loadSecureSecretBytes(encrypted, alias))
decrypted shouldBeEqualTo TEST_STR
secretStoringUtils.safeDeleteKey(alias)
}
@@ -69,9 +86,9 @@ class SecretStoringUtilsTest : InstrumentedTest {
val alias = generateAlias()
buildVersionSdkIntProvider.value = Build.VERSION_CODES.R
// Encrypt
- val encrypted = secretStoringUtils.securelyStoreString(TEST_STR, alias)
+ val encrypted = secretStoringUtils.securelyStoreBytes(TEST_STR.toByteArray(), alias)
// Decrypt
- val decrypted = secretStoringUtils.loadSecureSecret(encrypted, alias)
+ val decrypted = String(secretStoringUtils.loadSecureSecretBytes(encrypted, alias))
decrypted shouldBeEqualTo TEST_STR
secretStoringUtils.safeDeleteKey(alias)
}
@@ -81,13 +98,13 @@ class SecretStoringUtilsTest : InstrumentedTest {
val alias = generateAlias()
buildVersionSdkIntProvider.value = Build.VERSION_CODES.LOLLIPOP
// Encrypt
- val encrypted = secretStoringUtils.securelyStoreString(TEST_STR, alias)
+ val encrypted = secretStoringUtils.securelyStoreBytes(TEST_STR.toByteArray(), alias)
// Simulate a system upgrade
buildVersionSdkIntProvider.value = Build.VERSION_CODES.M
// Decrypt
- val decrypted = secretStoringUtils.loadSecureSecret(encrypted, alias)
+ val decrypted = String(secretStoringUtils.loadSecureSecretBytes(encrypted, alias))
decrypted shouldBeEqualTo TEST_STR
secretStoringUtils.safeDeleteKey(alias)
}
@@ -180,5 +197,56 @@ class SecretStoringUtilsTest : InstrumentedTest {
secretStoringUtils.safeDeleteKey(alias)
}
+ @Test
+ fun testEnsureKeyReturnsSymmetricKeyOnAndroidM() {
+ buildVersionSdkIntProvider.value = Build.VERSION_CODES.M
+ val alias = generateAlias()
+
+ val key = secretStoringUtils.ensureKey(alias)
+ key shouldBeInstanceOf KeyStore.SecretKeyEntry::class
+
+ secretStoringUtils.safeDeleteKey(alias)
+ }
+
+ @Test
+ fun testEnsureKeyReturnsPrivateKeyOnAndroidL() {
+ buildVersionSdkIntProvider.value = Build.VERSION_CODES.LOLLIPOP
+ val alias = generateAlias()
+
+ val key = secretStoringUtils.ensureKey(alias)
+ key shouldBeInstanceOf KeyStore.PrivateKeyEntry::class
+
+ secretStoringUtils.safeDeleteKey(alias)
+ }
+
+ @Test
+ fun testSafeDeleteCanHandleKeyStoreExceptions() {
+ every { keyStore.deleteEntry(any()) } throws KeyStoreException()
+
+ invoking { secretStoringUtils.safeDeleteKey(generateAlias()) } shouldNotThrow KeyStoreException::class
+ }
+
+ @Test
+ fun testLoadSecureSecretBytesWillThrowOnInvalidStreamFormat() {
+ invoking {
+ secretStoringUtils.loadSecureSecretBytes(byteArrayOf(255.toByte()), generateAlias())
+ } shouldThrow IllegalArgumentException::class
+ }
+
+ @Test
+ fun testLoadSecureSecretWillThrowOnInvalidStreamFormat() {
+ invoking {
+ secretStoringUtils.loadSecureSecret(byteArrayOf(255.toByte()).inputStream(), generateAlias())
+ } shouldThrow IllegalArgumentException::class
+ }
+
private fun generateAlias() = UUID.randomUUID().toString()
}
+
+private fun ByteArray.toBase64NoPadding(): String {
+ return Base64.encodeToString(this, Base64.NO_PADDING or Base64.NO_WRAP)
+}
+
+private fun String.fromBase64(): ByteArray {
+ return Base64.decode(this, Base64.DEFAULT)
+}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt
index fdfaceeb4d..7dafe33935 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt
@@ -137,11 +137,11 @@ class CommonTestHelper private constructor(context: Context) {
fun syncSession(session: Session, timeout: Long = TestConstants.timeOutMillis * 10) {
val lock = CountDownLatch(1)
coroutineScope.launch {
- session.startSync(true)
- val syncLiveData = session.getSyncStateLive()
+ session.syncService().startSync(true)
+ val syncLiveData = session.syncService().getSyncStateLive()
val syncObserver = object : Observer {
override fun onChanged(t: SyncState?) {
- if (session.hasAlreadySynced()) {
+ if (session.syncService().hasAlreadySynced()) {
lock.countDown()
syncLiveData.removeObserver(this)
}
@@ -160,10 +160,10 @@ class CommonTestHelper private constructor(context: Context) {
fun clearCacheAndSync(session: Session, timeout: Long = TestConstants.timeOutMillis) {
waitWithLatch(timeout) { latch ->
session.clearCache()
- val syncLiveData = session.getSyncStateLive()
+ val syncLiveData = session.syncService().getSyncStateLive()
val syncObserver = object : Observer {
override fun onChanged(t: SyncState?) {
- if (session.hasAlreadySynced()) {
+ if (session.syncService().hasAlreadySynced()) {
Timber.v("Clear cache and synced")
syncLiveData.removeObserver(this)
latch.countDown()
@@ -171,7 +171,7 @@ class CommonTestHelper private constructor(context: Context) {
}
}
syncLiveData.observeForever(syncObserver)
- session.startSync(true)
+ session.syncService().startSync(true)
}
}
@@ -252,7 +252,8 @@ class CommonTestHelper private constructor(context: Context) {
message: String,
numberOfMessages: Int,
rootThreadEventId: String,
- timeout: Long = TestConstants.timeOutMillis): List {
+ timeout: Long = TestConstants.timeOutMillis
+ ): List {
val timeline = room.timelineService().createTimeline(null, TimelineSettings(10))
timeline.start()
val sentEvents = sendTextMessagesBatched(timeline, room, message, numberOfMessages, timeout, rootThreadEventId)
@@ -272,9 +273,11 @@ class CommonTestHelper private constructor(context: Context) {
* @param testParams test params about the session
* @return the session associated with the newly created account
*/
- private fun createAccount(userNamePrefix: String,
- password: String,
- testParams: SessionTestParams): Session {
+ private fun createAccount(
+ userNamePrefix: String,
+ password: String,
+ testParams: SessionTestParams
+ ): Session {
val session = createAccountAndSync(
userNamePrefix + "_" + accountNumber++ + "_" + UUID.randomUUID(),
password,
@@ -294,9 +297,11 @@ class CommonTestHelper private constructor(context: Context) {
* @param testParams test params about the session
* @return the session associated with the existing account
*/
- fun logIntoAccount(userId: String,
- password: String,
- testParams: SessionTestParams): Session {
+ fun logIntoAccount(
+ userId: String,
+ password: String,
+ testParams: SessionTestParams
+ ): Session {
val session = logAccountAndSync(userId, password, testParams)
assertNotNull(session)
return session.also {
@@ -311,9 +316,11 @@ class CommonTestHelper private constructor(context: Context) {
* @param password the password
* @param sessionTestParams parameters for the test
*/
- private fun createAccountAndSync(userName: String,
- password: String,
- sessionTestParams: SessionTestParams): Session {
+ private fun createAccountAndSync(
+ userName: String,
+ password: String,
+ sessionTestParams: SessionTestParams
+ ): Session {
val hs = createHomeServerConfig()
runBlockingTest {
@@ -349,9 +356,11 @@ class CommonTestHelper private constructor(context: Context) {
* @param password the password
* @param sessionTestParams session test params
*/
- private fun logAccountAndSync(userName: String,
- password: String,
- sessionTestParams: SessionTestParams): Session {
+ private fun logAccountAndSync(
+ userName: String,
+ password: String,
+ sessionTestParams: SessionTestParams
+ ): Session {
val hs = createHomeServerConfig()
runBlockingTest {
@@ -377,8 +386,10 @@ class CommonTestHelper private constructor(context: Context) {
* @param userName the account username
* @param password the password
*/
- fun logAccountWithError(userName: String,
- password: String): Throwable {
+ fun logAccountWithError(
+ userName: String,
+ password: String
+ ): Throwable {
val hs = createHomeServerConfig()
runBlockingTest {
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestData.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestData.kt
index b6bedbd719..41d0d3a7e8 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestData.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestData.kt
@@ -18,8 +18,10 @@ package org.matrix.android.sdk.common
import org.matrix.android.sdk.api.session.Session
-data class CryptoTestData(val roomId: String,
- val sessions: List) {
+data class CryptoTestData(
+ val roomId: String,
+ val sessions: List
+) {
val firstSession: Session
get() = sessions.first()
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/MockOkHttpInterceptor.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/MockOkHttpInterceptor.kt
index b6d833a77c..6dfee2f18f 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/MockOkHttpInterceptor.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/MockOkHttpInterceptor.kt
@@ -73,9 +73,11 @@ class MockOkHttpInterceptor : TestInterceptor {
/**
* Simple rule that reply with the given body for any request that matches the match param
*/
- class SimpleRule(match: String,
- private val code: Int = HttpsURLConnection.HTTP_OK,
- private val body: String = "{}") : Rule(match) {
+ class SimpleRule(
+ match: String,
+ private val code: Int = HttpsURLConnection.HTTP_OK,
+ private val body: String = "{}"
+ ) : Rule(match) {
override fun process(originalRequest: Request): Response? {
return Response.Builder()
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixCallback.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixCallback.kt
index 9f6d6eb136..a007d684e3 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixCallback.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixCallback.kt
@@ -27,8 +27,10 @@ import java.util.concurrent.CountDownLatch
* @param onlySuccessful true to fail if an error occurs. This is the default behavior
* @param
*/
-open class TestMatrixCallback(private val countDownLatch: CountDownLatch,
- private val onlySuccessful: Boolean = true) : MatrixCallback {
+open class TestMatrixCallback(
+ private val countDownLatch: CountDownLatch,
+ private val onlySuccessful: Boolean = true
+) : MatrixCallback {
@CallSuper
override fun onSuccess(data: T) {
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt
index 525e168cf1..6cf01d4ae2 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt
@@ -20,7 +20,9 @@ import android.content.Context
import dagger.BindsInstance
import dagger.Component
import org.matrix.android.sdk.api.MatrixConfiguration
+import org.matrix.android.sdk.api.securestorage.SecureStorageModule
import org.matrix.android.sdk.internal.auth.AuthModule
+import org.matrix.android.sdk.internal.debug.DebugModule
import org.matrix.android.sdk.internal.di.MatrixComponent
import org.matrix.android.sdk.internal.di.MatrixModule
import org.matrix.android.sdk.internal.di.MatrixScope
@@ -36,8 +38,10 @@ import org.matrix.android.sdk.internal.util.system.SystemModule
NetworkModule::class,
AuthModule::class,
RawModule::class,
+ DebugModule::class,
SettingsModule::class,
- SystemModule::class
+ SystemModule::class,
+ SecureStorageModule::class,
]
)
@MatrixScope
@@ -47,7 +51,9 @@ internal interface TestMatrixComponent : MatrixComponent {
@Component.Factory
interface Factory {
- fun create(@BindsInstance context: Context,
- @BindsInstance matrixConfiguration: MatrixConfiguration): TestMatrixComponent
+ fun create(
+ @BindsInstance context: Context,
+ @BindsInstance matrixConfiguration: MatrixConfiguration,
+ ): TestMatrixComponent
}
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
index f5f585a1e0..17c7c28d81 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
@@ -22,6 +22,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -40,6 +41,7 @@ import java.util.UUID
@Suppress("SpellCheckingInspection")
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Ignore
class AttachmentEncryptionTest {
private fun checkDecryption(input: String, encryptedFileInfo: EncryptedFileInfo): String {
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt
index cd6c146f03..dbc6929e34 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt
@@ -22,6 +22,7 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNull
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -37,6 +38,7 @@ import org.matrix.olm.OlmSession
private const val DUMMY_DEVICE_KEY = "DeviceKey"
@RunWith(AndroidJUnit4::class)
+@Ignore
class CryptoStoreTest : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt
index 010383dab8..5a61eee7fe 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt
@@ -626,7 +626,7 @@ class E2eeSanityTests : InstrumentedTest {
// we can release this latch?
oldCompleteLatch.countDown()
}
- else -> Unit
+ else -> Unit
}
}
})
@@ -653,17 +653,17 @@ class E2eeSanityTests : InstrumentedTest {
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
// no need to accept as there was a request first it will auto accept
}
- IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
+ IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
if (matchOnce) {
sasTx.userHasVerifiedShortCode()
newCode = sasTx.getDecimalCodeRepresentation()
matchOnce = false
}
}
- IncomingSasVerificationTransaction.UxState.VERIFIED -> {
+ IncomingSasVerificationTransaction.UxState.VERIFIED -> {
newCompleteLatch.countDown()
}
- else -> Unit
+ else -> Unit
}
}
})
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ExportEncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ExportEncryptionTest.kt
index c2d8f4fb35..bddb31fc92 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ExportEncryptionTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ExportEncryptionTest.kt
@@ -21,6 +21,7 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -30,6 +31,7 @@ import org.junit.runners.MethodSorters
*/
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Ignore
class ExportEncryptionTest {
@Test
@@ -83,7 +85,8 @@ class ExportEncryptionTest {
@Test
fun checkExportDecrypt1() {
val password = "password"
- val input = "-----BEGIN MEGOLM SESSION DATA-----\nAXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx\n" + "cissyYBxjsfsAndErh065A8=\n-----END MEGOLM SESSION DATA-----"
+ val input = "-----BEGIN MEGOLM SESSION DATA-----\nAXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx\n" +
+ "cissyYBxjsfsAndErh065A8=\n-----END MEGOLM SESSION DATA-----"
val expectedString = "plain"
var decodedString: String? = null
@@ -103,7 +106,8 @@ class ExportEncryptionTest {
@Test
fun checkExportDecrypt2() {
val password = "betterpassword"
- val input = "-----BEGIN MEGOLM SESSION DATA-----\nAW1vcmVzYWx0bW9yZXNhbHT//////////wAAAAAAAAAAAAAD6KyBpe1Niv5M5NPm4ZATsJo5nghk\n" + "KYu63a0YQ5DRhUWEKk7CcMkrKnAUiZny\n-----END MEGOLM SESSION DATA-----"
+ val input = "-----BEGIN MEGOLM SESSION DATA-----\nAW1vcmVzYWx0bW9yZXNhbHT//////////wAAAAAAAAAAAAAD6KyBpe1Niv5M5NPm4ZATsJo5nghk\n" +
+ "KYu63a0YQ5DRhUWEKk7CcMkrKnAUiZny\n-----END MEGOLM SESSION DATA-----"
val expectedString = "Hello, World"
var decodedString: String? = null
@@ -123,7 +127,8 @@ class ExportEncryptionTest {
@Test
fun checkExportDecrypt3() {
val password = "SWORDFISH"
- val input = "-----BEGIN MEGOLM SESSION DATA-----\nAXllc3NhbHR5Z29vZG5lc3P//////////wAAAAAAAAAAAAAD6OIW+Je7gwvjd4kYrb+49gKCfExw\n" + "MgJBMD4mrhLkmgAngwR1pHjbWXaoGybtiAYr0moQ93GrBQsCzPbvl82rZhaXO3iH5uHo/RCEpOqp\nPgg29363BGR+/Ripq/VCLKGNbw==\n-----END MEGOLM SESSION DATA-----"
+ val input = "-----BEGIN MEGOLM SESSION DATA-----\nAXllc3NhbHR5Z29vZG5lc3P//////////wAAAAAAAAAAAAAD6OIW+Je7gwvjd4kYrb+49gKCfExw\n" +
+ "MgJBMD4mrhLkmgAngwR1pHjbWXaoGybtiAYr0moQ93GrBQsCzPbvl82rZhaXO3iH5uHo/RCEpOqp\nPgg29363BGR+/Ripq/VCLKGNbw==\n-----END MEGOLM SESSION DATA-----"
val expectedString = "alphanumericallyalphanumericallyalphanumericallyalphanumerically"
var decodedString: String? = null
@@ -202,7 +207,8 @@ class ExportEncryptionTest {
@Test
fun checkExportEncrypt4() {
- val password = "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" + "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword"
+ val password = "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" +
+ "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword"
val expectedString = "alphanumericallyalphanumericallyalphanumericallyalphanumerically"
var decodedString: String? = null
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt
index 5fe7376184..e8a474a54a 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt
@@ -21,6 +21,7 @@ import org.amshove.kluent.shouldBe
import org.junit.Assert
import org.junit.Before
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -59,6 +60,7 @@ import kotlin.coroutines.resume
*/
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
+@Ignore
class UnwedgingTest : InstrumentedTest {
private lateinit var messagesReceivedByBob: List
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt
index 05790bfb7d..8cb38ddc87 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt
@@ -25,6 +25,7 @@ import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -47,6 +48,7 @@ import kotlin.coroutines.resume
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@LargeTest
+@Ignore
class XSigningTest : InstrumentedTest {
@Test
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt
index b16e4b82eb..7bb53e139c 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt
@@ -25,6 +25,7 @@ import org.amshove.kluent.internal.assertEquals
import org.junit.Assert
import org.junit.Assert.assertNull
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -50,6 +51,7 @@ import org.matrix.android.sdk.mustFail
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
+@Ignore
class KeyShareTests : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)
@@ -422,7 +424,7 @@ class KeyShareTests : InstrumentedTest {
// /!\ Stop initial alice session syncing so that it can't reply
aliceSession.cryptoService().enableKeyGossiping(false)
- aliceSession.stopSync()
+ aliceSession.syncService().stopSync()
// Let's now try to request
aliceNewSession.cryptoService().reRequestRoomKeyForEvent(sentEvents.first().root)
@@ -445,7 +447,7 @@ class KeyShareTests : InstrumentedTest {
// let's wake up alice
aliceSession.cryptoService().enableKeyGossiping(true)
- aliceSession.startSync(true)
+ aliceSession.syncService().startSync(true)
// We should now get a reply from first session
commonTestHelper.waitWithLatch { latch ->
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt
index 0aac4297e4..ae420a09b3 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt
@@ -21,6 +21,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import org.junit.Assert
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -46,6 +47,7 @@ import org.matrix.android.sdk.mustFail
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
+@Ignore
class WithHeldTests : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt
index c6e17e8c44..fb498e0de5 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt
@@ -24,6 +24,7 @@ import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -55,6 +56,7 @@ import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
+@Ignore
class KeysBackupTest : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt
index 4eccdfad1f..38f94c5103 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt
@@ -33,7 +33,8 @@ import java.util.concurrent.CountDownLatch
internal class KeysBackupTestHelper(
private val testHelper: CommonTestHelper,
- private val cryptoTestHelper: CryptoTestHelper) {
+ private val cryptoTestHelper: CryptoTestHelper
+) {
fun waitForKeybackUpBatching() {
Thread.sleep(400)
@@ -96,8 +97,10 @@ internal class KeysBackupTestHelper(
)
}
- fun prepareAndCreateKeysBackupData(keysBackup: KeysBackupService,
- password: String? = null): PrepareKeysBackupDataResult {
+ fun prepareAndCreateKeysBackupData(
+ keysBackup: KeysBackupService,
+ password: String? = null
+ ): PrepareKeysBackupDataResult {
val stateObserver = StateObserver(keysBackup)
val megolmBackupCreationInfo = testHelper.doSync {
@@ -169,9 +172,11 @@ internal class KeysBackupTestHelper(
* - The new device must have the same count of megolm keys
* - Alice must have the same keys on both devices
*/
- fun checkRestoreSuccess(testData: KeysBackupScenarioData,
- total: Int,
- imported: Int) {
+ fun checkRestoreSuccess(
+ testData: KeysBackupScenarioData,
+ total: Int,
+ imported: Int
+ ) {
// - Imported keys number must be correct
Assert.assertEquals(testData.aliceKeys.size, total)
Assert.assertEquals(total, imported)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/PrepareKeysBackupDataResult.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/PrepareKeysBackupDataResult.kt
index 31bd3c9cce..9ee10eddcf 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/PrepareKeysBackupDataResult.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/PrepareKeysBackupDataResult.kt
@@ -18,5 +18,7 @@ package org.matrix.android.sdk.internal.crypto.keysbackup
import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo
-data class PrepareKeysBackupDataResult(val megolmBackupCreationInfo: MegolmBackupCreationInfo,
- val version: String)
+data class PrepareKeysBackupDataResult(
+ val megolmBackupCreationInfo: MegolmBackupCreationInfo,
+ val version: String
+)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/StateObserver.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/StateObserver.kt
index 80e54d82ec..6c97774547 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/StateObserver.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/StateObserver.kt
@@ -27,9 +27,11 @@ import java.util.concurrent.CountDownLatch
* This class observe the state change of a KeysBackup object and provide a method to check the several state change
* It checks all state transitions and detected forbidden transition
*/
-internal class StateObserver(private val keysBackup: KeysBackupService,
- private val latch: CountDownLatch? = null,
- private val expectedStateChange: Int = -1) : KeysBackupStateListener {
+internal class StateObserver(
+ private val keysBackup: KeysBackupService,
+ private val latch: CountDownLatch? = null,
+ private val expectedStateChange: Int = -1
+) : KeysBackupStateListener {
private val allowedStateTransitions = listOf(
KeysBackupState.BackingUp to KeysBackupState.ReadyToBackUp,
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt
index c4d9ba4ee3..c2e74abc59 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt
@@ -52,6 +52,7 @@ import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Ignore
class SASTest : InstrumentedTest {
@Test
@@ -264,14 +265,16 @@ class SASTest : InstrumentedTest {
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
}
- private fun fakeBobStart(bobSession: Session,
- aliceUserID: String?,
- aliceDevice: String?,
- tid: String,
- protocols: List = SASDefaultVerificationTransaction.KNOWN_AGREEMENT_PROTOCOLS,
- hashes: List = SASDefaultVerificationTransaction.KNOWN_HASHES,
- mac: List = SASDefaultVerificationTransaction.KNOWN_MACS,
- codes: List = SASDefaultVerificationTransaction.KNOWN_SHORT_CODES) {
+ private fun fakeBobStart(
+ bobSession: Session,
+ aliceUserID: String?,
+ aliceDevice: String?,
+ tid: String,
+ protocols: List = SASDefaultVerificationTransaction.KNOWN_AGREEMENT_PROTOCOLS,
+ hashes: List = SASDefaultVerificationTransaction.KNOWN_HASHES,
+ mac: List = SASDefaultVerificationTransaction.KNOWN_MACS,
+ codes: List = SASDefaultVerificationTransaction.KNOWN_SHORT_CODES
+ ) {
val startMessage = KeyVerificationStart(
fromDevice = bobSession.cryptoService().getMyDevice().deviceId,
method = VerificationMethod.SAS.toValue(),
@@ -412,7 +415,7 @@ class SASTest : InstrumentedTest {
OutgoingSasVerificationTransaction.UxState.SHOW_SAS -> {
aliceSASLatch.countDown()
}
- else -> Unit
+ else -> Unit
}
}
}
@@ -426,7 +429,7 @@ class SASTest : InstrumentedTest {
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
tx.performAccept()
}
- else -> Unit
+ else -> Unit
}
if (uxState === IncomingSasVerificationTransaction.UxState.SHOW_SAS) {
bobSASLatch.countDown()
@@ -476,7 +479,7 @@ class SASTest : InstrumentedTest {
aliceSASLatch.countDown()
}
}
- else -> Unit
+ else -> Unit
}
}
}
@@ -496,16 +499,16 @@ class SASTest : InstrumentedTest {
tx.performAccept()
}
}
- IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
+ IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
if (matchOnce) {
matchOnce = false
tx.userHasVerifiedShortCode()
}
}
- IncomingSasVerificationTransaction.UxState.VERIFIED -> {
+ IncomingSasVerificationTransaction.UxState.VERIFIED -> {
bobSASLatch.countDown()
}
- else -> Unit
+ else -> Unit
}
}
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt
index 462f47cafc..3f22906965 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt
@@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.crypto.verification.qrcode
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.amshove.kluent.shouldBe
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -41,6 +42,7 @@ import kotlin.coroutines.resume
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
+@Ignore
class VerificationTest : InstrumentedTest {
data class ExpectedResult(
@@ -151,10 +153,12 @@ class VerificationTest : InstrumentedTest {
// TODO Add tests without SAS
- private fun doTest(aliceSupportedMethods: List,
- bobSupportedMethods: List,
- expectedResultForAlice: ExpectedResult,
- expectedResultForBob: ExpectedResult) = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
+ private fun doTest(
+ aliceSupportedMethods: List,
+ bobSupportedMethods: List,
+ expectedResultForAlice: ExpectedResult,
+ expectedResultForBob: ExpectedResult
+ ) = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
index acb23bf723..0560cfec95 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
@@ -289,9 +289,11 @@ class MarkdownParserTest : InstrumentedTest {
markdownParser.parse(text).expect(text, null)
}
- private fun testType(name: String,
- markdownPattern: String,
- htmlExpectedTag: String) {
+ private fun testType(
+ name: String,
+ markdownPattern: String,
+ htmlExpectedTag: String
+ ) {
// Test simple case
"$markdownPattern$name$markdownPattern"
.let {
@@ -376,10 +378,12 @@ class MarkdownParserTest : InstrumentedTest {
}
}
- private fun testTypeNewLines(name: String,
- markdownPattern: String,
- htmlExpectedTag: String,
- softBreak: String = "
") {
+ private fun testTypeNewLines(
+ name: String,
+ markdownPattern: String,
+ htmlExpectedTag: String,
+ softBreak: String = "
"
+ ) {
// With new line inside the block
"$markdownPattern$name\n$name$markdownPattern"
.let {
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/TestPermalinkService.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/TestPermalinkService.kt
index 2f9a5e0a73..3a267ec694 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/TestPermalinkService.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/TestPermalinkService.kt
@@ -44,7 +44,7 @@ class TestPermalinkService : PermalinkService {
override fun createMentionSpanTemplate(type: PermalinkService.SpanTemplateType, forceMatrixTo: Boolean): String {
return when (type) {
- HTML -> "%2\$s"
+ HTML -> "%2\$s"
MARKDOWN -> "[%2\$s](https://matrix.to/#/%1\$s)"
}
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt
index 1ffcc2a3e6..45bd38870d 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt
@@ -83,7 +83,7 @@ class ThreadMessagingTest : InstrumentedTest {
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
- aliceSession.startSync(true)
+ aliceSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
@@ -97,7 +97,7 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
- aliceSession.stopSync()
+ aliceSession.syncService().stopSync()
}
@Test
@@ -144,7 +144,7 @@ class ThreadMessagingTest : InstrumentedTest {
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
- aliceSession.startSync(true)
+ aliceSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
@@ -156,9 +156,9 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
- aliceSession.stopSync()
+ aliceSession.syncService().stopSync()
- bobSession.startSync(true)
+ bobSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
@@ -170,7 +170,7 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
- bobSession.stopSync()
+ bobSession.syncService().stopSync()
}
@Test
@@ -217,7 +217,7 @@ class ThreadMessagingTest : InstrumentedTest {
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
- aliceSession.startSync(true)
+ aliceSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
@@ -233,7 +233,7 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
- aliceSession.stopSync()
+ aliceSession.syncService().stopSync()
}
@Test
@@ -314,7 +314,7 @@ class ThreadMessagingTest : InstrumentedTest {
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
- aliceSession.startSync(true)
+ aliceSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
@@ -338,6 +338,6 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
- aliceSession.stopSync()
+ aliceSession.syncService().stopSync()
}
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt
index 94b2ba55a3..7b0d57abbc 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt
@@ -22,7 +22,6 @@ import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.kotlin.createObject
import org.amshove.kluent.shouldBeEqualTo
-import org.amshove.kluent.shouldBeTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -30,13 +29,11 @@ import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
-import org.matrix.android.sdk.internal.database.helper.merge
import org.matrix.android.sdk.internal.database.mapper.toEntity
import org.matrix.android.sdk.internal.database.model.ChunkEntity
import org.matrix.android.sdk.internal.database.model.SessionRealmModule
import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection
import org.matrix.android.sdk.internal.util.time.DefaultClock
-import org.matrix.android.sdk.session.room.timeline.RoomDataHelper.createFakeListOfEvents
import org.matrix.android.sdk.session.room.timeline.RoomDataHelper.createFakeMessageEvent
@RunWith(AndroidJUnit4::class)
@@ -97,66 +94,11 @@ internal class ChunkEntityTest : InstrumentedTest {
}
}
- @Test
- fun merge_shouldAddEvents_whenMergingBackward() {
- monarchy.runTransactionSync { realm ->
- val chunk1: ChunkEntity = realm.createObject()
- val chunk2: ChunkEntity = realm.createObject()
- chunk1.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
- chunk2.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
- chunk1.merge(ROOM_ID, chunk2, PaginationDirection.BACKWARDS)
- chunk1.timelineEvents.size shouldBeEqualTo 60
- }
- }
-
- @Test
- fun merge_shouldAddOnlyDifferentEvents_whenMergingBackward() {
- monarchy.runTransactionSync { realm ->
- val chunk1: ChunkEntity = realm.createObject()
- val chunk2: ChunkEntity = realm.createObject()
- val eventsForChunk1 = createFakeListOfEvents(30)
- val eventsForChunk2 = eventsForChunk1 + createFakeListOfEvents(10)
- chunk1.isLastForward = true
- chunk2.isLastForward = false
- chunk1.addAll(ROOM_ID, eventsForChunk1, PaginationDirection.FORWARDS)
- chunk2.addAll(ROOM_ID, eventsForChunk2, PaginationDirection.BACKWARDS)
- chunk1.merge(ROOM_ID, chunk2, PaginationDirection.BACKWARDS)
- chunk1.timelineEvents.size shouldBeEqualTo 40
- chunk1.isLastForward.shouldBeTrue()
- }
- }
-
- @Test
- fun merge_shouldPrevTokenMerged_whenMergingForwards() {
- monarchy.runTransactionSync { realm ->
- val chunk1: ChunkEntity = realm.createObject()
- val chunk2: ChunkEntity = realm.createObject()
- val prevToken = "prev_token"
- chunk1.prevToken = prevToken
- chunk1.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
- chunk2.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
- chunk1.merge(ROOM_ID, chunk2, PaginationDirection.FORWARDS)
- chunk1.prevToken shouldBeEqualTo prevToken
- }
- }
-
- @Test
- fun merge_shouldNextTokenMerged_whenMergingBackwards() {
- monarchy.runTransactionSync { realm ->
- val chunk1: ChunkEntity = realm.createObject()
- val chunk2: ChunkEntity = realm.createObject()
- val nextToken = "next_token"
- chunk1.nextToken = nextToken
- chunk1.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
- chunk2.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
- chunk1.merge(ROOM_ID, chunk2, PaginationDirection.BACKWARDS)
- chunk1.nextToken shouldBeEqualTo nextToken
- }
- }
-
- private fun ChunkEntity.addAll(roomId: String,
- events: List,
- direction: PaginationDirection) {
+ private fun ChunkEntity.addAll(
+ roomId: String,
+ events: List,
+ direction: PaginationDirection
+ ) {
events.forEach { event ->
val fakeEvent = event.toEntity(roomId, SendState.SYNCED, clock.epochMillis()).let {
realm.copyToRealm(it)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeTokenChunkEvent.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeTokenChunkEvent.kt
index 657f622c5b..2e9478ba7e 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeTokenChunkEvent.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeTokenChunkEvent.kt
@@ -19,8 +19,9 @@ package org.matrix.android.sdk.session.room.timeline
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.internal.session.room.timeline.TokenChunkEvent
-internal data class FakeTokenChunkEvent(override val start: String?,
- override val end: String?,
- override val events: List = emptyList(),
- override val stateEvents: List = emptyList()
+internal data class FakeTokenChunkEvent(
+ override val start: String?,
+ override val end: String?,
+ override val events: List = emptyList(),
+ override val stateEvents: List = emptyList()
) : TokenChunkEvent
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt
index 2b72ecc52a..a37d2ce015 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt
@@ -57,7 +57,7 @@ class PollAggregationTest : InstrumentedTest {
// Bob creates a poll
roomFromBobPOV.sendService().sendPoll(PollType.DISCLOSED, pollQuestion, pollOptions)
- aliceSession.startSync(true)
+ aliceSession.syncService().startSync(true)
val aliceTimeline = roomFromAlicePOV.timelineService().createTimeline(null, TimelineSettings(30))
aliceTimeline.start()
@@ -77,7 +77,7 @@ class PollAggregationTest : InstrumentedTest {
}
when (lock.count.toInt()) {
- TOTAL_TEST_COUNT -> {
+ TOTAL_TEST_COUNT -> {
// Poll has just been created.
testInitialPollConditions(pollContent, pollSummary)
lock.countDown()
@@ -119,7 +119,7 @@ class PollAggregationTest : InstrumentedTest {
testEndedPoll(pollSummary)
lock.countDown()
}
- else -> {
+ else -> {
fail("Lock count ${lock.count} didn't handled.")
}
}
@@ -133,7 +133,7 @@ class PollAggregationTest : InstrumentedTest {
aliceTimeline.removeAllListeners()
- aliceSession.stopSync()
+ aliceSession.syncService().stopSync()
aliceTimeline.dispose()
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/RoomDataHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/RoomDataHelper.kt
index 8a4429db45..53585ae82a 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/RoomDataHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/RoomDataHelper.kt
@@ -41,11 +41,12 @@ object RoomDataHelper {
}
}
- private fun createFakeEvent(type: String,
- content: Content? = null,
- prevContent: Content? = null,
- sender: String = FAKE_TEST_SENDER,
- stateKey: String? = null
+ private fun createFakeEvent(
+ type: String,
+ content: Content? = null,
+ prevContent: Content? = null,
+ sender: String = FAKE_TEST_SENDER,
+ stateKey: String? = null
): Event {
return Event(
type = type,
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt
index 3dd3f5fa2a..3dbf206e08 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt
@@ -163,6 +163,8 @@ class TimelineForwardPaginationTest : InstrumentedTest {
// Ask for a forward pagination
val snapshot = runBlocking {
aliceTimeline.awaitPaginate(Timeline.Direction.FORWARDS, 50)
+ // We should paginate one more time to check we are at the end now that chunks are not merged.
+ aliceTimeline.awaitPaginate(Timeline.Direction.FORWARDS, 50)
}
// 7 for room creation item (backward pagination),and numberOfMessagesToSend (all the message of the room)
snapshot.size == 7 + numberOfMessagesToSend &&
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt
index 3ff4572add..7c1a097b24 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt
@@ -20,6 +20,7 @@ import androidx.test.filters.LargeTest
import org.amshove.kluent.shouldBeFalse
import org.amshove.kluent.shouldBeTrue
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -39,6 +40,7 @@ import java.util.concurrent.CountDownLatch
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
+@Ignore("This test will be ignored until it is fixed")
@LargeTest
class TimelinePreviousLastForwardTest : InstrumentedTest {
@@ -88,7 +90,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
}
// Bob stop to sync
- bobSession.stopSync()
+ bobSession.syncService().stopSync()
val firstMessage = "First messages from Alice"
// Alice sends 30 messages
@@ -101,7 +103,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
.eventId
// Bob start to sync
- bobSession.startSync(true)
+ bobSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
@@ -125,7 +127,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
}
// Bob stop to sync
- bobSession.stopSync()
+ bobSession.syncService().stopSync()
val secondMessage = "Second messages from Alice"
// Alice sends again 30 messages
@@ -136,7 +138,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
)
// Bob start to sync
- bobSession.startSync(true)
+ bobSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
@@ -229,6 +231,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
bobTimeline.addListener(eventsListener)
+ bobTimeline.paginate(Timeline.Direction.FORWARDS, 50)
bobTimeline.paginate(Timeline.Direction.FORWARDS, 50)
commonTestHelper.await(lock)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt
index 7ed0be927c..59b3b14532 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt
@@ -20,6 +20,7 @@ import androidx.test.filters.LargeTest
import kotlinx.coroutines.runBlocking
import org.amshove.kluent.internal.assertEquals
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -38,6 +39,7 @@ import org.matrix.android.sdk.common.TestConstants
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
+@Ignore
class TimelineSimpleBackPaginationTest : InstrumentedTest {
@Test
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt
index 87f404b0f1..27ea0e1c3c 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt
@@ -71,7 +71,7 @@ class TimelineWithManyMembersTest : InstrumentedTest {
val timelineForCurrentMember = roomForCurrentMember.timelineService().createTimeline(null, TimelineSettings(30))
timelineForCurrentMember.start()
- session.startSync(true)
+ session.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
@@ -92,7 +92,7 @@ class TimelineWithManyMembersTest : InstrumentedTest {
timelineForCurrentMember.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
- session.stopSync()
+ session.syncService().stopSync()
}
}
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt
index 0d8a9058a2..38136ff5ce 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt
@@ -22,11 +22,13 @@ import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
+import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.getStateEvent
@@ -72,32 +74,43 @@ class SpaceCreationTest : InstrumentedTest {
// assertEquals(topic, syncedSpace.asRoom().roomSummary()?., "Room topic should be set")
assertNotNull("Space should be found by Id", syncedSpace)
- val creationEvent = syncedSpace!!.asRoom().getStateEvent(EventType.STATE_ROOM_CREATE)
- val createContent = creationEvent?.content.toModel()
+ val createContent = syncedSpace!!.asRoom()
+ .getStateEvent(EventType.STATE_ROOM_CREATE, QueryStringValue.IsEmpty)
+ ?.content
+ ?.toModel()
assertEquals("Room type should be space", RoomType.SPACE, createContent?.type)
var powerLevelsContent: PowerLevelsContent? = null
commonTestHelper.waitWithLatch { latch ->
commonTestHelper.retryPeriodicallyWithLatch(latch) {
- val toModel = syncedSpace.asRoom().getStateEvent(EventType.STATE_ROOM_POWER_LEVELS)?.content.toModel()
- powerLevelsContent = toModel
- toModel != null
+ powerLevelsContent = syncedSpace.asRoom()
+ .getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
+ ?.content
+ ?.toModel()
+ powerLevelsContent != null
}
}
assertEquals("Space-rooms should be created with a power level for events_default of 100", 100, powerLevelsContent?.eventsDefault)
- val guestAccess = syncedSpace.asRoom().getStateEvent(EventType.STATE_ROOM_GUEST_ACCESS)?.content
- ?.toModel()?.guestAccess
+ val guestAccess = syncedSpace.asRoom()
+ .getStateEvent(EventType.STATE_ROOM_GUEST_ACCESS, QueryStringValue.IsEmpty)
+ ?.content
+ ?.toModel()
+ ?.guestAccess
assertEquals("Public space room should be peekable by guest", GuestAccess.CanJoin, guestAccess)
- val historyVisibility = syncedSpace.asRoom().getStateEvent(EventType.STATE_ROOM_HISTORY_VISIBILITY)?.content
- ?.toModel()?.historyVisibility
+ val historyVisibility = syncedSpace.asRoom()
+ .getStateEvent(EventType.STATE_ROOM_HISTORY_VISIBILITY, QueryStringValue.IsEmpty)
+ ?.content
+ ?.toModel()
+ ?.historyVisibility
assertEquals("Public space room should be world readable", RoomHistoryVisibility.WORLD_READABLE, historyVisibility)
}
@Test
+ @Ignore
fun testJoinSimplePublicSpace() = runSessionTest(context()) { commonTestHelper ->
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt
index f16cd91e36..63ca963479 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt
@@ -387,9 +387,10 @@ class SpaceHierarchyTest : InstrumentedTest {
val roomIds: List
)
- private fun createPublicSpace(session: Session,
- spaceName: String,
- childInfo: List>
+ private fun createPublicSpace(
+ session: Session,
+ spaceName: String,
+ childInfo: List>
/** Name, auto-join, canonical*/
): TestSpaceCreationResult {
var spaceId = ""
@@ -416,9 +417,10 @@ class SpaceHierarchyTest : InstrumentedTest {
return TestSpaceCreationResult(spaceId, roomIds)
}
- private fun createPrivateSpace(session: Session,
- spaceName: String,
- childInfo: List>
+ private fun createPrivateSpace(
+ session: Session,
+ spaceName: String,
+ childInfo: List>
/** Name, auto-join, canonical*/
): TestSpaceCreationResult {
var spaceId = ""
@@ -567,8 +569,9 @@ class SpaceHierarchyTest : InstrumentedTest {
commonTestHelper.waitWithLatch {
val room = bobSession.getRoom(bobRoomId)!!
val currentPLContent = room
- .getStateEvent(EventType.STATE_ROOM_POWER_LEVELS)
- ?.let { it.content.toModel() }
+ .getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
+ ?.content
+ .toModel()
val newPowerLevelsContent = currentPLContent
?.setUserPowerLevel(aliceSession.myUserId, Role.Admin.value)
@@ -581,7 +584,7 @@ class SpaceHierarchyTest : InstrumentedTest {
commonTestHelper.waitWithLatch { latch ->
commonTestHelper.retryPeriodicallyWithLatch(latch) {
val powerLevelsHelper = aliceSession.getRoom(bobRoomId)!!
- .getStateEvent(EventType.STATE_ROOM_POWER_LEVELS)
+ .getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
?.content
?.toModel()
?.let { PowerLevelsHelper(it) }
diff --git a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/InlineMaths.kt b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/InlineMaths.kt
index 3fe8d15696..556579942b 100644
--- a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/InlineMaths.kt
+++ b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/InlineMaths.kt
@@ -26,14 +26,14 @@ internal class InlineMaths(private val delimiter: InlineDelimiter) : CustomNode(
override fun getOpeningDelimiter(): String {
return when (delimiter) {
- InlineDelimiter.SINGLE_DOLLAR -> "$"
+ InlineDelimiter.SINGLE_DOLLAR -> "$"
InlineDelimiter.ROUND_BRACKET_ESCAPED -> "\\("
}
}
override fun getClosingDelimiter(): String {
return when (delimiter) {
- InlineDelimiter.SINGLE_DOLLAR -> "$"
+ InlineDelimiter.SINGLE_DOLLAR -> "$"
InlineDelimiter.ROUND_BRACKET_ESCAPED -> "\\)"
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt
index 979201706b..953ebddcbf 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt
@@ -17,6 +17,8 @@
package org.matrix.android.sdk.api
import android.content.Context
+import android.os.Handler
+import android.os.Looper
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.work.Configuration
import androidx.work.WorkManager
@@ -25,10 +27,12 @@ import com.zhuinden.monarchy.Monarchy
import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
+import org.matrix.android.sdk.api.debug.DebugService
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
import org.matrix.android.sdk.api.network.ApiInterceptorListener
import org.matrix.android.sdk.api.network.ApiPath
import org.matrix.android.sdk.api.raw.RawService
+import org.matrix.android.sdk.api.securestorage.SecureStorageService
import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
import org.matrix.android.sdk.internal.SessionManager
import org.matrix.android.sdk.internal.di.DaggerMatrixComponent
@@ -54,6 +58,7 @@ class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) {
@Inject internal lateinit var legacySessionImporter: LegacySessionImporter
@Inject internal lateinit var authenticationService: AuthenticationService
@Inject internal lateinit var rawService: RawService
+ @Inject internal lateinit var debugService: DebugService
@Inject internal lateinit var userAgentHolder: UserAgentHolder
@Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver
@Inject internal lateinit var olmManager: OlmManager
@@ -62,6 +67,9 @@ class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) {
@Inject internal lateinit var apiInterceptor: ApiInterceptor
@Inject internal lateinit var matrixWorkerFactory: MatrixWorkerFactory
@Inject internal lateinit var lightweightSettingsStorage: LightweightSettingsStorage
+ @Inject internal lateinit var secureStorageService: SecureStorageService
+
+ private val uiHandler = Handler(Looper.getMainLooper())
init {
val appContext = context.applicationContext
@@ -74,7 +82,9 @@ class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) {
.build()
WorkManager.initialize(appContext, configuration)
}
- ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver)
+ uiHandler.post {
+ ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver)
+ }
}
/**
@@ -93,6 +103,11 @@ class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) {
*/
fun rawService() = rawService
+ /**
+ * Return the DebugService.
+ */
+ fun debugService() = debugService
+
/**
* Return the LightweightSettingsStorage.
*/
@@ -108,6 +123,11 @@ class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) {
*/
fun legacySessionImporter() = legacySessionImporter
+ /**
+ * Returns the SecureStorageService used to encrypt and decrypt sensitive data.
+ */
+ fun secureStorageService(): SecureStorageService = secureStorageService
+
/**
* Get the worker factory. The returned value has to be provided to `WorkConfiguration.Builder()`.
*/
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt
index 21106fba6c..893e90fb3e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt
@@ -17,6 +17,7 @@
package org.matrix.android.sdk.api
import okhttp3.ConnectionSpec
+import okhttp3.Interceptor
import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import java.net.Proxy
@@ -65,4 +66,8 @@ data class MatrixConfiguration(
* Thread messages default enable/disabled value.
*/
val threadMessagesEnabledDefault: Boolean = false,
+ /**
+ * List of network interceptors, they will be added when building an OkHttp client.
+ */
+ val networkInterceptors: List = emptyList(),
)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt
index 629d947bb3..5ae70e1978 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt
@@ -28,9 +28,11 @@ import org.matrix.android.sdk.api.session.Session
* This interface defines methods to authenticate or to create an account to a matrix server.
*/
interface AuthenticationService {
+
/**
* Request the supported login flows for this homeserver.
- * This is the first method to call to be able to get a wizard to login or to create an account
+ * This is the first method to call to be able to get a wizard to login or to create an account.
+ * @param homeServerConnectionConfig contains the homeserver URL to login to, a wellKnown lookup will be attempted.
*/
suspend fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult
@@ -93,14 +95,18 @@ interface AuthenticationService {
/**
* Create a session after a SSO successful login.
*/
- suspend fun createSessionFromSso(homeServerConnectionConfig: HomeServerConnectionConfig,
- credentials: Credentials): Session
+ suspend fun createSessionFromSso(
+ homeServerConnectionConfig: HomeServerConnectionConfig,
+ credentials: Credentials
+ ): Session
/**
* Perform a wellknown request, using the domain from the matrixId.
*/
- suspend fun getWellKnownData(matrixId: String,
- homeServerConnectionConfig: HomeServerConnectionConfig?): WellknownResult
+ suspend fun getWellKnownData(
+ matrixId: String,
+ homeServerConnectionConfig: HomeServerConnectionConfig?
+ ): WellknownResult
/**
* Authenticate with a matrixId and a password.
@@ -111,9 +117,11 @@ interface AuthenticationService {
* @param initialDeviceName the initial device name
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
*/
- suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig,
- matrixId: String,
- password: String,
- initialDeviceName: String,
- deviceId: String? = null): Session
+ suspend fun directAuthentication(
+ homeServerConnectionConfig: HomeServerConnectionConfig,
+ matrixId: String,
+ password: String,
+ initialDeviceName: String,
+ deviceId: String? = null
+ ): Session
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/converter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/converter.kt
index 80630bc4e7..e2f16ceee8 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/converter.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/converter.kt
@@ -41,8 +41,10 @@ import org.matrix.android.sdk.api.auth.registration.TermPolicies
* @param userLanguage the user language
* @param defaultLanguage the default language to use if the user language is not found for a policy in registrationFlowResponse
*/
-fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
- defaultLanguage: String = "en"): List {
+fun TermPolicies.toLocalizedLoginTerms(
+ userLanguage: String,
+ defaultLanguage: String = "en"
+): List {
val result = ArrayList()
val policies = get("policies")
@@ -67,8 +69,8 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
// Search for language
policy.keys.forEach { policyKey ->
when (policyKey) {
- "version" -> Unit // Ignore
- userLanguage -> {
+ "version" -> Unit // Ignore
+ userLanguage -> {
// We found the data for the user language
userLanguageUrlAndName = extractUrlAndName(policy[policyKey])
}
@@ -76,7 +78,7 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
// We found default language
defaultLanguageUrlAndName = extractUrlAndName(policy[policyKey])
}
- else -> {
+ else -> {
if (firstUrlAndName == null) {
// Get at least some data
firstUrlAndName = extractUrlAndName(policy[policyKey])
@@ -87,7 +89,7 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
// Copy found language data by priority
when {
- userLanguageUrlAndName != null -> {
+ userLanguageUrlAndName != null -> {
localizedFlowDataLoginTermsLocalizedUrl = userLanguageUrlAndName!!.url
localizedFlowDataLoginTermsLocalizedName = userLanguageUrlAndName!!.name
}
@@ -95,7 +97,7 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String,
localizedFlowDataLoginTermsLocalizedUrl = defaultLanguageUrlAndName!!.url
localizedFlowDataLoginTermsLocalizedName = defaultLanguageUrlAndName!!.name
}
- firstUrlAndName != null -> {
+ firstUrlAndName != null -> {
localizedFlowDataLoginTermsLocalizedUrl = firstUrlAndName!!.url
localizedFlowDataLoginTermsLocalizedName = firstUrlAndName!!.name
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/LoginFlowResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/LoginFlowResult.kt
index 7d1407c0d8..5b6c1897bf 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/LoginFlowResult.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/LoginFlowResult.kt
@@ -21,5 +21,6 @@ data class LoginFlowResult(
val ssoIdentityProviders: List?,
val isLoginAndRegistrationSupported: Boolean,
val homeServerUrl: String,
- val isOutdatedHomeserver: Boolean
+ val isOutdatedHomeserver: Boolean,
+ val isLogoutDevicesSupported: Boolean
)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SsoIdentityProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SsoIdentityProvider.kt
index a0733dda97..773f5a8cc4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SsoIdentityProvider.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SsoIdentityProvider.kt
@@ -66,17 +66,17 @@ data class SsoIdentityProvider(
private fun toPriority(): Int {
return when (brand) {
// We are on Android, so user is more likely to have a Google account
- BRAND_GOOGLE -> 5
+ BRAND_GOOGLE -> 5
// Facebook is also an important SSO provider
BRAND_FACEBOOK -> 4
// Twitter is more for professionals
- BRAND_TWITTER -> 3
+ BRAND_TWITTER -> 3
// Here it's very for techie people
BRAND_GITHUB,
- BRAND_GITLAB -> 2
+ BRAND_GITLAB -> 2
// And finally, if the account has been created with an iPhone...
- BRAND_APPLE -> 1
- else -> 0
+ BRAND_APPLE -> 1
+ else -> 0
}
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt
index 3232025de3..145cdbdc22 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt
@@ -39,10 +39,12 @@ interface LoginWizard {
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
* @return a [Session] if the login is successful
*/
- suspend fun login(login: String,
- password: String,
- initialDeviceName: String,
- deviceId: String? = null): Session
+ suspend fun login(
+ login: String,
+ password: String,
+ initialDeviceName: String,
+ deviceId: String? = null
+ ): Session
/**
* Exchange a login token to an access token.
@@ -63,14 +65,16 @@ interface LoginWizard {
* [resetPasswordMailConfirmed] is successfully called.
*
* @param email an email previously associated to the account the user wants the password to be reset.
- * @param newPassword the desired new password
*/
- suspend fun resetPassword(email: String,
- newPassword: String)
+ suspend fun resetPassword(email: String)
/**
* Confirm the new password, once the user has checked their email
* When this method succeed, tha account password will be effectively modified.
+ *
+ * @param newPassword the desired new password.
+ * @param logoutAllDevices defaults to true, all devices will be logged out. False values will only be taken into account
+ * if [org.matrix.android.sdk.api.auth.data.LoginFlowResult.isLogoutDevicesSupported] is true.
*/
- suspend fun resetPasswordMailConfirmed()
+ suspend fun resetPasswordMailConfirmed(newPassword: String, logoutAllDevices: Boolean = true)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt
index 1252e93b84..98542d2086 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt
@@ -88,15 +88,15 @@ fun RegistrationFlowResponse.toFlowResult(): FlowResult {
val isMandatory = flows?.all { type in it.stages.orEmpty() } == true
val stage = when (type) {
- LoginFlowTypes.RECAPTCHA -> Stage.ReCaptcha(
+ LoginFlowTypes.RECAPTCHA -> Stage.ReCaptcha(
isMandatory, ((params?.get(type) as? Map<*, *>)?.get("public_key") as? String)
?: ""
)
- LoginFlowTypes.DUMMY -> Stage.Dummy(isMandatory)
- LoginFlowTypes.TERMS -> Stage.Terms(isMandatory, params?.get(type) as? TermPolicies ?: emptyMap())
+ LoginFlowTypes.DUMMY -> Stage.Dummy(isMandatory)
+ LoginFlowTypes.TERMS -> Stage.Terms(isMandatory, params?.get(type) as? TermPolicies ?: emptyMap())
LoginFlowTypes.EMAIL_IDENTITY -> Stage.Email(isMandatory)
- LoginFlowTypes.MSISDN -> Stage.Msisdn(isMandatory)
- else -> Stage.Other(isMandatory, type, (params?.get(type) as? Map<*, *>))
+ LoginFlowTypes.MSISDN -> Stage.Msisdn(isMandatory)
+ else -> Stage.Other(isMandatory, type, (params?.get(type) as? Map<*, *>))
}
if (type in completedStages.orEmpty()) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt
index 14d26bf2b3..995fd27ace 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt
@@ -54,9 +54,11 @@ interface RegistrationWizard {
* @param password the desired password
* @param initialDeviceDisplayName the device display name
*/
- suspend fun createAccount(userName: String?,
- password: String?,
- initialDeviceDisplayName: String?): RegistrationResult
+ suspend fun createAccount(
+ userName: String?,
+ password: String?,
+ initialDeviceDisplayName: String?
+ ): RegistrationResult
/**
* Perform the "m.login.recaptcha" stage.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt
index 56257db79c..ea5570db1c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt
@@ -26,9 +26,11 @@ sealed class WellknownResult {
* Retrieve the specific piece of information from the user in a way which fits within the existing client user experience,
* if the client is inclined to do so. Failure can take place instead if no good user experience for this is possible at this point.
*/
- data class Prompt(val homeServerUrl: String,
- val identityServerUrl: String?,
- val wellKnown: WellKnown) : WellknownResult()
+ data class Prompt(
+ val homeServerUrl: String,
+ val identityServerUrl: String?,
+ val wellKnown: WellKnown
+ ) : WellknownResult()
/**
* Stop the current auto-discovery mechanism. If no more auto-discovery mechanisms are available,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/debug/DebugService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/debug/DebugService.kt
new file mode 100644
index 0000000000..d0cee08831
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/debug/DebugService.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.api.debug
+
+import io.realm.RealmConfiguration
+
+/**
+ * Useful methods to access to some private data managed by the SDK.
+ */
+interface DebugService {
+ /**
+ * Get all the available Realm Configuration.
+ */
+ fun getAllRealmConfigurations(): List
+
+ /**
+ * Prints out info on DB size to logcat.
+ */
+ fun logDbUsageInfo()
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/Strings.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/Strings.kt
index 5e1350e327..9f979098f8 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/Strings.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/Strings.kt
@@ -19,7 +19,7 @@ package org.matrix.android.sdk.api.extensions
fun CharSequence.ensurePrefix(prefix: CharSequence): CharSequence {
return when {
startsWith(prefix) -> this
- else -> "$prefix$this"
+ else -> "$prefix$this"
}
}
@@ -27,3 +27,8 @@ fun CharSequence.ensurePrefix(prefix: CharSequence): CharSequence {
* Append a new line and then the provided string.
*/
fun StringBuilder.appendNl(str: String) = append("\n").append(str)
+
+/**
+ * Returns null if the string is empty.
+ */
+fun String.ensureNotEmpty() = ifEmpty { null }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/network/ssl/Fingerprint.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/network/ssl/Fingerprint.kt
index 93e93fd292..2fc04013f9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/network/ssl/Fingerprint.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/network/ssl/Fingerprint.kt
@@ -36,7 +36,7 @@ data class Fingerprint(
internal fun matchesCert(cert: X509Certificate): Boolean {
val o: Fingerprint? = when (hashType) {
HashType.SHA256 -> newSha256Fingerprint(cert)
- HashType.SHA1 -> newSha1Fingerprint(cert)
+ HashType.SHA1 -> newSha1Fingerprint(cert)
}
return equals(o)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt
index f08c86885d..d3f6ec2287 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt
@@ -16,6 +16,11 @@
package org.matrix.android.sdk.api.query
+/**
+ * Only a subset of [QueryStringValue] are applicable to query the `stateKey` of a state event.
+ */
+sealed interface QueryStateEventValue
+
/**
* Basic query language. All these cases are mutually exclusive.
*/
@@ -33,22 +38,22 @@ sealed interface QueryStringValue {
/**
* The tested field has to be not null.
*/
- object IsNotNull : QueryStringValue
+ object IsNotNull : QueryStringValue, QueryStateEventValue
/**
* The tested field has to be empty.
*/
- object IsEmpty : QueryStringValue
+ object IsEmpty : QueryStringValue, QueryStateEventValue
/**
- * The tested field has to not empty.
+ * The tested field has to be not empty.
*/
- object IsNotEmpty : QueryStringValue
+ object IsNotEmpty : QueryStringValue, QueryStateEventValue
/**
* Interface to check String content.
*/
- sealed interface ContentQueryStringValue : QueryStringValue {
+ sealed interface ContentQueryStringValue : QueryStringValue, QueryStateEventValue {
val string: String
val case: Case
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecretStoringUtils.kt
similarity index 81%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecretStoringUtils.kt
index 07a5cbe5a0..bd2a1078b2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecretStoringUtils.kt
@@ -16,7 +16,7 @@
@file:Suppress("DEPRECATION")
-package org.matrix.android.sdk.internal.session.securestorage
+package org.matrix.android.sdk.api.securestorage
import android.annotation.SuppressLint
import android.content.Context
@@ -25,7 +25,7 @@ import android.security.KeyPairGeneratorSpec
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import androidx.annotation.RequiresApi
-import org.matrix.android.sdk.internal.util.system.BuildVersionSdkIntProvider
+import org.matrix.android.sdk.api.util.BuildVersionSdkIntProvider
import timber.log.Timber
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
@@ -80,9 +80,11 @@ import javax.security.auth.x500.X500Principal
* Important: Keys stored in the keystore can be wiped out (depends of the OS version, like for example if you
* add a pin or change the schema); So you might and with a useless pile of bytes.
*/
-internal class SecretStoringUtils @Inject constructor(
+class SecretStoringUtils @Inject constructor(
private val context: Context,
- private val buildVersionSdkIntProvider: BuildVersionSdkIntProvider
+ private val keyStore: KeyStore,
+ private val buildVersionSdkIntProvider: BuildVersionSdkIntProvider,
+ private val keyNeedsUserAuthentication: Boolean = false,
) {
companion object {
@@ -94,14 +96,24 @@ internal class SecretStoringUtils @Inject constructor(
private const val FORMAT_1: Byte = 1
}
- private val keyStore: KeyStore by lazy {
- KeyStore.getInstance(ANDROID_KEY_STORE).apply {
- load(null)
- }
- }
-
private val secureRandom = SecureRandom()
+ /**
+ * Allows creation of the crypto keys associated witht he [alias] before encrypting some value with it.
+ * @return A [KeyStore.Entry] with the keys.
+ */
+ @SuppressLint("NewApi")
+ fun ensureKey(alias: String): KeyStore.Entry {
+ when {
+ buildVersionSdkIntProvider.get() >= Build.VERSION_CODES.M -> getOrGenerateSymmetricKeyForAliasM(alias)
+ else -> getOrGenerateKeyPairForAlias(alias).privateKey
+ }
+ return keyStore.getEntry(alias, null)
+ }
+
+ /**
+ * Deletes the key associated with the [keyAlias] and logs any [KeyStoreException] that could happen.
+ */
fun safeDeleteKey(keyAlias: String) {
try {
keyStore.deleteEntry(keyAlias)
@@ -121,25 +133,25 @@ internal class SecretStoringUtils @Inject constructor(
*/
@SuppressLint("NewApi")
@Throws(Exception::class)
- fun securelyStoreString(secret: String, keyAlias: String): ByteArray {
+ fun securelyStoreBytes(secret: ByteArray, keyAlias: String): ByteArray {
return when {
- buildVersionSdkIntProvider.get() >= Build.VERSION_CODES.M -> encryptStringM(secret, keyAlias)
- else -> encryptString(secret, keyAlias)
+ buildVersionSdkIntProvider.get() >= Build.VERSION_CODES.M -> encryptBytesM(secret, keyAlias)
+ else -> encryptBytes(secret, keyAlias)
}
}
/**
- * Decrypt a secret that was encrypted by #securelyStoreString().
+ * Decrypt a secret that was encrypted by [securelyStoreBytes].
*/
@SuppressLint("NewApi")
@Throws(Exception::class)
- fun loadSecureSecret(encrypted: ByteArray, keyAlias: String): String {
+ fun loadSecureSecretBytes(encrypted: ByteArray, keyAlias: String): ByteArray {
encrypted.inputStream().use { inputStream ->
// First get the format
return when (val format = inputStream.read().toByte()) {
- FORMAT_API_M -> decryptStringM(inputStream, keyAlias)
- FORMAT_1 -> decryptString(inputStream, keyAlias)
- else -> throw IllegalArgumentException("Unknown format $format")
+ FORMAT_API_M -> decryptBytesM(inputStream, keyAlias)
+ FORMAT_1 -> decryptBytes(inputStream, keyAlias)
+ else -> throw IllegalArgumentException("Unknown format $format")
}
}
}
@@ -148,7 +160,7 @@ internal class SecretStoringUtils @Inject constructor(
fun securelyStoreObject(any: Any, keyAlias: String, output: OutputStream) {
when {
buildVersionSdkIntProvider.get() >= Build.VERSION_CODES.M -> saveSecureObjectM(keyAlias, output, any)
- else -> saveSecureObject(keyAlias, output, any)
+ else -> saveSecureObject(keyAlias, output, any)
}
}
@@ -157,11 +169,27 @@ internal class SecretStoringUtils @Inject constructor(
// First get the format
return when (val format = inputStream.read().toByte()) {
FORMAT_API_M -> loadSecureObjectM(keyAlias, inputStream)
- FORMAT_1 -> loadSecureObject(keyAlias, inputStream)
- else -> throw IllegalArgumentException("Unknown format $format")
+ FORMAT_1 -> loadSecureObject(keyAlias, inputStream)
+ else -> throw IllegalArgumentException("Unknown format $format")
}
}
+ fun getEncryptCipher(alias: String): Cipher {
+ val key = when (val keyEntry = ensureKey(alias)) {
+ is KeyStore.SecretKeyEntry -> keyEntry.secretKey
+ is KeyStore.PrivateKeyEntry -> keyEntry.certificate.publicKey
+ else -> throw IllegalStateException("Unknown KeyEntry type.")
+ }
+ val cipherMode = when {
+ buildVersionSdkIntProvider.get() >= Build.VERSION_CODES.M -> AES_MODE
+ else -> RSA_MODE
+ }
+ val cipher = Cipher.getInstance(cipherMode)
+ cipher.init(Cipher.ENCRYPT_MODE, key)
+ return cipher
+ }
+
+ @SuppressLint("NewApi")
@RequiresApi(Build.VERSION_CODES.M)
private fun getOrGenerateSymmetricKeyForAliasM(alias: String): SecretKey {
val secretKeyEntry = (keyStore.getEntry(alias, null) as? KeyStore.SecretKeyEntry)
@@ -176,6 +204,13 @@ internal class SecretStoringUtils @Inject constructor(
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setKeySize(128)
+ .apply {
+ setUserAuthenticationRequired(keyNeedsUserAuthentication)
+ if (buildVersionSdkIntProvider.get() >= Build.VERSION_CODES.N) {
+ setInvalidatedByBiometricEnrollment(true)
+ }
+ }
+ .setUserAuthenticationRequired(keyNeedsUserAuthentication)
.build()
generator.init(keyGenSpec)
return generator.generateKey()
@@ -216,19 +251,16 @@ internal class SecretStoringUtils @Inject constructor(
}
@RequiresApi(Build.VERSION_CODES.M)
- private fun encryptStringM(text: String, keyAlias: String): ByteArray {
- val secretKey = getOrGenerateSymmetricKeyForAliasM(keyAlias)
-
- val cipher = Cipher.getInstance(AES_MODE)
- cipher.init(Cipher.ENCRYPT_MODE, secretKey)
+ private fun encryptBytesM(byteArray: ByteArray, keyAlias: String): ByteArray {
+ val cipher = getEncryptCipher(keyAlias)
val iv = cipher.iv
// we happen the iv to the final result
- val encryptedBytes: ByteArray = cipher.doFinal(text.toByteArray(Charsets.UTF_8))
+ val encryptedBytes: ByteArray = cipher.doFinal(byteArray)
return formatMMake(iv, encryptedBytes)
}
@RequiresApi(Build.VERSION_CODES.M)
- private fun decryptStringM(inputStream: InputStream, keyAlias: String): String {
+ private fun decryptBytesM(inputStream: InputStream, keyAlias: String): ByteArray {
val (iv, encryptedText) = formatMExtract(inputStream)
val secretKey = getOrGenerateSymmetricKeyForAliasM(keyAlias)
@@ -237,10 +269,10 @@ internal class SecretStoringUtils @Inject constructor(
val spec = GCMParameterSpec(128, iv)
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec)
- return String(cipher.doFinal(encryptedText), Charsets.UTF_8)
+ return cipher.doFinal(encryptedText)
}
- private fun encryptString(text: String, keyAlias: String): ByteArray {
+ private fun encryptBytes(byteArray: ByteArray, keyAlias: String): ByteArray {
// we generate a random symmetric key
val key = ByteArray(16)
secureRandom.nextBytes(key)
@@ -252,12 +284,12 @@ internal class SecretStoringUtils @Inject constructor(
val cipher = Cipher.getInstance(AES_MODE)
cipher.init(Cipher.ENCRYPT_MODE, sKey)
val iv = cipher.iv
- val encryptedBytes: ByteArray = cipher.doFinal(text.toByteArray(Charsets.UTF_8))
+ val encryptedBytes: ByteArray = cipher.doFinal(byteArray)
return format1Make(encryptedKey, iv, encryptedBytes)
}
- private fun decryptString(inputStream: InputStream, keyAlias: String): String {
+ private fun decryptBytes(inputStream: InputStream, keyAlias: String): ByteArray {
val (encryptedKey, iv, encrypted) = format1Extract(inputStream)
// we need to decrypt the key
@@ -266,16 +298,13 @@ internal class SecretStoringUtils @Inject constructor(
val spec = GCMParameterSpec(128, iv)
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(sKeyBytes, "AES"), spec)
- return String(cipher.doFinal(encrypted), Charsets.UTF_8)
+ return cipher.doFinal(encrypted)
}
@RequiresApi(Build.VERSION_CODES.M)
@Throws(IOException::class)
private fun saveSecureObjectM(keyAlias: String, output: OutputStream, writeObject: Any) {
- val secretKey = getOrGenerateSymmetricKeyForAliasM(keyAlias)
-
- val cipher = Cipher.getInstance(AES_MODE)
- cipher.init(Cipher.ENCRYPT_MODE, secretKey/*, spec*/)
+ val cipher = getEncryptCipher(keyAlias)
val iv = cipher.iv
val bos1 = ByteArrayOutputStream()
@@ -362,10 +391,8 @@ internal class SecretStoringUtils @Inject constructor(
@Throws(Exception::class)
private fun rsaEncrypt(alias: String, secret: ByteArray): ByteArray {
- val privateKeyEntry = getOrGenerateKeyPairForAlias(alias)
// Encrypt the text
- val inputCipher = Cipher.getInstance(RSA_MODE)
- inputCipher.init(Cipher.ENCRYPT_MODE, privateKeyEntry.certificate.publicKey)
+ val inputCipher = getEncryptCipher(alias)
val outputStream = ByteArrayOutputStream()
CipherOutputStream(outputStream, inputCipher).use {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecureStorageModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecureStorageModule.kt
new file mode 100644
index 0000000000..37a40fd677
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecureStorageModule.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2022 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.api.securestorage
+
+import android.content.Context
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import org.matrix.android.sdk.api.util.BuildVersionSdkIntProvider
+import org.matrix.android.sdk.api.util.DefaultBuildVersionSdkIntProvider
+import java.security.KeyStore
+
+@Module
+internal abstract class SecureStorageModule {
+
+ @Module
+ companion object {
+ @Provides
+ fun provideKeyStore(): KeyStore = KeyStore.getInstance("AndroidKeyStore").also { it.load(null) }
+
+ @Provides
+ fun provideSecretStoringUtils(
+ context: Context,
+ keyStore: KeyStore,
+ buildVersionSdkIntProvider: BuildVersionSdkIntProvider,
+ ): SecretStoringUtils = SecretStoringUtils(context, keyStore, buildVersionSdkIntProvider)
+ }
+
+ @Binds
+ abstract fun bindBuildVersionSdkIntProvider(provider: DefaultBuildVersionSdkIntProvider): BuildVersionSdkIntProvider
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SecureStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecureStorageService.kt
similarity index 93%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SecureStorageService.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecureStorageService.kt
index 6b75c94cb2..e217611d96 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SecureStorageService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/securestorage/SecureStorageService.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.matrix.android.sdk.api.session.securestorage
+package org.matrix.android.sdk.api.securestorage
import java.io.InputStream
import java.io.OutputStream
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt
index 2f1ae8cd87..1b01239de5 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt
@@ -17,8 +17,7 @@
package org.matrix.android.sdk.api.session
import androidx.annotation.MainThread
-import androidx.lifecycle.LiveData
-import kotlinx.coroutines.flow.SharedFlow
+import io.realm.RealmConfiguration
import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.auth.data.SessionParams
@@ -37,7 +36,6 @@ import org.matrix.android.sdk.api.session.file.FileService
import org.matrix.android.sdk.api.session.group.GroupService
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
import org.matrix.android.sdk.api.session.identity.IdentityService
-import org.matrix.android.sdk.api.session.initsync.SyncStatusService
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
import org.matrix.android.sdk.api.session.media.MediaService
import org.matrix.android.sdk.api.session.openid.OpenIdService
@@ -49,14 +47,12 @@ import org.matrix.android.sdk.api.session.pushrules.PushRuleService
import org.matrix.android.sdk.api.session.room.RoomDirectoryService
import org.matrix.android.sdk.api.session.room.RoomService
import org.matrix.android.sdk.api.session.search.SearchService
-import org.matrix.android.sdk.api.session.securestorage.SecureStorageService
import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService
import org.matrix.android.sdk.api.session.signout.SignOutService
import org.matrix.android.sdk.api.session.space.SpaceService
import org.matrix.android.sdk.api.session.statistics.StatisticsListener
import org.matrix.android.sdk.api.session.sync.FilterService
-import org.matrix.android.sdk.api.session.sync.SyncState
-import org.matrix.android.sdk.api.session.sync.model.SyncResponse
+import org.matrix.android.sdk.api.session.sync.SyncService
import org.matrix.android.sdk.api.session.terms.TermsService
import org.matrix.android.sdk.api.session.thirdparty.ThirdPartyService
import org.matrix.android.sdk.api.session.typing.TypingUsersTracker
@@ -98,59 +94,11 @@ interface Session {
@MainThread
fun open()
- /**
- * Requires a one time background sync.
- */
- fun requireBackgroundSync()
-
- /**
- * Launches infinite self rescheduling background syncs via the WorkManager.
- *
- * While dozing, syncs will only occur during maintenance windows.
- * For reliability it's recommended to also start a long running foreground service
- * along with disabling battery optimizations.
- */
- fun startAutomaticBackgroundSync(timeOutInSeconds: Long, repeatDelayInSeconds: Long)
-
- fun stopAnyBackgroundSync()
-
- /**
- * This method start the sync thread.
- */
- fun startSync(fromForeground: Boolean)
-
- /**
- * This method stop the sync thread.
- */
- fun stopSync()
-
/**
* Clear cache of the session.
*/
suspend fun clearCache()
- /**
- * This method allows to listen the sync state.
- * @return a [LiveData] of [SyncState].
- */
- fun getSyncStateLive(): LiveData
-
- /**
- * This method returns the current sync state.
- * @return the current [SyncState].
- */
- fun getSyncState(): SyncState
-
- /**
- * This method returns a flow of SyncResponse. New value will be pushed through the sync thread.
- */
- fun syncFlow(): SharedFlow
-
- /**
- * This methods return true if an initial sync has been processed.
- */
- fun hasAlreadySynced(): Boolean
-
/**
* This method allow to close a session. It does stop some services.
*/
@@ -247,14 +195,9 @@ interface Session {
fun termsService(): TermsService
/**
- * Returns the SyncStatusService associated with the session.
+ * Returns the SyncService associated with the session.
*/
- fun syncStatusService(): SyncStatusService
-
- /**
- * Returns the SecureStorageService associated with the session.
- */
- fun secureStorageService(): SecureStorageService
+ fun syncService(): SyncService
/**
* Returns the ProfileService associated with the session.
@@ -386,7 +329,12 @@ interface Session {
fun getUiaSsoFallbackUrl(authenticationSessionId: String): String
/**
- * Maintenance API, allows to print outs info on DB size to logcat.
+ * Debug API, will print out info on DB size to logcat.
*/
fun logDbUsageInfo()
+
+ /**
+ * Debug API, return the list of all RealmConfiguration used by this session.
+ */
+ fun getRealmConfigurations(): List
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/account/AccountService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/account/AccountService.kt
index 1f28dbd8af..094c66f6f7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/account/AccountService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/account/AccountService.kt
@@ -24,11 +24,13 @@ import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
interface AccountService {
/**
* Ask the homeserver to change the password.
+ *
* @param password Current password.
* @param newPassword New password
+ * @param logoutAllDevices defaults to true, all devices will be logged out. False values will only be taken into account
+ * if [org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities.canControlLogoutDevices] is true.
*/
- suspend fun changePassword(password: String,
- newPassword: String)
+ suspend fun changePassword(password: String, newPassword: String, logoutAllDevices: Boolean = true)
/**
* Deactivate the account.
@@ -46,6 +48,8 @@ interface AccountService {
* an incomplete view of conversations
* @param userInteractiveAuthInterceptor see [UserInteractiveAuthInterceptor]
*/
- suspend fun deactivateAccount(eraseAllData: Boolean,
- userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor)
+ suspend fun deactivateAccount(
+ eraseAllData: Boolean,
+ userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor
+ )
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/MxCall.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/MxCall.kt
index e13f7310e0..c87ac3c821 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/MxCall.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/MxCall.kt
@@ -91,10 +91,12 @@ interface MxCall : MxCallDetail {
* Send a m.call.replaces event to initiate call transfer.
* See [org.matrix.android.sdk.api.session.room.model.call.CallReplacesContent] for documentation about the parameters
*/
- suspend fun transfer(targetUserId: String,
- targetRoomId: String?,
- createCallId: String?,
- awaitCallId: String?)
+ suspend fun transfer(
+ targetUserId: String,
+ targetRoomId: String?,
+ createCallId: String?,
+ awaitCallId: String?
+ )
fun addListener(listener: StateListener)
fun removeListener(listener: StateListener)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt
index 35f3ab3162..638da11804 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt
@@ -88,9 +88,11 @@ interface CryptoService {
fun getDeviceTrackingStatus(userId: String): Int
- suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
- password: String,
- progressListener: ProgressListener?): ImportRoomKeysResult
+ suspend fun importRoomKeys(
+ roomKeysAsArray: ByteArray,
+ password: String,
+ progressListener: ProgressListener?
+ ): ImportRoomKeysResult
suspend fun exportRoomKeys(password: String): ByteArray
@@ -119,10 +121,12 @@ interface CryptoService {
fun isRoomEncrypted(roomId: String): Boolean
// TODO This could be removed from this interface
- fun encryptEventContent(eventContent: Content,
- eventType: String,
- roomId: String,
- callback: MatrixCallback)
+ fun encryptEventContent(
+ eventContent: Content,
+ eventType: String,
+ roomId: String,
+ callback: MatrixCallback
+ )
fun discardOutboundSession(roomId: String)
@@ -167,8 +171,6 @@ interface CryptoService {
fun getSharedWithInfo(roomId: String?, sessionId: String): MXUsersDevicesMap
fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent?
- fun logDbUsageInfo()
-
/**
* Perform any background tasks that can be done before a message is ready to
* send, in order to speed up sending of the message.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt
index 0b5bbe3bbd..94ee7ba403 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt
@@ -25,12 +25,14 @@ import org.matrix.olm.OlmException
*/
sealed class MXCryptoError : Throwable() {
- data class Base(val errorType: ErrorType,
- val technicalMessage: String,
- /**
- * Describe the error with more details.
- */
- val detailedErrorDescription: String? = null) : MXCryptoError()
+ data class Base(
+ val errorType: ErrorType,
+ val technicalMessage: String,
+ /**
+ * Describe the error with more details.
+ */
+ val detailedErrorDescription: String? = null
+ ) : MXCryptoError()
data class OlmError(val olmException: OlmException) : MXCryptoError()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/OutgoingKeyRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/OutgoingKeyRequest.kt
index 855f17a34f..7202be7a21 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/OutgoingKeyRequest.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/OutgoingKeyRequest.kt
@@ -26,7 +26,7 @@ data class RequestReply(
)
sealed class RequestResult {
- data class Success(val chainIndex: Int) : RequestResult()
+ data class Success(val chainIndex: Int) : RequestResult()
data class Failure(val code: WithHeldCode) : RequestResult()
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt
index 5439389096..69f314f76f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt
@@ -37,14 +37,18 @@ interface CrossSigningService {
* Initialize cross signing for this user.
* Users needs to enter credentials
*/
- fun initializeCrossSigning(uiaInterceptor: UserInteractiveAuthInterceptor?,
- callback: MatrixCallback)
+ fun initializeCrossSigning(
+ uiaInterceptor: UserInteractiveAuthInterceptor?,
+ callback: MatrixCallback
+ )
fun isCrossSigningInitialized(): Boolean = getMyCrossSigningKeys() != null
- fun checkTrustFromPrivateKeys(masterKeyPrivateKey: String?,
- uskKeyPrivateKey: String?,
- sskPrivateKey: String?): UserTrustResult
+ fun checkTrustFromPrivateKeys(
+ masterKeyPrivateKey: String?,
+ uskKeyPrivateKey: String?,
+ sskPrivateKey: String?
+ ): UserTrustResult
fun getUserCrossSigningKeys(otherUserId: String): MXCrossSigningInfo?
@@ -60,20 +64,26 @@ interface CrossSigningService {
fun allPrivateKeysKnown(): Boolean
- fun trustUser(otherUserId: String,
- callback: MatrixCallback)
+ fun trustUser(
+ otherUserId: String,
+ callback: MatrixCallback
+ )
fun markMyMasterKeyAsTrusted()
/**
* Sign one of your devices and upload the signature.
*/
- fun trustDevice(deviceId: String,
- callback: MatrixCallback)
+ fun trustDevice(
+ deviceId: String,
+ callback: MatrixCallback
+ )
- fun checkDeviceTrust(otherUserId: String,
- otherDeviceId: String,
- locallyTrusted: Boolean?): DeviceTrustResult
+ fun checkDeviceTrust(
+ otherUserId: String,
+ otherDeviceId: String,
+ locallyTrusted: Boolean?
+ ): DeviceTrustResult
// FIXME Those method do not have to be in the service
fun onSecretMSKGossip(mskPrivateKey: String)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupLastVersionResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupLastVersionResult.kt
index a7e985cea9..92510bb52e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupLastVersionResult.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupLastVersionResult.kt
@@ -24,5 +24,5 @@ sealed interface KeysBackupLastVersionResult {
fun KeysBackupLastVersionResult.toKeysVersionResult(): KeysVersionResult? = when (this) {
is KeysBackupLastVersionResult.KeysBackup -> keysVersionResult
- KeysBackupLastVersionResult.NoKeysBackup -> null
+ KeysBackupLastVersionResult.NoKeysBackup -> null
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt
index dc8b03eaae..8745003f9f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt
@@ -36,8 +36,10 @@ interface KeysBackupService {
* @param keysBackupCreationInfo the info object from [prepareKeysBackupVersion].
* @param callback Asynchronous callback
*/
- fun createKeysBackupVersion(keysBackupCreationInfo: MegolmBackupCreationInfo,
- callback: MatrixCallback)
+ fun createKeysBackupVersion(
+ keysBackupCreationInfo: MegolmBackupCreationInfo,
+ callback: MatrixCallback
+ )
/**
* Facility method to get the total number of locally stored keys.
@@ -55,8 +57,10 @@ interface KeysBackupService {
* @param progressListener the callback to follow the progress
* @param callback the main callback
*/
- fun backupAllGroupSessions(progressListener: ProgressListener?,
- callback: MatrixCallback?)
+ fun backupAllGroupSessions(
+ progressListener: ProgressListener?,
+ callback: MatrixCallback?
+ )
/**
* Check trust on a key backup version.
@@ -64,8 +68,10 @@ interface KeysBackupService {
* @param keysBackupVersion the backup version to check.
* @param callback block called when the operations completes.
*/
- fun getKeysBackupTrust(keysBackupVersion: KeysVersionResult,
- callback: MatrixCallback)
+ fun getKeysBackupTrust(
+ keysBackupVersion: KeysVersionResult,
+ callback: MatrixCallback
+ )
/**
* Return the current progress of the backup.
@@ -79,8 +85,10 @@ interface KeysBackupService {
* @param version the backup version
* @param callback
*/
- fun getVersion(version: String,
- callback: MatrixCallback)
+ fun getVersion(
+ version: String,
+ callback: MatrixCallback
+ )
/**
* This method fetches the last backup version on the server, then compare to the currently backup version use.
@@ -114,9 +122,11 @@ interface KeysBackupService {
* @param progressListener a progress listener, as generating private key from password may take a while
* @param callback Asynchronous callback
*/
- fun prepareKeysBackupVersion(password: String?,
- progressListener: ProgressListener?,
- callback: MatrixCallback)
+ fun prepareKeysBackupVersion(
+ password: String?,
+ progressListener: ProgressListener?,
+ callback: MatrixCallback
+ )
/**
* Delete a keys backup version. It will delete all backed up keys on the server, and the backup itself.
@@ -125,8 +135,10 @@ interface KeysBackupService {
* @param version the backup version to delete.
* @param callback Asynchronous callback
*/
- fun deleteBackup(version: String,
- callback: MatrixCallback?)
+ fun deleteBackup(
+ version: String,
+ callback: MatrixCallback?
+ )
/**
* Ask if the backup on the server contains keys that we may do not have locally.
@@ -142,9 +154,11 @@ interface KeysBackupService {
* @param trust the trust to set to the keys backup.
* @param callback block called when the operations completes.
*/
- fun trustKeysBackupVersion(keysBackupVersion: KeysVersionResult,
- trust: Boolean,
- callback: MatrixCallback)
+ fun trustKeysBackupVersion(
+ keysBackupVersion: KeysVersionResult,
+ trust: Boolean,
+ callback: MatrixCallback
+ )
/**
* Set trust on a keys backup version.
@@ -153,9 +167,11 @@ interface KeysBackupService {
* @param recoveryKey the recovery key to challenge with the key backup public key.
* @param callback block called when the operations completes.
*/
- fun trustKeysBackupVersionWithRecoveryKey(keysBackupVersion: KeysVersionResult,
- recoveryKey: String,
- callback: MatrixCallback)
+ fun trustKeysBackupVersionWithRecoveryKey(
+ keysBackupVersion: KeysVersionResult,
+ recoveryKey: String,
+ callback: MatrixCallback
+ )
/**
* Set trust on a keys backup version.
@@ -164,9 +180,11 @@ interface KeysBackupService {
* @param password the pass phrase to challenge with the keyBackupVersion public key.
* @param callback block called when the operations completes.
*/
- fun trustKeysBackupVersionWithPassphrase(keysBackupVersion: KeysVersionResult,
- password: String,
- callback: MatrixCallback)
+ fun trustKeysBackupVersionWithPassphrase(
+ keysBackupVersion: KeysVersionResult,
+ password: String,
+ callback: MatrixCallback
+ )
/**
* Restore a backup with a recovery key from a given backup version stored on the homeserver.
@@ -178,11 +196,14 @@ interface KeysBackupService {
* @param stepProgressListener the step progress listener
* @param callback Callback. It provides the number of found keys and the number of successfully imported keys.
*/
- fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult,
- recoveryKey: String, roomId: String?,
- sessionId: String?,
- stepProgressListener: StepProgressListener?,
- callback: MatrixCallback)
+ fun restoreKeysWithRecoveryKey(
+ keysVersionResult: KeysVersionResult,
+ recoveryKey: String,
+ roomId: String?,
+ sessionId: String?,
+ stepProgressListener: StepProgressListener?,
+ callback: MatrixCallback
+ )
/**
* Restore a backup with a password from a given backup version stored on the homeserver.
@@ -194,12 +215,14 @@ interface KeysBackupService {
* @param stepProgressListener the step progress listener
* @param callback Callback. It provides the number of found keys and the number of successfully imported keys.
*/
- fun restoreKeyBackupWithPassword(keysBackupVersion: KeysVersionResult,
- password: String,
- roomId: String?,
- sessionId: String?,
- stepProgressListener: StepProgressListener?,
- callback: MatrixCallback)
+ fun restoreKeyBackupWithPassword(
+ keysBackupVersion: KeysVersionResult,
+ password: String,
+ roomId: String?,
+ sessionId: String?,
+ stepProgressListener: StepProgressListener?,
+ callback: MatrixCallback
+ )
val keysBackupVersion: KeysVersionResult?
@@ -216,8 +239,10 @@ interface KeysBackupService {
fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String, callback: MatrixCallback)
- fun computePrivateKey(passphrase: String,
- privateKeySalt: String,
- privateKeyIterations: Int,
- progressListener: ProgressListener): ByteArray
+ fun computePrivateKey(
+ passphrase: String,
+ privateKeySalt: String,
+ privateKeyIterations: Int,
+ progressListener: ProgressListener
+ ): ByteArray
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrustSignature.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrustSignature.kt
index 7127c8d3f4..afbf45ac70 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrustSignature.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrustSignature.kt
@@ -40,7 +40,8 @@ sealed class KeysBackupVersionTrustSignature {
/**
* Flag to indicate the signature from this device is valid.
*/
- val valid: Boolean) : KeysBackupVersionTrustSignature()
+ val valid: Boolean
+ ) : KeysBackupVersionTrustSignature()
data class UserSignature(
val keyId: String?,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/EmojiRepresentation.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/EmojiRepresentation.kt
index 2c1bf9ff4d..5402471e46 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/EmojiRepresentation.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/EmojiRepresentation.kt
@@ -19,7 +19,8 @@ package org.matrix.android.sdk.api.session.crypto.verification
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
-data class EmojiRepresentation(val emoji: String,
- @StringRes val nameResId: Int,
- @DrawableRes val drawableRes: Int? = null
+data class EmojiRepresentation(
+ val emoji: String,
+ @StringRes val nameResId: Int,
+ @DrawableRes val drawableRes: Int? = null
)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt
index 321ec73094..ee93f14992 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt
@@ -46,54 +46,68 @@ interface VerificationService {
fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest?
- fun beginKeyVerification(method: VerificationMethod,
- otherUserId: String,
- otherDeviceId: String,
- transactionId: String?): String?
+ fun beginKeyVerification(
+ method: VerificationMethod,
+ otherUserId: String,
+ otherDeviceId: String,
+ transactionId: String?
+ ): String?
/**
* Request key verification with another user via room events (instead of the to-device API).
*/
- fun requestKeyVerificationInDMs(methods: List,
- otherUserId: String,
- roomId: String,
- localId: String? = LocalEcho.createLocalEchoId()): PendingVerificationRequest
+ fun requestKeyVerificationInDMs(
+ methods: List,
+ otherUserId: String,
+ roomId: String,
+ localId: String? = LocalEcho.createLocalEchoId()
+ ): PendingVerificationRequest
fun cancelVerificationRequest(request: PendingVerificationRequest)
/**
* Request a key verification from another user using toDevice events.
*/
- fun requestKeyVerification(methods: List,
- otherUserId: String,
- otherDevices: List?): PendingVerificationRequest
+ fun requestKeyVerification(
+ methods: List,
+ otherUserId: String,
+ otherDevices: List?
+ ): PendingVerificationRequest
- fun declineVerificationRequestInDMs(otherUserId: String,
- transactionId: String,
- roomId: String)
+ fun declineVerificationRequestInDMs(
+ otherUserId: String,
+ transactionId: String,
+ roomId: String
+ )
// Only SAS method is supported for the moment
// TODO Parameter otherDeviceId should be removed in this case
- fun beginKeyVerificationInDMs(method: VerificationMethod,
- transactionId: String,
- roomId: String,
- otherUserId: String,
- otherDeviceId: String): String
+ fun beginKeyVerificationInDMs(
+ method: VerificationMethod,
+ transactionId: String,
+ roomId: String,
+ otherUserId: String,
+ otherDeviceId: String
+ ): String
/**
* Returns false if the request is unknown.
*/
- fun readyPendingVerificationInDMs(methods: List,
- otherUserId: String,
- roomId: String,
- transactionId: String): Boolean
+ fun readyPendingVerificationInDMs(
+ methods: List,
+ otherUserId: String,
+ roomId: String,
+ transactionId: String
+ ): Boolean
/**
* Returns false if the request is unknown.
*/
- fun readyPendingVerification(methods: List,
- otherUserId: String,
- transactionId: String): Boolean
+ fun readyPendingVerification(
+ methods: List,
+ otherUserId: String,
+ transactionId: String
+ ): Boolean
interface Listener {
/**
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/EventService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/EventService.kt
index 297f277497..7f275bf952 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/EventService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/EventService.kt
@@ -24,6 +24,8 @@ interface EventService {
* Ask the homeserver for an event content. The SDK will try to decrypt it if it is possible
* The result will not be stored into cache
*/
- suspend fun getEvent(roomId: String,
- eventId: String): Event
+ suspend fun getEvent(
+ roomId: String,
+ eventId: String
+ ): Event
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
index 7124d8a1a3..7f9ab4c6dd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
@@ -212,13 +212,13 @@ data class Event(
return when {
isReplyRenderedInThread() || isQuote() -> ContentUtils.extractUsefulTextFromReply(text)
- isFileMessage() -> "sent a file."
- isAudioMessage() -> "sent an audio file."
- isImageMessage() -> "sent an image."
- isVideoMessage() -> "sent a video."
- isSticker() -> "sent a sticker"
- isPoll() -> getPollQuestion() ?: "created a poll."
- else -> text
+ isFileMessage() -> "sent a file."
+ isAudioMessage() -> "sent an audio file."
+ isImageMessage() -> "sent an image."
+ isVideoMessage() -> "sent a video."
+ isSticker() -> "sent a sticker"
+ isPoll() -> getPollQuestion() ?: "created a poll."
+ else -> text
}
}
@@ -318,35 +318,35 @@ fun Event.isTextMessage(): Boolean {
MessageType.MSGTYPE_TEXT,
MessageType.MSGTYPE_EMOTE,
MessageType.MSGTYPE_NOTICE -> true
- else -> false
+ else -> false
}
}
fun Event.isImageMessage(): Boolean {
return when (getMsgType()) {
MessageType.MSGTYPE_IMAGE -> true
- else -> false
+ else -> false
}
}
fun Event.isVideoMessage(): Boolean {
return when (getMsgType()) {
MessageType.MSGTYPE_VIDEO -> true
- else -> false
+ else -> false
}
}
fun Event.isAudioMessage(): Boolean {
return when (getMsgType()) {
MessageType.MSGTYPE_AUDIO -> true
- else -> false
+ else -> false
}
}
fun Event.isFileMessage(): Boolean {
return when (getMsgType()) {
MessageType.MSGTYPE_FILE -> true
- else -> false
+ else -> false
}
}
@@ -356,14 +356,14 @@ fun Event.isAttachmentMessage(): Boolean {
MessageType.MSGTYPE_AUDIO,
MessageType.MSGTYPE_VIDEO,
MessageType.MSGTYPE_FILE -> true
- else -> false
+ else -> false
}
}
fun Event.isLocationMessage(): Boolean {
return when (getMsgType()) {
MessageType.MSGTYPE_LOCATION -> true
- else -> false
+ else -> false
}
}
@@ -378,9 +378,9 @@ fun Event.getRelationContent(): RelationDefaultContent? {
content.toModel()?.relatesTo ?: run {
// Special cases when there is only a local msgtype for some event types
when (getClearType()) {
- EventType.STICKER -> getClearContent().toModel()?.relatesTo
+ EventType.STICKER -> getClearContent().toModel()?.relatesTo
in EventType.BEACON_LOCATION_DATA -> getClearContent().toModel()?.relatesTo
- else -> null
+ else -> null
}
}
}
@@ -427,3 +427,6 @@ fun Event.getPollContent(): MessagePollContent? {
fun Event.supportsNotification() =
this.getClearType() in EventType.MESSAGE + EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO
+
+fun Event.isContentReportable() =
+ this.getClearType() in EventType.MESSAGE + EventType.STATE_ROOM_BEACON_INFO
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyWithHeldContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyWithHeldContent.kt
index d58c3614a7..fb8b65c4f2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyWithHeldContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyWithHeldContent.kt
@@ -98,12 +98,12 @@ enum class WithHeldCode(val value: String) {
companion object {
fun fromCode(code: String?): WithHeldCode? {
return when (code) {
- BLACKLISTED.value -> BLACKLISTED
- UNVERIFIED.value -> UNVERIFIED
+ BLACKLISTED.value -> BLACKLISTED
+ UNVERIFIED.value -> UNVERIFIED
UNAUTHORISED.value -> UNAUTHORISED
- UNAVAILABLE.value -> UNAVAILABLE
- NO_OLM.value -> NO_OLM
- else -> null
+ UNAVAILABLE.value -> UNAVAILABLE
+ NO_OLM.value -> NO_OLM
+ else -> null
}
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt
index a7c81136e3..ca6c889cb8 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt
@@ -44,10 +44,12 @@ interface FileService {
* Download a file if necessary and ensure that if the file is encrypted, the file is decrypted.
* Result will be a decrypted file, stored in the cache folder. url parameter will be used to create unique filename to avoid name collision.
*/
- suspend fun downloadFile(fileName: String,
- mimeType: String?,
- url: String?,
- elementToDecrypt: ElementToDecrypt?): File
+ suspend fun downloadFile(
+ fileName: String,
+ mimeType: String?,
+ url: String?,
+ elementToDecrypt: ElementToDecrypt?
+ ): File
suspend fun downloadFile(messageContent: MessageWithAttachmentContent): File =
downloadFile(
@@ -57,10 +59,11 @@ interface FileService {
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt()
)
- fun isFileInCache(mxcUrl: String?,
- fileName: String,
- mimeType: String?,
- elementToDecrypt: ElementToDecrypt?
+ fun isFileInCache(
+ mxcUrl: String?,
+ fileName: String,
+ mimeType: String?,
+ elementToDecrypt: ElementToDecrypt?
): Boolean
fun isFileInCache(messageContent: MessageWithAttachmentContent) =
@@ -75,10 +78,12 @@ interface FileService {
* Use this URI and pass it to intent using flag Intent.FLAG_GRANT_READ_URI_PERMISSION
* (if not other app won't be able to access it).
*/
- fun getTemporarySharableURI(mxcUrl: String?,
- fileName: String,
- mimeType: String?,
- elementToDecrypt: ElementToDecrypt?): Uri?
+ fun getTemporarySharableURI(
+ mxcUrl: String?,
+ fileName: String,
+ mimeType: String?,
+ elementToDecrypt: ElementToDecrypt?
+ ): Uri?
fun getTemporarySharableURI(messageContent: MessageWithAttachmentContent): Uri? =
getTemporarySharableURI(
@@ -92,10 +97,12 @@ interface FileService {
* Get information on the given file.
* Mimetype should be the same one as passed to downloadFile (limitation for now)
*/
- fun fileState(mxcUrl: String?,
- fileName: String,
- mimeType: String?,
- elementToDecrypt: ElementToDecrypt?): FileState
+ fun fileState(
+ mxcUrl: String?,
+ fileName: String,
+ mimeType: String?,
+ elementToDecrypt: ElementToDecrypt?
+ ): FileState
fun fileState(messageContent: MessageWithAttachmentContent): FileState =
fileState(
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt
index 5b06fdacae..b5d6d891e4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt
@@ -54,7 +54,12 @@ data class HomeServerCapabilities(
/**
* True if the home server support threading.
*/
- val canUseThreading: Boolean = false
+ val canUseThreading: Boolean = false,
+
+ /**
+ * True if the home server supports controlling the logout of all devices when changing password.
+ */
+ val canControlLogoutDevices: Boolean = false
) {
enum class RoomCapabilitySupport {
@@ -81,13 +86,13 @@ data class HomeServerCapabilities(
val versionCap = roomVersions.supportedVersion.firstOrNull { it.version == preferred }
return when {
- versionCap == null -> {
+ versionCap == null -> {
RoomCapabilitySupport.UNKNOWN
}
versionCap.status == RoomVersionStatus.STABLE -> {
RoomCapabilitySupport.SUPPORTED
}
- else -> {
+ else -> {
RoomCapabilitySupport.SUPPORTED_UNSTABLE
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/ThreePid.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/ThreePid.kt
index 42d777849b..6bcf576824 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/ThreePid.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/ThreePid.kt
@@ -27,7 +27,7 @@ sealed class ThreePid(open val value: String) {
internal fun ThreePid.toMedium(): String {
return when (this) {
- is ThreePid.Email -> ThirdPartyIdentifier.MEDIUM_EMAIL
+ is ThreePid.Email -> ThirdPartyIdentifier.MEDIUM_EMAIL
is ThreePid.Msisdn -> ThirdPartyIdentifier.MEDIUM_MSISDN
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt
deleted file mode 100644
index 7006e11751..0000000000
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2020 The Matrix.org Foundation C.I.C.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.matrix.android.sdk.api.session.initsync
-
-import androidx.lifecycle.LiveData
-
-interface SyncStatusService {
-
- fun getSyncStatusLive(): LiveData
-
- sealed class Status {
- /**
- * For initial sync.
- */
- abstract class InitialSyncStatus : Status()
-
- object Idle : InitialSyncStatus()
- data class InitialSyncProgressing(
- val initSyncStep: InitSyncStep,
- val percentProgress: Int = 0
- ) : InitialSyncStatus()
-
- /**
- * For incremental sync.
- */
- abstract class IncrementalSyncStatus : Status()
-
- object IncrementalSyncIdle : IncrementalSyncStatus()
- data class IncrementalSyncParsing(
- val rooms: Int,
- val toDevice: Int
- ) : IncrementalSyncStatus()
-
- object IncrementalSyncError : IncrementalSyncStatus()
- object IncrementalSyncDone : IncrementalSyncStatus()
- }
-}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixPermalinkSpan.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixPermalinkSpan.kt
index 48b30dfa21..9c71c081be 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixPermalinkSpan.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixPermalinkSpan.kt
@@ -25,8 +25,10 @@ import org.matrix.android.sdk.api.session.permalinks.MatrixPermalinkSpan.Callbac
* @property url the permalink url tied to the span
* @property callback the callback to use.
*/
-class MatrixPermalinkSpan(private val url: String,
- private val callback: Callback? = null) : ClickableSpan() {
+class MatrixPermalinkSpan(
+ private val url: String,
+ private val callback: Callback? = null
+) : ClickableSpan() {
interface Callback {
fun onUrlClicked(url: String)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixToConverter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixToConverter.kt
index a904e89681..c418b59df4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixToConverter.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixToConverter.kt
@@ -38,12 +38,12 @@ object MatrixToConverter {
// URL is already a matrix.to
uriString.startsWith(PermalinkService.MATRIX_TO_URL_BASE) -> uri
// Web or client url
- SUPPORTED_PATHS.any { it in uriString } -> {
+ SUPPORTED_PATHS.any { it in uriString } -> {
val path = SUPPORTED_PATHS.first { it in uriString }
Uri.parse(PermalinkService.MATRIX_TO_URL_BASE + uriString.substringAfter(path))
}
// URL is not supported
- else -> null
+ else -> null
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt
index 9d078dc4b2..0168b7ac3a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt
@@ -67,10 +67,10 @@ object PermalinkParser {
val identifier = params.getOrNull(0)
val extraParameter = params.getOrNull(1)
return when {
- identifier.isNullOrEmpty() -> PermalinkData.FallbackLink(uri)
- MatrixPatterns.isUserId(identifier) -> PermalinkData.UserLink(userId = identifier)
- MatrixPatterns.isGroupId(identifier) -> PermalinkData.GroupLink(groupId = identifier)
- MatrixPatterns.isRoomId(identifier) -> {
+ identifier.isNullOrEmpty() -> PermalinkData.FallbackLink(uri)
+ MatrixPatterns.isUserId(identifier) -> PermalinkData.UserLink(userId = identifier)
+ MatrixPatterns.isGroupId(identifier) -> PermalinkData.GroupLink(groupId = identifier)
+ MatrixPatterns.isRoomId(identifier) -> {
handleRoomIdCase(fragment, identifier, matrixToUri, extraParameter, viaQueryParameters)
}
MatrixPatterns.isRoomAlias(identifier) -> {
@@ -81,7 +81,7 @@ object PermalinkParser {
viaParameters = viaQueryParameters
)
}
- else -> PermalinkData.FallbackLink(uri)
+ else -> PermalinkData.FallbackLink(uri)
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt
index 095f2ef7c2..4c00c76459 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt
@@ -107,8 +107,10 @@ interface ProfileService {
/**
* Finalize adding a 3Pids. Call this method once the user has validated that he owns the ThreePid.
*/
- suspend fun finalizeAddingThreePid(threePid: ThreePid,
- userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor)
+ suspend fun finalizeAddingThreePid(
+ threePid: ThreePid,
+ userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor
+ )
/**
* Cancel adding a threepid. It will remove locally stored data about this ThreePid.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt
index 396f13ce46..d7958ea3cd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt
@@ -58,12 +58,14 @@ interface PushersService {
* email pushers since we don't want to stop other accounts notifying to the same email address.
* @throws [InvalidParameterException] if a parameter is not correct
*/
- suspend fun addEmailPusher(email: String,
- lang: String,
- emailBranding: String,
- appDisplayName: String,
- deviceDisplayName: String,
- append: Boolean = true)
+ suspend fun addEmailPusher(
+ email: String,
+ lang: String,
+ emailBranding: String,
+ appDisplayName: String,
+ deviceDisplayName: String,
+ append: Boolean = true
+ )
/**
* Directly ask the push gateway to send a push to this device.
@@ -75,10 +77,12 @@ interface PushersService {
* @param pushkey the FCM token
* @param eventId the eventId which will be sent in the Push message. Use a fake eventId.
*/
- suspend fun testPush(url: String,
- appId: String,
- pushkey: String,
- eventId: String)
+ suspend fun testPush(
+ url: String,
+ appId: String,
+ pushkey: String,
+ eventId: String
+ )
/**
* Remove a registered pusher.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt
index 2b2930c1ba..6122aae972 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt
@@ -71,15 +71,15 @@ sealed class Action {
fun List.toJson(): List {
return map { action ->
when (action) {
- is Action.Notify -> Action.ACTION_NOTIFY
+ is Action.Notify -> Action.ACTION_NOTIFY
is Action.DoNotNotify -> Action.ACTION_DONT_NOTIFY
- is Action.Sound -> {
+ is Action.Sound -> {
mapOf(
Action.ACTION_OBJECT_SET_TWEAK_KEY to Action.ACTION_OBJECT_SET_TWEAK_VALUE_SOUND,
Action.ACTION_OBJECT_VALUE_KEY to action.sound
)
}
- is Action.Highlight -> {
+ is Action.Highlight -> {
mapOf(
Action.ACTION_OBJECT_SET_TWEAK_KEY to Action.ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT,
Action.ACTION_OBJECT_VALUE_KEY to action.highlight
@@ -94,11 +94,11 @@ fun PushRule.getActions(): List {
actions.forEach { actionStrOrObj ->
when (actionStrOrObj) {
- Action.ACTION_NOTIFY -> Action.Notify
+ Action.ACTION_NOTIFY -> Action.Notify
Action.ACTION_DONT_NOTIFY -> Action.DoNotNotify
- is Map<*, *> -> {
+ is Map<*, *> -> {
when (actionStrOrObj[Action.ACTION_OBJECT_SET_TWEAK_KEY]) {
- Action.ACTION_OBJECT_SET_TWEAK_VALUE_SOUND -> {
+ Action.ACTION_OBJECT_SET_TWEAK_VALUE_SOUND -> {
(actionStrOrObj[Action.ACTION_OBJECT_VALUE_KEY] as? String)?.let { stringValue ->
Action.Sound(stringValue)
}
@@ -112,13 +112,13 @@ fun PushRule.getActions(): List {
// When the value is not there, default is true, says the spec
?: Action.Highlight(true)
}
- else -> {
+ else -> {
Timber.w("Unsupported set_tweak value ${actionStrOrObj[Action.ACTION_OBJECT_SET_TWEAK_KEY]}")
null
}
}
}
- else -> {
+ else -> {
Timber.w("Unsupported action type $actionStrOrObj")
null
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ConditionResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ConditionResolver.kt
index f8a930f987..d64ee5f777 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ConditionResolver.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ConditionResolver.kt
@@ -22,15 +22,23 @@ import org.matrix.android.sdk.api.session.events.model.Event
* This class as all required context needed to evaluate rules
*/
interface ConditionResolver {
- fun resolveEventMatchCondition(event: Event,
- condition: EventMatchCondition): Boolean
+ fun resolveEventMatchCondition(
+ event: Event,
+ condition: EventMatchCondition
+ ): Boolean
- fun resolveRoomMemberCountCondition(event: Event,
- condition: RoomMemberCountCondition): Boolean
+ fun resolveRoomMemberCountCondition(
+ event: Event,
+ condition: RoomMemberCountCondition
+ ): Boolean
- fun resolveSenderNotificationPermissionCondition(event: Event,
- condition: SenderNotificationPermissionCondition): Boolean
+ fun resolveSenderNotificationPermissionCondition(
+ event: Event,
+ condition: SenderNotificationPermissionCondition
+ ): Boolean
- fun resolveContainsDisplayNameCondition(event: Event,
- condition: ContainsDisplayNameCondition): Boolean
+ fun resolveContainsDisplayNameCondition(
+ event: Event,
+ condition: ContainsDisplayNameCondition
+ ): Boolean
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ContainsDisplayNameCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ContainsDisplayNameCondition.kt
index 69dd14ddc2..0bf14345b9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ContainsDisplayNameCondition.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ContainsDisplayNameCondition.kt
@@ -39,7 +39,7 @@ class ContainsDisplayNameCondition : Condition {
// EventType.ENCRYPTED -> {
// event.root.getClearContent()?.toModel()
// }
- else -> null
+ else -> null
} ?: return false
return message.body.caseInsensitiveFind(displayName)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Kind.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Kind.kt
index 463f3c2a73..bba6fe6026 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Kind.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Kind.kt
@@ -27,11 +27,11 @@ enum class Kind(val value: String) {
fun fromString(value: String): Kind {
return when (value) {
- "event_match" -> EventMatch
- "contains_display_name" -> ContainsDisplayName
- "room_member_count" -> RoomMemberCount
+ "event_match" -> EventMatch
+ "contains_display_name" -> ContainsDisplayName
+ "room_member_count" -> RoomMemberCount
"sender_notification_permission" -> SenderNotificationPermission
- else -> Unrecognised
+ else -> Unrecognised
}
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushRuleService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushRuleService.kt
index 7ffbc89559..8f9c25fd30 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushRuleService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushRuleService.kt
@@ -51,8 +51,10 @@ interface PushRuleService {
// fun fulfilledBingRule(event: Event, rules: List): PushRule?
- fun resolveSenderNotificationPermissionCondition(event: Event,
- condition: SenderNotificationPermissionCondition): Boolean
+ fun resolveSenderNotificationPermissionCondition(
+ event: Event,
+ condition: SenderNotificationPermissionCondition
+ ): Boolean
interface PushRuleListener {
fun onEvents(pushEvents: PushEvents)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RoomMemberCountCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RoomMemberCountCondition.kt
index 6973ff1372..db097fd92c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RoomMemberCountCondition.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RoomMemberCountCondition.kt
@@ -47,8 +47,8 @@ class RoomMemberCountCondition(
val numMembers = room.membershipService().getNumberOfJoinedMembers()
return when (prefix) {
- "<" -> numMembers < count
- ">" -> numMembers > count
+ "<" -> numMembers < count
+ ">" -> numMembers > count
"<=" -> numMembers <= count
">=" -> numMembers >= count
else -> numMembers == count
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushCondition.kt
index 1fc8329535..ec0936e4c8 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushCondition.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushCondition.kt
@@ -61,7 +61,7 @@ data class PushCondition(
fun asExecutableCondition(rule: PushRule): Condition? {
return when (Kind.fromString(kind)) {
- Kind.EventMatch -> {
+ Kind.EventMatch -> {
if (key != null && pattern != null) {
EventMatchCondition(key, pattern, rule.ruleId == RuleIds.RULE_ID_CONTAIN_USER_NAME)
} else {
@@ -69,10 +69,10 @@ data class PushCondition(
null
}
}
- Kind.ContainsDisplayName -> {
+ Kind.ContainsDisplayName -> {
ContainsDisplayNameCondition()
}
- Kind.RoomMemberCount -> {
+ Kind.RoomMemberCount -> {
if (iz.isNullOrEmpty()) {
Timber.e("Malformed ROOM_MEMBER_COUNT condition")
null
@@ -88,7 +88,7 @@ data class PushCondition(
SenderNotificationPermissionCondition(key)
}
}
- Kind.Unrecognised -> {
+ Kind.Unrecognised -> {
Timber.e("Unknown kind $kind")
null
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomDirectoryService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomDirectoryService.kt
index cb70603e66..77092c4811 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomDirectoryService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomDirectoryService.kt
@@ -28,8 +28,10 @@ interface RoomDirectoryService {
/**
* Get rooms from directory.
*/
- suspend fun getPublicRooms(server: String?,
- publicRoomsParams: PublicRoomsParams): PublicRoomsResponse
+ suspend fun getPublicRooms(
+ server: String?,
+ publicRoomsParams: PublicRoomsParams
+ ): PublicRoomsResponse
/**
* Get the visibility of a room in the directory.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomExtensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomExtensions.kt
index 0e631427bd..b30c60554f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomExtensions.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomExtensions.kt
@@ -16,18 +16,21 @@
package org.matrix.android.sdk.api.session.room
-import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
/**
* Get a TimelineEvent using the TimelineService of a Room.
+ * @param eventId The id of the event to retrieve
*/
fun Room.getTimelineEvent(eventId: String): TimelineEvent? =
timelineService().getTimelineEvent(eventId)
/**
* Get a StateEvent using the StateService of a Room.
+ * @param eventType The type of the event, see [org.matrix.android.sdk.api.session.events.model.EventType].
+ * @param stateKey the query which will be done on the stateKey.
*/
-fun Room.getStateEvent(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): Event? =
+fun Room.getStateEvent(eventType: String, stateKey: QueryStateEventValue): Event? =
stateService().getStateEvent(eventType, stateKey)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt
index 1e022ef02a..5dfb8961e3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt
@@ -60,9 +60,11 @@ interface RoomService {
* @param reason optional reason for joining the room
* @param viaServers the servers to attempt to join the room through. One of the servers must be participating in the room.
*/
- suspend fun joinRoom(roomIdOrAlias: String,
- reason: String? = null,
- viaServers: List = emptyList())
+ suspend fun joinRoom(
+ roomIdOrAlias: String,
+ reason: String? = null,
+ viaServers: List = emptyList()
+ )
/**
* @param roomId the roomId of the room to join
@@ -107,15 +109,19 @@ interface RoomService {
* Get a snapshot list of room summaries.
* @return the immutable list of [RoomSummary]
*/
- fun getRoomSummaries(queryParams: RoomSummaryQueryParams,
- sortOrder: RoomSortOrder = RoomSortOrder.NONE): List
+ fun getRoomSummaries(
+ queryParams: RoomSummaryQueryParams,
+ sortOrder: RoomSortOrder = RoomSortOrder.NONE
+ ): List
/**
* Get a live list of room summaries. This list is refreshed as soon as the data changes.
* @return the [LiveData] of List[RoomSummary]
*/
- fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
- sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): LiveData>
+ fun getRoomSummariesLive(
+ queryParams: RoomSummaryQueryParams,
+ sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY
+ ): LiveData>
/**
* Get a snapshot list of Breadcrumbs.
@@ -145,8 +151,10 @@ interface RoomService {
/**
* Resolve a room alias to a room ID.
*/
- suspend fun getRoomIdByAlias(roomAlias: String,
- searchOnServer: Boolean): Optional
+ suspend fun getRoomIdByAlias(
+ roomAlias: String,
+ searchOnServer: Boolean
+ ): Optional
/**
* Delete a room alias.
@@ -211,9 +219,11 @@ interface RoomService {
/**
* TODO Doc.
*/
- fun getPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams,
- pagedListConfig: PagedList.Config = defaultPagedListConfig,
- sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): LiveData>
+ fun getPagedRoomSummariesLive(
+ queryParams: RoomSummaryQueryParams,
+ pagedListConfig: PagedList.Config = defaultPagedListConfig,
+ sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY
+ ): LiveData>
/**
* Get's a live paged list from a filter that can be dynamically updated.
@@ -255,8 +265,10 @@ interface RoomService {
/**
* Returns all the children of this space, as LiveData.
*/
- fun getFlattenRoomSummaryChildrenOfLive(spaceId: String?,
- memberships: List = Membership.activeMemberships()): LiveData>
+ fun getFlattenRoomSummaryChildrenOfLive(
+ spaceId: String?,
+ memberships: List = Membership.activeMemberships()
+ ): LiveData>
/**
* Refreshes the RoomSummary LatestPreviewContent for the given @param roomId.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt
index dd48d51f45..ada3dc85d7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt
@@ -16,12 +16,58 @@
package org.matrix.android.sdk.api.session.room.location
+import androidx.annotation.MainThread
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary
+import org.matrix.android.sdk.api.util.Cancelable
+import org.matrix.android.sdk.api.util.Optional
/**
* Manage all location sharing related features.
*/
interface LocationSharingService {
+ /**
+ * Send a static location event to the room.
+ * @param latitude required latitude of the location
+ * @param longitude required longitude of the location
+ * @param uncertainty Accuracy of the location in meters
+ * @param isUserLocation indicates whether the location data corresponds to the user location or not (pinned location)
+ */
+ suspend fun sendStaticLocation(latitude: Double, longitude: Double, uncertainty: Double?, isUserLocation: Boolean): Cancelable
+
+ /**
+ * Send a live location event to the room.
+ * To get the beacon info event id, [startLiveLocationShare] must be called before sending live location updates.
+ * @param beaconInfoEventId event id of the initial beacon info state event
+ * @param latitude required latitude of the location
+ * @param longitude required longitude of the location
+ * @param uncertainty Accuracy of the location in meters
+ */
+ suspend fun sendLiveLocation(beaconInfoEventId: String, latitude: Double, longitude: Double, uncertainty: Double?): Cancelable
+
+ /**
+ * Starts sharing live location in the room.
+ * @param timeoutMillis timeout of the live in milliseconds
+ * @return the result of the update of the live
+ */
+ suspend fun startLiveLocationShare(timeoutMillis: Long): UpdateLiveLocationShareResult
+
+ /**
+ * Stops sharing live location in the room.
+ * @return the result of the update of the live
+ */
+ suspend fun stopLiveLocationShare(): UpdateLiveLocationShareResult
+
+ /**
+ * Returns a LiveData on the list of current running live location shares.
+ */
+ @MainThread
fun getRunningLiveLocationShareSummaries(): LiveData>
+
+ /**
+ * Returns a LiveData on the live location share summary with the given eventId.
+ * @param beaconInfoEventId event id of the initial beacon info state event
+ */
+ @MainThread
+ fun getLiveLocationShareSummary(beaconInfoEventId: String): LiveData>
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/UpdateLiveLocationShareResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/UpdateLiveLocationShareResult.kt
new file mode 100644
index 0000000000..6f8c03be46
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/UpdateLiveLocationShareResult.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.api.session.room.location
+
+/**
+ * Represents the result of an update of live location share like a start or a stop.
+ */
+sealed interface UpdateLiveLocationShareResult {
+ data class Success(val beaconEventId: String) : UpdateLiveLocationShareResult
+ data class Failure(val error: Throwable) : UpdateLiveLocationShareResult
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt
index 8ef94b2896..0329828130 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt
@@ -95,8 +95,8 @@ data class PowerLevelsContent(
// the first implementation was a string value
is String -> value.toInt()
is Double -> value.toInt()
- is Int -> value
- else -> Role.Moderator.value
+ is Int -> value
+ else -> Role.Moderator.value
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt
index ba274325bc..7dd853d75d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt
@@ -30,9 +30,9 @@ data class RoomGuestAccessContent(
@Json(name = "guest_access") val guestAccessStr: String? = null
) {
val guestAccess: GuestAccess? = when (guestAccessStr) {
- "can_join" -> GuestAccess.CanJoin
+ "can_join" -> GuestAccess.CanJoin
"forbidden" -> GuestAccess.Forbidden
- else -> {
+ else -> {
Timber.w("Invalid value for GuestAccess: `$guestAccessStr`")
null
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt
index da5c90ff05..39b4722c0c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt
@@ -26,10 +26,10 @@ data class RoomHistoryVisibilityContent(
) {
val historyVisibility: RoomHistoryVisibility? = when (historyVisibilityStr) {
"world_readable" -> RoomHistoryVisibility.WORLD_READABLE
- "shared" -> RoomHistoryVisibility.SHARED
- "invited" -> RoomHistoryVisibility.INVITED
- "joined" -> RoomHistoryVisibility.JOINED
- else -> {
+ "shared" -> RoomHistoryVisibility.SHARED
+ "invited" -> RoomHistoryVisibility.INVITED
+ "joined" -> RoomHistoryVisibility.JOINED
+ else -> {
Timber.w("Invalid value for RoomHistoryVisibility: `$historyVisibilityStr`")
null
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt
index 3b338a36cd..dbe21b1633 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt
@@ -36,12 +36,12 @@ data class RoomJoinRulesContent(
@Json(name = "allow") val allowList: List? = null
) {
val joinRules: RoomJoinRules? = when (joinRulesStr) {
- "public" -> RoomJoinRules.PUBLIC
- "invite" -> RoomJoinRules.INVITE
- "knock" -> RoomJoinRules.KNOCK
- "private" -> RoomJoinRules.PRIVATE
+ "public" -> RoomJoinRules.PUBLIC
+ "invite" -> RoomJoinRules.INVITE
+ "knock" -> RoomJoinRules.KNOCK
+ "private" -> RoomJoinRules.PRIVATE
"restricted" -> RoomJoinRules.RESTRICTED
- else -> {
+ else -> {
Timber.w("Invalid value for RoomJoinRules: `$joinRulesStr`")
null
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt
index a1fd3bd2ec..e0a7846167 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt
@@ -22,7 +22,7 @@ import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class LocationInfo(
/**
- * Required. RFC5870 formatted geo uri 'geo:latitude,longitude;uncertainty' like 'geo:40.05,29.24;30' representing this location.
+ * Required. RFC5870 formatted geo uri 'geo:latitude,longitude;u=uncertainty' like 'geo:40.05,29.24;u=30' representing this location.
*/
@Json(name = "uri") val geoUri: String? = null,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt
index 0a66a6e400..30420fd3c7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt
@@ -35,7 +35,7 @@ data class MessageLocationContent(
@Json(name = "body") override val body: String,
/**
- * Required. RFC5870 formatted geo uri 'geo:latitude,longitude;uncertainty' like 'geo:40.05,29.24;30' representing this location.
+ * Required. RFC5870 formatted geo uri 'geo:latitude,longitude;u=uncertainty' like 'geo:40.05,29.24;u=30' representing this location.
*/
@Json(name = "geo_uri") val geoUri: String,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationAcceptContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationAcceptContent.kt
index 27619cf0a9..33f61648dc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationAcceptContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationAcceptContent.kt
@@ -40,12 +40,14 @@ internal data class MessageVerificationAcceptContent(
companion object : VerificationInfoAcceptFactory {
- override fun create(tid: String,
- keyAgreementProtocol: String,
- hash: String,
- commitment: String,
- messageAuthenticationCode: String,
- shortAuthenticationStrings: List): VerificationInfoAccept {
+ override fun create(
+ tid: String,
+ keyAgreementProtocol: String,
+ hash: String,
+ commitment: String,
+ messageAuthenticationCode: String,
+ shortAuthenticationStrings: List
+ ): VerificationInfoAccept {
return MessageVerificationAcceptContent(
hash,
keyAgreementProtocol,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/PollCreationInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/PollCreationInfo.kt
index 81b034a809..ee31d5959e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/PollCreationInfo.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/PollCreationInfo.kt
@@ -25,4 +25,7 @@ data class PollCreationInfo(
@Json(name = "kind") val kind: PollType? = PollType.DISCLOSED_UNSTABLE,
@Json(name = "max_selections") val maxSelections: Int = 1,
@Json(name = "answers") val answers: List? = null
-)
+) {
+
+ fun isUndisclosed() = kind in listOf(PollType.UNDISCLOSED_UNSTABLE, PollType.UNDISCLOSED)
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationService.kt
index 02c597ee63..d34ea3c7d3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationService.kt
@@ -58,16 +58,20 @@ interface RelationService {
* @param targetEventId the id of the event being reacted
* @param reaction the reaction (preferably emoji)
*/
- fun sendReaction(targetEventId: String,
- reaction: String): Cancelable
+ fun sendReaction(
+ targetEventId: String,
+ reaction: String
+ ): Cancelable
/**
* Undo a reaction (emoji) to the targetedEvent.
* @param targetEventId the id of the event being reacted
* @param reaction the reaction (preferably emoji)
*/
- suspend fun undoReaction(targetEventId: String,
- reaction: String): Cancelable
+ suspend fun undoReaction(
+ targetEventId: String,
+ reaction: String
+ ): Cancelable
/**
* Edit a poll.
@@ -76,10 +80,12 @@ interface RelationService {
* @param question The edited question
* @param options The edited options
*/
- fun editPoll(targetEvent: TimelineEvent,
- pollType: PollType,
- question: String,
- options: List): Cancelable
+ fun editPoll(
+ targetEvent: TimelineEvent,
+ pollType: PollType,
+ question: String,
+ options: List
+ ): Cancelable
/**
* Edit a text message body. Limited to "m.text" contentType.
@@ -89,11 +95,13 @@ interface RelationService {
* @param newBodyAutoMarkdown true to parse markdown on the new body
* @param compatibilityBodyText The text that will appear on clients that don't support yet edition
*/
- fun editTextMessage(targetEvent: TimelineEvent,
- msgType: String,
- newBodyText: CharSequence,
- newBodyAutoMarkdown: Boolean,
- compatibilityBodyText: String = "* $newBodyText"): Cancelable
+ fun editTextMessage(
+ targetEvent: TimelineEvent,
+ msgType: String,
+ newBodyText: CharSequence,
+ newBodyAutoMarkdown: Boolean,
+ compatibilityBodyText: String = "* $newBodyText"
+ ): Cancelable
/**
* Edit a reply. This is a special case because replies contains fallback text as a prefix.
@@ -103,10 +111,12 @@ interface RelationService {
* @param newBodyText The edited body (stripped from in reply to content)
* @param compatibilityBodyText The text that will appear on clients that don't support yet edition
*/
- fun editReply(replyToEdit: TimelineEvent,
- originalTimelineEvent: TimelineEvent,
- newBodyText: String,
- compatibilityBodyText: String = "* $newBodyText"): Cancelable
+ fun editReply(
+ replyToEdit: TimelineEvent,
+ originalTimelineEvent: TimelineEvent,
+ newBodyText: String,
+ compatibilityBodyText: String = "* $newBodyText"
+ ): Cancelable
/**
* Get the edit history of the given event.
@@ -127,11 +137,12 @@ interface RelationService {
* @param showInThread If true, relation will be added to the reply in order to be visible from within threads
* @param rootThreadEventId If show in thread is true then we need the rootThreadEventId to generate the relation
*/
- fun replyToMessage(eventReplied: TimelineEvent,
- replyText: CharSequence,
- autoMarkdown: Boolean = false,
- showInThread: Boolean = false,
- rootThreadEventId: String? = null
+ fun replyToMessage(
+ eventReplied: TimelineEvent,
+ replyText: CharSequence,
+ autoMarkdown: Boolean = false,
+ showInThread: Boolean = false,
+ rootThreadEventId: String? = null
): Cancelable?
/**
@@ -159,10 +170,12 @@ interface RelationService {
* @param formattedText The formatted body using MessageType#FORMAT_MATRIX_HTML
* @param eventReplied the event referenced by the reply within a thread
*/
- fun replyInThread(rootThreadEventId: String,
- replyInThreadText: CharSequence,
- msgType: String = MessageType.MSGTYPE_TEXT,
- autoMarkdown: Boolean = false,
- formattedText: String? = null,
- eventReplied: TimelineEvent? = null): Cancelable?
+ fun replyInThread(
+ rootThreadEventId: String,
+ replyInThreadText: CharSequence,
+ msgType: String = MessageType.MSGTYPE_TEXT,
+ autoMarkdown: Boolean = false,
+ formattedText: String? = null,
+ eventReplied: TimelineEvent? = null
+ ): Cancelable?
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/Role.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/Role.kt
index 5fe9bf6993..c5cc573458 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/Role.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/Role.kt
@@ -32,11 +32,11 @@ sealed class Role(open val value: Int) : Comparable {
// Order matters, default value should be checked after defined roles
fun fromValue(value: Int, default: Int): Role {
return when (value) {
- Admin.value -> Admin
+ Admin.value -> Admin
Moderator.value -> Moderator
Default.value,
- default -> Default
- else -> Custom(value)
+ default -> Default
+ else -> Custom(value)
}
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt
index c2e3ded2fa..9cf062356f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt
@@ -76,10 +76,12 @@ interface SendService {
* @param rootThreadEventId when this param is not null, the Media will be sent in this specific thread
* @return a [Cancelable]
*/
- fun sendMedia(attachment: ContentAttachmentData,
- compressBeforeSending: Boolean,
- roomIds: Set,
- rootThreadEventId: String? = null): Cancelable
+ fun sendMedia(
+ attachment: ContentAttachmentData,
+ compressBeforeSending: Boolean,
+ roomIds: Set,
+ rootThreadEventId: String? = null
+ ): Cancelable
/**
* Method to send a list of media asynchronously.
@@ -90,10 +92,12 @@ interface SendService {
* @param rootThreadEventId when this param is not null, all the Media will be sent in this specific thread
* @return a [Cancelable]
*/
- fun sendMedias(attachments: List,
- compressBeforeSending: Boolean,
- roomIds: Set,
- rootThreadEventId: String? = null): Cancelable
+ fun sendMedias(
+ attachments: List,
+ compressBeforeSending: Boolean,
+ roomIds: Set,
+ rootThreadEventId: String? = null
+ ): Cancelable
/**
* Send a poll to the room.
@@ -138,24 +142,6 @@ interface SendService {
*/
fun resendMediaMessage(localEcho: TimelineEvent): Cancelable
- /**
- * Send a location event to the room.
- * @param latitude required latitude of the location
- * @param longitude required longitude of the location
- * @param uncertainty Accuracy of the location in meters
- * @param isUserLocation indicates whether the location data corresponds to the user location or not
- */
- fun sendLocation(latitude: Double, longitude: Double, uncertainty: Double?, isUserLocation: Boolean): Cancelable
-
- /**
- * Send a live location event to the room. beacon_info state event has to be sent before sending live location updates.
- * @param beaconInfoEventId event id of the initial beacon info state event
- * @param latitude required latitude of the location
- * @param longitude required longitude of the location
- * @param uncertainty Accuracy of the location in meters
- */
- fun sendLiveLocation(beaconInfoEventId: String, latitude: Double, longitude: Double, uncertainty: Double?): Cancelable
-
/**
* Remove this failed message from the timeline.
* @param localEcho the unsent local echo
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/UserDraft.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/UserDraft.kt
index 4ede1a66fc..e16405b3c0 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/UserDraft.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/UserDraft.kt
@@ -33,7 +33,7 @@ sealed interface UserDraft {
fun isValid(): Boolean {
return when (this) {
is Regular -> content.isNotBlank()
- else -> true
+ else -> true
}
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/sender/SenderInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/sender/SenderInfo.kt
index 4c308c355a..d629df8b16 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/sender/SenderInfo.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/sender/SenderInfo.kt
@@ -29,9 +29,9 @@ data class SenderInfo(
) {
val disambiguatedDisplayName: String
get() = when {
- displayName == null -> userId
+ displayName == null -> userId
displayName.replaceSpaceChars().isBlank() -> "$displayName ($userId)"
- isUniqueDisplayName -> displayName
- else -> "$displayName ($userId)"
+ isUniqueDisplayName -> displayName
+ else -> "$displayName ($userId)"
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt
index c79171f156..6ca63c2c49 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt
@@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.session.room.state
import android.net.Uri
import androidx.lifecycle.LiveData
-import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.model.GuestAccess
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
@@ -66,19 +66,6 @@ interface StateService {
*/
suspend fun deleteAvatar()
- /**
- * Stops sharing live location in the room.
- * @param userId user id
- */
- suspend fun stopLiveLocation(userId: String)
-
- /**
- * Returns beacon info state event of a user.
- * @param userId user id who is sharing location
- * @param filterOnlyLive filters only ongoing live location sharing beacons if true else ended event is included
- */
- suspend fun getLiveLocationBeaconInfo(userId: String, filterOnlyLive: Boolean): Event?
-
/**
* Send a state event to the room.
* @param eventType The type of event to send.
@@ -93,28 +80,28 @@ interface StateService {
* @param eventType An eventType.
* @param stateKey the query which will be done on the stateKey
*/
- fun getStateEvent(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): Event?
+ fun getStateEvent(eventType: String, stateKey: QueryStateEventValue): Event?
/**
* Get a live state event of the room.
* @param eventType An eventType.
* @param stateKey the query which will be done on the stateKey
*/
- fun getStateEventLive(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): LiveData>
+ fun getStateEventLive(eventType: String, stateKey: QueryStateEventValue): LiveData>
/**
* Get state events of the room.
* @param eventTypes Set of eventType. If empty, all state events will be returned
* @param stateKey the query which will be done on the stateKey
*/
- fun getStateEvents(eventTypes: Set, stateKey: QueryStringValue = QueryStringValue.NoCondition): List
+ fun getStateEvents(eventTypes: Set, stateKey: QueryStateEventValue): List
/**
* Get live state events of the room.
* @param eventTypes Set of eventType to observe. If empty, all state events will be observed
* @param stateKey the query which will be done on the stateKey
*/
- fun getStateEventsLive(eventTypes: Set, stateKey: QueryStringValue = QueryStringValue.NoCondition): LiveData>
+ fun getStateEventsLive(eventTypes: Set, stateKey: QueryStateEventValue): LiveData>
suspend fun setJoinRulePublic()
suspend fun setJoinRuleInviteOnly()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateServiceExtension.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateServiceExtension.kt
index 9e45fc126d..6a9506fd9e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateServiceExtension.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateServiceExtension.kt
@@ -26,7 +26,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
* Return true if a room can be joined by anyone (RoomJoinRules.PUBLIC).
*/
fun StateService.isPublic(): Boolean {
- return getStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.NoCondition)
+ return getStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.IsEmpty)
?.content
?.toModel()
?.joinRules == RoomJoinRules.PUBLIC
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadEditions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadEditions.kt
index c8353cf0de..dc9cc886e9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadEditions.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadEditions.kt
@@ -16,5 +16,7 @@
package org.matrix.android.sdk.api.session.room.threads.model
-data class ThreadEditions(var rootThreadEdition: String? = null,
- var latestThreadEdition: String? = null)
+data class ThreadEditions(
+ var rootThreadEdition: String? = null,
+ var latestThreadEdition: String? = null
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadSummary.kt
index 1ef972e889..0b1aea1966 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadSummary.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadSummary.kt
@@ -22,12 +22,14 @@ import org.matrix.android.sdk.api.session.room.sender.SenderInfo
/**
* The main thread Summary model, mainly used to display the thread list.
*/
-data class ThreadSummary(val roomId: String,
- val rootEvent: Event?,
- val latestEvent: Event?,
- val rootEventId: String,
- val rootThreadSenderInfo: SenderInfo,
- val latestThreadSenderInfo: SenderInfo,
- val isUserParticipating: Boolean,
- val numberOfThreads: Int,
- val threadEditions: ThreadEditions = ThreadEditions())
+data class ThreadSummary(
+ val roomId: String,
+ val rootEvent: Event?,
+ val latestEvent: Event?,
+ val rootEventId: String,
+ val rootThreadSenderInfo: SenderInfo,
+ val latestThreadSenderInfo: SenderInfo,
+ val isUserParticipating: Boolean,
+ val numberOfThreads: Int,
+ val threadEditions: ThreadEditions = ThreadEditions()
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt
index d4ade9b5b9..9d8c8a13bd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt
@@ -139,11 +139,11 @@ fun TimelineEvent.getEditedEventId(): String? {
*/
fun TimelineEvent.getLastMessageContent(): MessageContent? {
return when (root.getClearType()) {
- EventType.STICKER -> root.getClearContent().toModel()
- in EventType.POLL_START -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel()
+ EventType.STICKER -> root.getClearContent().toModel()
+ in EventType.POLL_START -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel()
in EventType.STATE_ROOM_BEACON_INFO -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel()
- in EventType.BEACON_LOCATION_DATA -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel()
- else -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel()
+ in EventType.BEACON_LOCATION_DATA -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel()
+ else -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel()
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/search/SearchService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/search/SearchService.kt
index bc1c9e5769..ffb8b1ca4d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/search/SearchService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/search/SearchService.kt
@@ -33,12 +33,14 @@ interface SearchService {
* @param afterLimit how many events after the result are returned.
* @param includeProfile requests that the server returns the historic profile information for the users that sent the events that were returned.
*/
- suspend fun search(searchTerm: String,
- roomId: String,
- nextBatch: String?,
- orderByRecent: Boolean,
- limit: Int,
- beforeLimit: Int,
- afterLimit: Int,
- includeProfile: Boolean): SearchResult
+ suspend fun search(
+ searchTerm: String,
+ roomId: String,
+ nextBatch: String?,
+ orderByRecent: Boolean,
+ limit: Int,
+ beforeLimit: Int,
+ afterLimit: Int,
+ includeProfile: Boolean
+ ): SearchResult
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt
index 929463563f..bdbbd3ea84 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt
@@ -44,10 +44,12 @@ interface SharedSecretStorageService {
*
* @return key creation info
*/
- suspend fun generateKey(keyId: String,
- key: SsssKeySpec?,
- keyName: String,
- keySigner: KeySigner?): SsssKeyCreationInfo
+ suspend fun generateKey(
+ keyId: String,
+ key: SsssKeySpec?,
+ keyName: String,
+ keySigner: KeySigner?
+ ): SsssKeyCreationInfo
/**
* Generates a SSSS key using the given passphrase.
@@ -61,11 +63,13 @@ interface SharedSecretStorageService {
*
* @return key creation info
*/
- suspend fun generateKeyWithPassphrase(keyId: String,
- keyName: String,
- passphrase: String,
- keySigner: KeySigner,
- progressListener: ProgressListener?): SsssKeyCreationInfo
+ suspend fun generateKeyWithPassphrase(
+ keyId: String,
+ keyName: String,
+ passphrase: String,
+ keySigner: KeySigner,
+ progressListener: ProgressListener?
+ ): SsssKeyCreationInfo
fun getKey(keyId: String): KeyInfoResult
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/Space.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/Space.kt
index c990388628..61c03e08fc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/Space.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/Space.kt
@@ -31,11 +31,13 @@ interface Space {
*/
fun spaceSummary(): RoomSummary?
- suspend fun addChildren(roomId: String,
- viaServers: List?,
- order: String?,
+ suspend fun addChildren(
+ roomId: String,
+ viaServers: List?,
+ order: String?,
// autoJoin: Boolean = false,
- suggested: Boolean? = false)
+ suggested: Boolean? = false
+ )
fun getChildInfo(roomId: String): SpaceChildContent?
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt
index 38e55664d2..c7a6405014 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt
@@ -37,11 +37,13 @@ interface SpaceService {
/**
* Just a shortcut for space creation for ease of use.
*/
- suspend fun createSpace(name: String,
- topic: String?,
- avatarUri: Uri?,
- isPublic: Boolean,
- roomAliasLocalPart: String? = null): String
+ suspend fun createSpace(
+ name: String,
+ topic: String?,
+ avatarUri: Uri?,
+ isPublic: Boolean,
+ roomAliasLocalPart: String? = null
+ ): String
/**
* Get a space from a spaceId.
@@ -68,25 +70,33 @@ interface SpaceService {
* then the parameters given for suggested_only and max_depth must be the same.
* @param knownStateList when paginating, pass back the m.space.child state events
*/
- suspend fun querySpaceChildren(spaceId: String,
- suggestedOnly: Boolean? = null,
- limit: Int? = null,
- from: String? = null,
- knownStateList: List? = null): SpaceHierarchyData
+ suspend fun querySpaceChildren(
+ spaceId: String,
+ suggestedOnly: Boolean? = null,
+ limit: Int? = null,
+ from: String? = null,
+ knownStateList: List? = null
+ ): SpaceHierarchyData
/**
* Get a live list of space summaries. This list is refreshed as soon as the data changes.
* @return the [LiveData] of List[SpaceSummary]
*/
- fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
- sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData>
+ fun getSpaceSummariesLive(
+ queryParams: SpaceSummaryQueryParams,
+ sortOrder: RoomSortOrder = RoomSortOrder.NONE
+ ): LiveData>
- fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
- sortOrder: RoomSortOrder = RoomSortOrder.NONE): List
+ fun getSpaceSummaries(
+ spaceSummaryQueryParams: SpaceSummaryQueryParams,
+ sortOrder: RoomSortOrder = RoomSortOrder.NONE
+ ): List
- suspend fun joinSpace(spaceIdOrAlias: String,
- reason: String? = null,
- viaServers: List = emptyList()): JoinSpaceResult
+ suspend fun joinSpace(
+ spaceIdOrAlias: String,
+ reason: String? = null,
+ viaServers: List = emptyList()
+ ): JoinSpaceResult
suspend fun rejectInvite(spaceId: String, reason: String?)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/statistics/StatisticEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/statistics/StatisticEvent.kt
index 76755517ce..d9c7772393 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/statistics/StatisticEvent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/statistics/StatisticEvent.kt
@@ -23,15 +23,19 @@ sealed interface StatisticEvent {
/**
* Initial sync request, response downloading, and treatment (parsing and storage) of response.
*/
- data class InitialSyncRequest(val requestDurationMs: Int,
- val downloadDurationMs: Int,
- val treatmentDurationMs: Int,
- val nbOfJoinedRooms: Int) : StatisticEvent
+ data class InitialSyncRequest(
+ val requestDurationMs: Int,
+ val downloadDurationMs: Int,
+ val treatmentDurationMs: Int,
+ val nbOfJoinedRooms: Int
+ ) : StatisticEvent
/**
* Incremental sync event.
*/
- data class SyncTreatment(val durationMs: Int,
- val afterPause: Boolean,
- val nbOfJoinedRooms: Int) : StatisticEvent
+ data class SyncTreatment(
+ val durationMs: Int,
+ val afterPause: Boolean,
+ val nbOfJoinedRooms: Int
+ ) : StatisticEvent
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/InitSyncStep.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStep.kt
similarity index 91%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/InitSyncStep.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStep.kt
index 901c1b2ffb..407585b003 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/InitSyncStep.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStep.kt
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package org.matrix.android.sdk.api.session.initsync
+package org.matrix.android.sdk.api.session.sync
-enum class InitSyncStep {
+enum class InitialSyncStep {
ServerComputing,
Downloading,
ImportingAccount,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncRequestState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncRequestState.kt
new file mode 100644
index 0000000000..4e932d49de
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncRequestState.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.api.session.sync
+
+sealed interface SyncRequestState {
+ /**
+ * For initial sync.
+ */
+ interface InitialSyncRequestState : SyncRequestState
+
+ object Idle : InitialSyncRequestState
+ data class InitialSyncProgressing(
+ val initialSyncStep: InitialSyncStep,
+ val percentProgress: Int = 0
+ ) : InitialSyncRequestState
+
+ /**
+ * For incremental sync.
+ */
+ interface IncrementalSyncRequestState : SyncRequestState
+
+ object IncrementalSyncIdle : IncrementalSyncRequestState
+ data class IncrementalSyncParsing(
+ val rooms: Int,
+ val toDevice: Int
+ ) : IncrementalSyncRequestState
+
+ object IncrementalSyncError : IncrementalSyncRequestState
+ object IncrementalSyncDone : IncrementalSyncRequestState
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt
new file mode 100644
index 0000000000..5b2bf651af
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2022 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.api.session.sync
+
+import androidx.lifecycle.LiveData
+import kotlinx.coroutines.flow.SharedFlow
+import org.matrix.android.sdk.api.session.sync.model.SyncResponse
+
+interface SyncService {
+ /**
+ * This method start the sync thread.
+ */
+ fun startSync(fromForeground: Boolean)
+
+ /**
+ * This method stop the sync thread.
+ */
+ fun stopSync()
+
+ /**
+ * Requires a one time background sync.
+ */
+ fun requireBackgroundSync()
+
+ /**
+ * Launches infinite self rescheduling background syncs via the WorkManager.
+ *
+ * While dozing, syncs will only occur during maintenance windows.
+ * For reliability it's recommended to also start a long running foreground service
+ * along with disabling battery optimizations.
+ */
+ fun startAutomaticBackgroundSync(timeOutInSeconds: Long, repeatDelayInSeconds: Long)
+
+ fun stopAnyBackgroundSync()
+
+ /**
+ * This method returns the current sync state.
+ * @return the current [SyncState].
+ */
+ fun getSyncState(): SyncState
+
+ /**
+ * This method allows to listen the sync state.
+ * @return a [LiveData] of [SyncState].
+ */
+ fun getSyncStateLive(): LiveData
+
+ /**
+ * Get the [SyncRequestState] as a LiveData.
+ */
+ fun getSyncRequestStateLive(): LiveData
+
+ /**
+ * This method returns a flow of SyncResponse. New value will be pushed through the sync thread.
+ */
+ fun syncFlow(): SharedFlow
+
+ /**
+ * This methods return true if an initial sync has been processed.
+ */
+ fun hasAlreadySynced(): Boolean
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/job/SyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/job/SyncAndroidService.kt
similarity index 97%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/job/SyncService.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/job/SyncAndroidService.kt
index ac81be2174..8dee633b9c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/job/SyncService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/job/SyncAndroidService.kt
@@ -46,7 +46,7 @@ import java.util.concurrent.atomic.AtomicBoolean
* in order to be able to perform a sync even if the app is not running.
* The and must be declared in the Manifest or the app using the SDK
*/
-abstract class SyncService : Service() {
+abstract class SyncAndroidService : Service() {
private var sessionId: String? = null
private var mIsSelfDestroyed: Boolean = false
@@ -84,7 +84,7 @@ abstract class SyncService : Service() {
stopMe()
}
}
- else -> {
+ else -> {
val isInit = initialize(intent)
onStart(isInitialSync)
if (isInit) {
@@ -158,9 +158,9 @@ abstract class SyncService : Service() {
// never do that in foreground, let the syncThread work
syncTask.execute(params)
// Start sync if we were doing an initial sync and the syncThread is not launched yet
- if (isInitialSync && session.getSyncState() == SyncState.Idle) {
+ if (isInitialSync && session.syncService().getSyncState() == SyncState.Idle) {
val isForeground = !backgroundDetectionObserver.isInBackground
- session.startSync(isForeground)
+ session.syncService().startSync(isForeground)
}
stopMe()
} catch (throwable: Throwable) {
@@ -210,7 +210,7 @@ abstract class SyncService : Service() {
session = sessionComponent.session()
sessionId = safeSessionId
syncTask = sessionComponent.syncTask()
- isInitialSync = !session.hasAlreadySynced()
+ isInitialSync = !session.syncService().hasAlreadySynced()
networkConnectivityChecker = sessionComponent.networkConnectivityChecker()
taskExecutor = sessionComponent.taskExecutor()
coroutineDispatchers = sessionComponent.coroutineDispatchers()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncUnreadNotifications.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncUnreadNotifications.kt
index 6618bceacd..09273f56e6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncUnreadNotifications.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncUnreadNotifications.kt
@@ -38,4 +38,5 @@ data class RoomSyncUnreadNotifications(
/**
* The number of highlighted unread messages (subset of notifications).
*/
- @Json(name = "highlight_count") val highlightCount: Int? = null)
+ @Json(name = "highlight_count") val highlightCount: Int? = null
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsResponse.kt
index 9a30b4d764..ae728326cc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsResponse.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsResponse.kt
@@ -30,8 +30,10 @@ data class TermsResponse(
val policies: JsonDict? = null
) {
- fun getLocalizedTerms(userLanguage: String,
- defaultLanguage: String = "en"): List {
+ fun getLocalizedTerms(
+ userLanguage: String,
+ defaultLanguage: String = "en"
+ ): List {
return policies?.map {
val tos = policies[it.key] as? Map<*, *> ?: return@map null
((tos[userLanguage] ?: tos[defaultLanguage]) as? Map<*, *>)?.let { termsMap ->
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt
index 6c357b2224..1ddce763d1 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt
@@ -24,10 +24,12 @@ interface TermsService {
suspend fun getTerms(serviceType: ServiceType, baseUrl: String): GetTermsResponse
- suspend fun agreeToTerms(serviceType: ServiceType,
- baseUrl: String,
- agreedUrls: List,
- token: String?)
+ suspend fun agreeToTerms(
+ serviceType: ServiceType,
+ baseUrl: String,
+ agreedUrls: List,
+ token: String?
+ )
/**
* Get the homeserver terms, from the register API.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetService.kt
index 8ad6500d25..c2094f46bd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetService.kt
@@ -17,7 +17,7 @@
package org.matrix.android.sdk.api.session.widgets
import androidx.lifecycle.LiveData
-import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.widgets.model.Widget
@@ -49,7 +49,7 @@ interface WidgetService {
*/
fun getRoomWidgets(
roomId: String,
- widgetId: QueryStringValue = QueryStringValue.NoCondition,
+ widgetId: QueryStateEventValue,
widgetTypes: Set? = null,
excludedTypes: Set? = null
): List
@@ -70,7 +70,7 @@ interface WidgetService {
*/
fun getRoomWidgetsLive(
roomId: String,
- widgetId: QueryStringValue = QueryStringValue.NoCondition,
+ widgetId: QueryStateEventValue,
widgetTypes: Set? = null,
excludedTypes: Set? = null
): LiveData>
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/BuildVersionSdkIntProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/BuildVersionSdkIntProvider.kt
similarity index 87%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/BuildVersionSdkIntProvider.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/BuildVersionSdkIntProvider.kt
index 515656049a..b7ea187ec5 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/BuildVersionSdkIntProvider.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/BuildVersionSdkIntProvider.kt
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package org.matrix.android.sdk.internal.util.system
+package org.matrix.android.sdk.api.util
-internal interface BuildVersionSdkIntProvider {
+interface BuildVersionSdkIntProvider {
/**
* Return the current version of the Android SDK.
*/
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/DefaultBuildVersionSdkIntProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/DefaultBuildVersionSdkIntProvider.kt
similarity index 85%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/DefaultBuildVersionSdkIntProvider.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/DefaultBuildVersionSdkIntProvider.kt
index 806c6e9735..7f0024cafa 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/DefaultBuildVersionSdkIntProvider.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/DefaultBuildVersionSdkIntProvider.kt
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package org.matrix.android.sdk.internal.util.system
+package org.matrix.android.sdk.api.util
import android.os.Build
import javax.inject.Inject
-internal class DefaultBuildVersionSdkIntProvider @Inject constructor() :
+class DefaultBuildVersionSdkIntProvider @Inject constructor() :
BuildVersionSdkIntProvider {
override fun get() = Build.VERSION.SDK_INT
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt
index c5cb40b43c..299f0c1b8b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt
@@ -33,9 +33,11 @@ sealed class MatrixItem(
open val displayName: String?,
open val avatarUrl: String?
) {
- data class UserItem(override val id: String,
- override val displayName: String? = null,
- override val avatarUrl: String? = null) :
+ data class UserItem(
+ override val id: String,
+ override val displayName: String? = null,
+ override val avatarUrl: String? = null
+ ) :
MatrixItem(id, displayName?.removeSuffix(IRC_PATTERN), avatarUrl) {
init {
@@ -45,10 +47,12 @@ sealed class MatrixItem(
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
}
- data class EveryoneInRoomItem(override val id: String,
- override val displayName: String = NOTIFY_EVERYONE,
- override val avatarUrl: String? = null,
- val roomDisplayName: String? = null) :
+ data class EveryoneInRoomItem(
+ override val id: String,
+ override val displayName: String = NOTIFY_EVERYONE,
+ override val avatarUrl: String? = null,
+ val roomDisplayName: String? = null
+ ) :
MatrixItem(id, displayName, avatarUrl) {
init {
if (BuildConfig.DEBUG) checkId()
@@ -57,9 +61,11 @@ sealed class MatrixItem(
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
}
- data class EventItem(override val id: String,
- override val displayName: String? = null,
- override val avatarUrl: String? = null) :
+ data class EventItem(
+ override val id: String,
+ override val displayName: String? = null,
+ override val avatarUrl: String? = null
+ ) :
MatrixItem(id, displayName, avatarUrl) {
init {
if (BuildConfig.DEBUG) checkId()
@@ -68,9 +74,11 @@ sealed class MatrixItem(
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
}
- data class RoomItem(override val id: String,
- override val displayName: String? = null,
- override val avatarUrl: String? = null) :
+ data class RoomItem(
+ override val id: String,
+ override val displayName: String? = null,
+ override val avatarUrl: String? = null
+ ) :
MatrixItem(id, displayName, avatarUrl) {
init {
if (BuildConfig.DEBUG) checkId()
@@ -79,9 +87,11 @@ sealed class MatrixItem(
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
}
- data class SpaceItem(override val id: String,
- override val displayName: String? = null,
- override val avatarUrl: String? = null) :
+ data class SpaceItem(
+ override val id: String,
+ override val displayName: String? = null,
+ override val avatarUrl: String? = null
+ ) :
MatrixItem(id, displayName, avatarUrl) {
init {
if (BuildConfig.DEBUG) checkId()
@@ -90,9 +100,11 @@ sealed class MatrixItem(
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
}
- data class RoomAliasItem(override val id: String,
- override val displayName: String? = null,
- override val avatarUrl: String? = null) :
+ data class RoomAliasItem(
+ override val id: String,
+ override val displayName: String? = null,
+ override val avatarUrl: String? = null
+ ) :
MatrixItem(id, displayName, avatarUrl) {
init {
if (BuildConfig.DEBUG) checkId()
@@ -101,9 +113,11 @@ sealed class MatrixItem(
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
}
- data class GroupItem(override val id: String,
- override val displayName: String? = null,
- override val avatarUrl: String? = null) :
+ data class GroupItem(
+ override val id: String,
+ override val displayName: String? = null,
+ override val avatarUrl: String? = null
+ ) :
MatrixItem(id, displayName, avatarUrl) {
init {
if (BuildConfig.DEBUG) checkId()
@@ -131,21 +145,21 @@ sealed class MatrixItem(
* Return the prefix as defined in the matrix spec (and not extracted from the id).
*/
private fun getIdPrefix() = when (this) {
- is UserItem -> '@'
- is EventItem -> '$'
+ is UserItem -> '@'
+ is EventItem -> '$'
is SpaceItem,
is RoomItem,
is EveryoneInRoomItem -> '!'
- is RoomAliasItem -> '#'
- is GroupItem -> '+'
- is EmoteItem -> 'm'
+ is RoomAliasItem -> '#'
+ is GroupItem -> '+'
+ is EmoteItem -> 'm'
}
fun firstLetterOfDisplayName(): String {
val displayName = when (this) {
// use the room display name for the notify everyone item
is EveryoneInRoomItem -> roomDisplayName
- else -> displayName
+ else -> displayName
}
return (displayName?.takeIf { it.isNotBlank() } ?: id)
.let { dn ->
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/SessionManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/SessionManager.kt
index 934d61de45..5f5bb1f951 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/SessionManager.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/SessionManager.kt
@@ -27,8 +27,10 @@ import org.matrix.android.sdk.internal.session.SessionComponent
import javax.inject.Inject
@MatrixScope
-internal class SessionManager @Inject constructor(private val matrixComponent: MatrixComponent,
- private val sessionParamsStore: SessionParamsStore) {
+internal class SessionManager @Inject constructor(
+ private val matrixComponent: MatrixComponent,
+ private val sessionParamsStore: SessionParamsStore
+) {
// SessionId -> SessionComponent
private val sessionComponents = HashMap()
@@ -38,6 +40,13 @@ internal class SessionManager @Inject constructor(private val matrixComponent: M
return getOrCreateSessionComponent(sessionParams)
}
+ fun getLastSession(): Session? {
+ val sessionParams = sessionParamsStore.getLast()
+ return sessionParams?.let {
+ getOrCreateSession(it)
+ }
+ }
+
fun getOrCreateSession(sessionParams: SessionParams): Session {
return getOrCreateSessionComponent(sessionParams).session()
}
@@ -53,7 +62,7 @@ internal class SessionManager @Inject constructor(private val matrixComponent: M
fun stopSession(sessionId: String) {
val sessionComponent = sessionComponents[sessionId] ?: throw RuntimeException("You don't have a session for id $sessionId")
- sessionComponent.session().stopSync()
+ sessionComponent.session().syncService().stopSync()
}
fun getOrCreateSessionComponent(sessionParams: SessionParams): SessionComponent {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt
index 46fa63334c..ea4502824e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt
@@ -98,15 +98,19 @@ internal interface AuthAPI {
* https://github.com/matrix-org/matrix-doc/pull/2290
*/
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "register/{threePid}/requestToken")
- suspend fun add3Pid(@Path("threePid") threePid: String,
- @Body params: AddThreePidRegistrationParams): AddThreePidRegistrationResponse
+ suspend fun add3Pid(
+ @Path("threePid") threePid: String,
+ @Body params: AddThreePidRegistrationParams
+ ): AddThreePidRegistrationResponse
/**
* Validate 3pid.
*/
@POST
- suspend fun validate3Pid(@Url url: String,
- @Body params: ValidationCodeBody): SuccessResult
+ suspend fun validate3Pid(
+ @Url url: String,
+ @Body params: ValidationCodeBody
+ ): SuccessResult
/**
* Get the supported login flow.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthModule.kt
index 298e116199..ddb70be906 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthModule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthModule.kt
@@ -46,9 +46,11 @@ internal abstract class AuthModule {
@JvmStatic
@Provides
@AuthDatabase
- fun providesRealmConfiguration(context: Context,
- realmKeysUtils: RealmKeysUtils,
- authRealmMigration: AuthRealmMigration): RealmConfiguration {
+ fun providesRealmConfiguration(
+ context: Context,
+ realmKeysUtils: RealmKeysUtils,
+ authRealmMigration: AuthRealmMigration
+ ): RealmConfiguration {
val old = File(context.filesDir, "matrix-sdk-auth")
if (old.exists()) {
old.renameTo(File(context.filesDir, "matrix-sdk-auth.realm"))
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt
index fe78ccc75a..9d6b018a67 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt
@@ -40,6 +40,7 @@ import org.matrix.android.sdk.internal.auth.login.DefaultLoginWizard
import org.matrix.android.sdk.internal.auth.login.DirectLoginTask
import org.matrix.android.sdk.internal.auth.registration.DefaultRegistrationWizard
import org.matrix.android.sdk.internal.auth.version.Versions
+import org.matrix.android.sdk.internal.auth.version.doesServerSupportLogoutDevices
import org.matrix.android.sdk.internal.auth.version.isLoginAndRegistrationSupportedBySdk
import org.matrix.android.sdk.internal.auth.version.isSupportedBySdk
import org.matrix.android.sdk.internal.di.Unauthenticated
@@ -73,10 +74,7 @@ internal class DefaultAuthenticationService @Inject constructor(
}
override fun getLastAuthenticatedSession(): Session? {
- val sessionParams = sessionParamsStore.getLast()
- return sessionParams?.let {
- sessionManager.getOrCreateSession(it)
- }
+ return sessionManager.getLastSession()
}
override suspend fun getLoginFlowOfSession(sessionId: String): LoginFlowResult {
@@ -130,16 +128,7 @@ internal class DefaultAuthenticationService @Inject constructor(
?.trim { it == '/' }
}
- /**
- * This is the entry point of the authentication service.
- * homeServerConnectionConfig contains a homeserver URL probably entered by the user, which can be a
- * valid homeserver API url, the url of Element Web, or anything else.
- */
override suspend fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult {
- pendingSessionData = null
-
- pendingSessionStore.delete()
-
val result = runCatching {
getLoginFlowInternal(homeServerConnectionConfig)
}
@@ -290,7 +279,7 @@ internal class DefaultAuthenticationService @Inject constructor(
getLoginFlowResult(newAuthAPI, versions, wellknownResult.homeServerUrl)
}
- else -> throw Failure.OtherServerError("", HttpsURLConnection.HTTP_NOT_FOUND /* 404 */)
+ else -> throw Failure.OtherServerError("", HttpsURLConnection.HTTP_NOT_FOUND /* 404 */)
}
}
@@ -304,7 +293,8 @@ internal class DefaultAuthenticationService @Inject constructor(
ssoIdentityProviders = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == LoginFlowTypes.SSO }?.ssoIdentityProvider,
isLoginAndRegistrationSupported = versions.isLoginAndRegistrationSupportedBySdk(),
homeServerUrl = homeServerUrl,
- isOutdatedHomeserver = !versions.isSupportedBySdk()
+ isOutdatedHomeserver = !versions.isSupportedBySdk(),
+ isLogoutDevicesSupported = versions.doesServerSupportLogoutDevices()
)
}
@@ -367,13 +357,17 @@ internal class DefaultAuthenticationService @Inject constructor(
pendingSessionStore.delete()
}
- override suspend fun createSessionFromSso(homeServerConnectionConfig: HomeServerConnectionConfig,
- credentials: Credentials): Session {
+ override suspend fun createSessionFromSso(
+ homeServerConnectionConfig: HomeServerConnectionConfig,
+ credentials: Credentials
+ ): Session {
return sessionCreator.createSession(credentials, homeServerConnectionConfig)
}
- override suspend fun getWellKnownData(matrixId: String,
- homeServerConnectionConfig: HomeServerConnectionConfig?): WellknownResult {
+ override suspend fun getWellKnownData(
+ matrixId: String,
+ homeServerConnectionConfig: HomeServerConnectionConfig?
+ ): WellknownResult {
if (!MatrixPatterns.isUserId(matrixId)) {
throw MatrixIdFailure.InvalidMatrixId
}
@@ -391,11 +385,13 @@ internal class DefaultAuthenticationService @Inject constructor(
.withHomeServerUri("https://dummy.org")
.build()
- override suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig,
- matrixId: String,
- password: String,
- initialDeviceName: String,
- deviceId: String?): Session {
+ override suspend fun directAuthentication(
+ homeServerConnectionConfig: HomeServerConnectionConfig,
+ matrixId: String,
+ password: String,
+ initialDeviceName: String,
+ deviceId: String?
+ ): Session {
return directLoginTask.execute(
DirectLoginTask.Params(
homeServerConnectionConfig = homeServerConnectionConfig,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/PasswordLoginParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/PasswordLoginParams.kt
index 5be480f633..5f0a2298cb 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/PasswordLoginParams.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/PasswordLoginParams.kt
@@ -31,7 +31,8 @@ internal data class PasswordLoginParams(
@Json(name = "password") val password: String,
@Json(name = "type") override val type: String,
@Json(name = "initial_device_display_name") val deviceDisplayName: String?,
- @Json(name = "device_id") val deviceId: String?) : LoginParams {
+ @Json(name = "device_id") val deviceId: String?
+) : LoginParams {
companion object {
private const val IDENTIFIER_KEY_TYPE = "type"
@@ -47,10 +48,12 @@ internal data class PasswordLoginParams(
private const val IDENTIFIER_KEY_COUNTRY = "country"
private const val IDENTIFIER_KEY_PHONE = "phone"
- fun userIdentifier(user: String,
- password: String,
- deviceDisplayName: String?,
- deviceId: String?): PasswordLoginParams {
+ fun userIdentifier(
+ user: String,
+ password: String,
+ deviceDisplayName: String?,
+ deviceId: String?
+ ): PasswordLoginParams {
return PasswordLoginParams(
identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_USER,
@@ -63,11 +66,13 @@ internal data class PasswordLoginParams(
)
}
- fun thirdPartyIdentifier(medium: String,
- address: String,
- password: String,
- deviceDisplayName: String?,
- deviceId: String?): PasswordLoginParams {
+ fun thirdPartyIdentifier(
+ medium: String,
+ address: String,
+ password: String,
+ deviceDisplayName: String?,
+ deviceId: String?
+ ): PasswordLoginParams {
return PasswordLoginParams(
identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_THIRD_PARTY,
@@ -81,11 +86,13 @@ internal data class PasswordLoginParams(
)
}
- fun phoneIdentifier(country: String,
- phone: String,
- password: String,
- deviceDisplayName: String?,
- deviceId: String?): PasswordLoginParams {
+ fun phoneIdentifier(
+ country: String,
+ phone: String,
+ password: String,
+ deviceDisplayName: String?,
+ deviceId: String?
+ ): PasswordLoginParams {
return PasswordLoginParams(
identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_PHONE,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/RealmPendingSessionStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/RealmPendingSessionStore.kt
index 13f26e321d..aae8ff8419 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/RealmPendingSessionStore.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/RealmPendingSessionStore.kt
@@ -23,9 +23,10 @@ import org.matrix.android.sdk.internal.database.awaitTransaction
import org.matrix.android.sdk.internal.di.AuthDatabase
import javax.inject.Inject
-internal class RealmPendingSessionStore @Inject constructor(private val mapper: PendingSessionMapper,
- @AuthDatabase
- private val realmConfiguration: RealmConfiguration
+internal class RealmPendingSessionStore @Inject constructor(
+ private val mapper: PendingSessionMapper,
+ @AuthDatabase
+ private val realmConfiguration: RealmConfiguration
) : PendingSessionStore {
override suspend fun savePendingSessionData(pendingSessionData: PendingSessionData) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/RealmSessionParamsStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/RealmSessionParamsStore.kt
index 235ef6b709..4c3e3ca824 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/RealmSessionParamsStore.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/RealmSessionParamsStore.kt
@@ -28,9 +28,10 @@ import org.matrix.android.sdk.internal.di.AuthDatabase
import timber.log.Timber
import javax.inject.Inject
-internal class RealmSessionParamsStore @Inject constructor(private val mapper: SessionParamsMapper,
- @AuthDatabase
- private val realmConfiguration: RealmConfiguration
+internal class RealmSessionParamsStore @Inject constructor(
+ private val mapper: SessionParamsMapper,
+ @AuthDatabase
+ private val realmConfiguration: RealmConfiguration
) : SessionParamsStore {
override fun getLast(): SessionParams? {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt
index 0583951138..656a4f671b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt
@@ -52,10 +52,12 @@ internal class DefaultLoginWizard(
return getProfileTask.execute(GetProfileTask.Params(matrixId))
}
- override suspend fun login(login: String,
- password: String,
- initialDeviceName: String,
- deviceId: String?): Session {
+ override suspend fun login(
+ login: String,
+ password: String,
+ initialDeviceName: String,
+ deviceId: String?
+ ): Session {
val loginParams = if (Patterns.EMAIL_ADDRESS.matcher(login).matches()) {
PasswordLoginParams.thirdPartyIdentifier(
medium = ThreePidMedium.EMAIL,
@@ -101,7 +103,7 @@ internal class DefaultLoginWizard(
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
}
- override suspend fun resetPassword(email: String, newPassword: String) {
+ override suspend fun resetPassword(email: String) {
val param = RegisterAddThreePidTask.Params(
RegisterThreePid.Email(email),
pendingSessionData.clientSecret,
@@ -115,18 +117,17 @@ internal class DefaultLoginWizard(
authAPI.resetPassword(AddThreePidRegistrationParams.from(param))
}
- pendingSessionData = pendingSessionData.copy(resetPasswordData = ResetPasswordData(newPassword, result))
+ pendingSessionData = pendingSessionData.copy(resetPasswordData = ResetPasswordData(result))
.also { pendingSessionStore.savePendingSessionData(it) }
}
- override suspend fun resetPasswordMailConfirmed() {
- val safeResetPasswordData = pendingSessionData.resetPasswordData
- ?: throw IllegalStateException("developer error, no reset password in progress")
-
+ override suspend fun resetPasswordMailConfirmed(newPassword: String, logoutAllDevices: Boolean) {
+ val resetPasswordData = pendingSessionData.resetPasswordData ?: throw IllegalStateException("Developer error - Must call resetPassword first")
val param = ResetPasswordMailConfirmed.create(
pendingSessionData.clientSecret,
- safeResetPasswordData.addThreePidRegistrationResponse.sid,
- safeResetPasswordData.newPassword
+ resetPasswordData.addThreePidRegistrationResponse.sid,
+ newPassword,
+ logoutAllDevices
)
executeRequest(null) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DirectLoginTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DirectLoginTask.kt
index 28706c7e80..c9311867c8 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DirectLoginTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DirectLoginTask.kt
@@ -73,7 +73,7 @@ internal class DefaultDirectLoginTask @Inject constructor(
homeServerUrl,
throwable.fingerprint
)
- else -> throwable
+ else -> throwable
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordData.kt
index a65ec38d6d..87a7b346dc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordData.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordData.kt
@@ -24,6 +24,5 @@ import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistration
*/
@JsonClass(generateAdapter = true)
internal data class ResetPasswordData(
- val newPassword: String,
val addThreePidRegistrationResponse: AddThreePidRegistrationResponse
)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordMailConfirmed.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordMailConfirmed.kt
index 4e0c000f87..01481f70dc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordMailConfirmed.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordMailConfirmed.kt
@@ -30,13 +30,17 @@ internal data class ResetPasswordMailConfirmed(
// the new password
@Json(name = "new_password")
- val newPassword: String? = null
+ val newPassword: String? = null,
+
+ @Json(name = "logout_devices")
+ val logoutDevices: Boolean? = null
) {
companion object {
- fun create(clientSecret: String, sid: String, newPassword: String): ResetPasswordMailConfirmed {
+ fun create(clientSecret: String, sid: String, newPassword: String, logoutDevices: Boolean?): ResetPasswordMailConfirmed {
return ResetPasswordMailConfirmed(
auth = AuthParams.createForResetPassword(clientSecret, sid),
- newPassword = newPassword
+ newPassword = newPassword,
+ logoutDevices = logoutDevices
)
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt
index 2f05864d3b..f0cb6ebd6d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt
@@ -84,7 +84,7 @@ internal data class AddThreePidRegistrationParams(
companion object {
fun from(params: RegisterAddThreePidTask.Params): AddThreePidRegistrationParams {
return when (params.threePid) {
- is RegisterThreePid.Email -> AddThreePidRegistrationParams(
+ is RegisterThreePid.Email -> AddThreePidRegistrationParams(
email = params.threePid.email,
clientSecret = params.clientSecret,
sendAttempt = params.sendAttempt
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt
index 345f4097db..d6ec0297b4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt
@@ -51,12 +51,12 @@ internal class DefaultRegistrationWizard(
override fun getCurrentThreePid(): String? {
return when (val threePid = pendingSessionData.currentThreePidData?.threePid) {
- is RegisterThreePid.Email -> threePid.email
+ is RegisterThreePid.Email -> threePid.email
is RegisterThreePid.Msisdn -> {
// Take formatted msisdn if provided by the server
pendingSessionData.currentThreePidData?.addThreePidRegistrationResponse?.formattedMsisdn?.takeIf { it.isNotBlank() } ?: threePid.msisdn
}
- null -> null
+ null -> null
}
}
@@ -67,9 +67,11 @@ internal class DefaultRegistrationWizard(
return performRegistrationRequest(params)
}
- override suspend fun createAccount(userName: String?,
- password: String?,
- initialDeviceDisplayName: String?): RegistrationResult {
+ override suspend fun createAccount(
+ userName: String?,
+ password: String?,
+ initialDeviceDisplayName: String?
+ ): RegistrationResult {
val params = RegistrationParams(
username = userName,
password = password,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegisterAddThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegisterAddThreePidTask.kt
index 54a8ba0e6c..b84ed61361 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegisterAddThreePidTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegisterAddThreePidTask.kt
@@ -41,7 +41,7 @@ internal class DefaultRegisterAddThreePidTask(
private fun RegisterThreePid.toPath(): String {
return when (this) {
- is RegisterThreePid.Email -> "email"
+ is RegisterThreePid.Email -> "email"
is RegisterThreePid.Msisdn -> "msisdn"
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidData.kt
index c8f71af306..dde0a44ea0 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidData.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidData.kt
@@ -40,11 +40,13 @@ internal data class ThreePidData(
}
companion object {
- fun from(threePid: RegisterThreePid,
- addThreePidRegistrationResponse: AddThreePidRegistrationResponse,
- registrationParams: RegistrationParams): ThreePidData {
+ fun from(
+ threePid: RegisterThreePid,
+ addThreePidRegistrationResponse: AddThreePidRegistrationResponse,
+ registrationParams: RegistrationParams
+ ): ThreePidData {
return when (threePid) {
- is RegisterThreePid.Email ->
+ is RegisterThreePid.Email ->
ThreePidData(threePid.email, "", "", addThreePidRegistrationResponse, registrationParams)
is RegisterThreePid.Msisdn ->
ThreePidData("", threePid.msisdn, threePid.countryCode, addThreePidRegistrationResponse, registrationParams)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt
index 9b135c347d..8118f9faff 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt
@@ -35,9 +35,11 @@ import kotlin.coroutines.suspendCoroutine
* @return UiaResult if UIA handled, failed or cancelled
*
*/
-internal suspend fun handleUIA(failure: Throwable,
- interceptor: UserInteractiveAuthInterceptor,
- retryBlock: suspend (UIABaseAuth) -> Unit): UiaResult {
+internal suspend fun handleUIA(
+ failure: Throwable,
+ interceptor: UserInteractiveAuthInterceptor,
+ retryBlock: suspend (UIABaseAuth) -> Unit
+): UiaResult {
Timber.d("## UIA: check error ${failure.message}")
val flowResponse = failure.toRegistrationFlowResponse()
?: return UiaResult.FAILURE.also {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/HomeServerVersion.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/HomeServerVersion.kt
index 815f8de2de..75639c6a21 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/HomeServerVersion.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/HomeServerVersion.kt
@@ -16,6 +16,8 @@
package org.matrix.android.sdk.internal.auth.version
+import org.matrix.android.sdk.api.extensions.ensureNotEmpty
+
/**
* Values will take the form "rX.Y.Z".
* Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-versions
@@ -33,19 +35,19 @@ internal data class HomeServerVersion(
minor < other.minor -> -1
patch > other.patch -> 1
patch < other.patch -> -1
- else -> 0
+ else -> 0
}
}
companion object {
- internal val pattern = Regex("""[r|v](\d+)\.(\d+)\.(\d+)""")
+ internal val pattern = Regex("""[r|v](\d+)\.(\d+)(?:\.(\d+))?""")
internal fun parse(value: String): HomeServerVersion? {
val result = pattern.matchEntire(value) ?: return null
return HomeServerVersion(
major = result.groupValues[1].toInt(),
minor = result.groupValues[2].toInt(),
- patch = result.groupValues[3].toInt()
+ patch = result.groupValues.getOrNull(index = 3)?.ensureNotEmpty()?.toInt() ?: 0
)
}
@@ -56,6 +58,7 @@ internal data class HomeServerVersion(
val r0_4_0 = HomeServerVersion(major = 0, minor = 4, patch = 0)
val r0_5_0 = HomeServerVersion(major = 0, minor = 5, patch = 0)
val r0_6_0 = HomeServerVersion(major = 0, minor = 6, patch = 0)
+ val r0_6_1 = HomeServerVersion(major = 0, minor = 6, patch = 1)
val v1_3_0 = HomeServerVersion(major = 1, minor = 3, patch = 0)
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt
index cee4b12138..915b25134b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt
@@ -111,6 +111,15 @@ private fun Versions.doesServerSeparatesAddAndBind(): Boolean {
unstableFeatures?.get(FEATURE_SEPARATE_ADD_AND_BIND) ?: false
}
+/**
+ * Indicate if the server supports MSC2457 `logout_devices` parameter when setting a new password.
+ *
+ * @return true if logout_devices is supported
+ */
+internal fun Versions.doesServerSupportLogoutDevices(): Boolean {
+ return getMaxVersion() >= HomeServerVersion.r0_6_1
+}
+
private fun Versions.getMaxVersion(): HomeServerVersion {
return supportedVersions
?.mapNotNull { HomeServerVersion.parse(it) }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt
index 2265526484..c69a859016 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt
@@ -110,10 +110,12 @@ internal abstract class CryptoModule {
@Provides
@CryptoDatabase
@SessionScope
- fun providesRealmConfiguration(@SessionFilesDirectory directory: File,
- @UserMd5 userMd5: String,
- realmKeysUtils: RealmKeysUtils,
- realmCryptoStoreMigration: RealmCryptoStoreMigration): RealmConfiguration {
+ fun providesRealmConfiguration(
+ @SessionFilesDirectory directory: File,
+ @UserMd5 userMd5: String,
+ realmKeysUtils: RealmKeysUtils,
+ realmCryptoStoreMigration: RealmCryptoStoreMigration
+ ): RealmConfiguration {
return RealmConfiguration.Builder()
.directory(directory)
.apply {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt
index 824478f1d3..e0bcde2296 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt
@@ -188,8 +188,8 @@ internal class DefaultCryptoService @Inject constructor(
fun onStateEvent(roomId: String, event: Event) {
when (event.type) {
- EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
- EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event)
+ EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
+ EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event)
EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event)
}
}
@@ -198,8 +198,8 @@ internal class DefaultCryptoService @Inject constructor(
// handle state events
if (event.isStateEvent()) {
when (event.type) {
- EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
- EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event)
+ EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
+ EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event)
EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event)
}
}
@@ -592,10 +592,12 @@ internal class DefaultCryptoService @Inject constructor(
* @param membersId list of members to start tracking their devices
* @return true if the operation succeeds.
*/
- private suspend fun setEncryptionInRoom(roomId: String,
- algorithm: String?,
- inhibitDeviceQuery: Boolean,
- membersId: List): Boolean {
+ private suspend fun setEncryptionInRoom(
+ roomId: String,
+ algorithm: String?,
+ inhibitDeviceQuery: Boolean,
+ membersId: List
+ ): Boolean {
// If we already have encryption in this room, we should ignore this event
// (for now at least. Maybe we should alert the user somehow?)
val existingAlgorithm = cryptoStore.getRoomAlgorithm(roomId)
@@ -618,8 +620,8 @@ internal class DefaultCryptoService @Inject constructor(
val alg: IMXEncrypting? = when (algorithm) {
MXCRYPTO_ALGORITHM_MEGOLM -> megolmEncryptionFactory.create(roomId)
- MXCRYPTO_ALGORITHM_OLM -> olmEncryptionFactory.create(roomId)
- else -> null
+ MXCRYPTO_ALGORITHM_OLM -> olmEncryptionFactory.create(roomId)
+ else -> null
}
if (alg != null) {
@@ -691,10 +693,12 @@ internal class DefaultCryptoService @Inject constructor(
* @param roomId the room identifier the event will be sent.
* @param callback the asynchronous callback
*/
- override fun encryptEventContent(eventContent: Content,
- eventType: String,
- roomId: String,
- callback: MatrixCallback) {
+ override fun encryptEventContent(
+ eventContent: Content,
+ eventType: String,
+ roomId: String,
+ callback: MatrixCallback
+ ) {
// moved to crypto scope to have uptodate values
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
val userIds = getRoomUserIds(roomId)
@@ -796,10 +800,10 @@ internal class DefaultCryptoService @Inject constructor(
// Keys are imported directly, not waiting for end of sync
onRoomKeyEvent(event)
}
- EventType.REQUEST_SECRET -> {
+ EventType.REQUEST_SECRET -> {
secretShareManager.handleSecretRequest(event)
}
- EventType.ROOM_KEY_REQUEST -> {
+ EventType.ROOM_KEY_REQUEST -> {
event.getClearContent().toModel()?.let { req ->
// We'll always get these because we send room key requests to
// '*' (ie. 'all devices') which includes the sending device,
@@ -811,13 +815,13 @@ internal class DefaultCryptoService @Inject constructor(
}
}
}
- EventType.SEND_SECRET -> {
+ EventType.SEND_SECRET -> {
onSecretSendReceived(event)
}
- EventType.ROOM_KEY_WITHHELD -> {
+ EventType.ROOM_KEY_WITHHELD -> {
onKeyWithHeldReceived(event)
}
- else -> {
+ else -> {
// ignore
}
}
@@ -879,10 +883,12 @@ internal class DefaultCryptoService @Inject constructor(
/**
* Returns true if handled by SDK, otherwise should be sent to application layer.
*/
- private fun handleSDKLevelGossip(secretName: String?,
- secretValue: String): Boolean {
+ private fun handleSDKLevelGossip(
+ secretName: String?,
+ secretValue: String
+ ): Boolean {
return when (secretName) {
- MASTER_KEY_SSSS_NAME -> {
+ MASTER_KEY_SSSS_NAME -> {
crossSigningService.onSecretMSKGossip(secretValue)
true
}
@@ -898,7 +904,7 @@ internal class DefaultCryptoService @Inject constructor(
keysBackupService.onSecretKeyGossip(secretValue)
true
}
- else -> false
+ else -> false
}
}
@@ -1022,9 +1028,11 @@ internal class DefaultCryptoService @Inject constructor(
* @param progressListener the progress listener
* @return the result ImportRoomKeysResult
*/
- override suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
- password: String,
- progressListener: ProgressListener?): ImportRoomKeysResult {
+ override suspend fun importRoomKeys(
+ roomKeysAsArray: ByteArray,
+ password: String,
+ progressListener: ProgressListener?
+ ): ImportRoomKeysResult {
return withContext(coroutineDispatchers.crypto) {
Timber.tag(loggerTag.value).v("importRoomKeys starts")
@@ -1290,10 +1298,6 @@ internal class DefaultCryptoService @Inject constructor(
return cryptoStore.getWithHeldMegolmSession(roomId, sessionId)
}
- override fun logDbUsageInfo() {
- cryptoStore.logDbUsageInfo()
- }
-
override fun prepareToEncrypt(roomId: String, callback: MatrixCallback) {
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
Timber.tag(loggerTag.value).d("prepareToEncrypt() roomId:$roomId Check room members up to date")
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt
index 18b815b3d8..4f3900adb9 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt
@@ -231,8 +231,8 @@ internal class DeviceListManager @Inject constructor(
for ((k, value) in failures) {
val statusCode = when (val status = value["status"]) {
is Double -> status.toInt()
- is Int -> status.toInt()
- else -> 0
+ is Int -> status.toInt()
+ else -> 0
}
if (statusCode == 503) {
synchronized(notReadyToRetryHS) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt
index 28ddf291b2..e4d322cadd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt
@@ -44,7 +44,8 @@ private val loggerTag = LoggerTag("InboundGroupSessionStore", LoggerTag.CRYPTO)
internal class InboundGroupSessionStore @Inject constructor(
private val store: IMXCryptoStore,
private val cryptoCoroutineScope: CoroutineScope,
- private val coroutineDispatchers: MatrixCoroutineDispatchers) {
+ private val coroutineDispatchers: MatrixCoroutineDispatchers
+) {
private data class CacheKey(
val sessionId: String,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingKeyRequestManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingKeyRequestManager.kt
index 13f2fb861a..7f36224dae 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingKeyRequestManager.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingKeyRequestManager.kt
@@ -135,7 +135,7 @@ internal class IncomingKeyRequestManager @Inject constructor(
// just add to the buffer
incomingRequestBuffer.add(validMegolmRequest)
}
- MegolmRequestAction.Cancel -> {
+ MegolmRequestAction.Cancel -> {
// ignore, we can't cancel as it's not known (probably already processed)
// still notify app layer if it was passed up previously
IncomingRoomKeyRequest.fromRestRequest(senderId, request, clock)?.let { iReq ->
@@ -159,7 +159,7 @@ internal class IncomingKeyRequestManager @Inject constructor(
MegolmRequestAction.Request -> {
// it's already in buffer, nop keep existing
}
- MegolmRequestAction.Cancel -> {
+ MegolmRequestAction.Cancel -> {
// discard the request in buffer
incomingRequestBuffer.remove(existing)
outgoingRequestScope.launch(coroutineDispatchers.computation) {
@@ -369,9 +369,11 @@ internal class IncomingKeyRequestManager @Inject constructor(
shareMegolmKey(validReq, requestingDevice, null)
}
- private suspend fun shareMegolmKey(validRequest: ValidMegolmRequestBody,
- requestingDevice: CryptoDeviceInfo,
- chainIndex: Long?): Boolean {
+ private suspend fun shareMegolmKey(
+ validRequest: ValidMegolmRequestBody,
+ requestingDevice: CryptoDeviceInfo,
+ chainIndex: Long?
+ ): Boolean {
Timber.tag(loggerTag.value)
.d("try to re-share Megolm Key at index $chainIndex for ${validRequest.shortDbgString()}")
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXCryptoAlgorithms.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXCryptoAlgorithms.kt
index 5a5ee9e696..14b0e8e125 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXCryptoAlgorithms.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXCryptoAlgorithms.kt
@@ -32,7 +32,7 @@ internal object MXCryptoAlgorithms {
return when (algorithm) {
MXCRYPTO_ALGORITHM_MEGOLM,
MXCRYPTO_ALGORITHM_OLM -> true
- else -> false
+ else -> false
}
}
@@ -47,7 +47,7 @@ internal object MXCryptoAlgorithms {
return when (algorithm) {
MXCRYPTO_ALGORITHM_MEGOLM,
MXCRYPTO_ALGORITHM_OLM -> true
- else -> false
+ else -> false
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt
index 1d25d82549..24b6fd166f 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt
@@ -600,13 +600,15 @@ internal class MXOlmDevice @Inject constructor(
* @param exportFormat true if the megolm keys are in export format
* @return true if the operation succeeds.
*/
- fun addInboundGroupSession(sessionId: String,
- sessionKey: String,
- roomId: String,
- senderKey: String,
- forwardingCurve25519KeyChain: List,
- keysClaimed: Map,
- exportFormat: Boolean): AddSessionResult {
+ fun addInboundGroupSession(
+ sessionId: String,
+ sessionKey: String,
+ roomId: String,
+ senderKey: String,
+ forwardingCurve25519KeyChain: List,
+ keysClaimed: Map,
+ exportFormat: Boolean
+ ): AddSessionResult {
val candidateSession = OlmInboundGroupSessionWrapper2(sessionKey, exportFormat)
val existingSessionHolder = tryOrNull { getInboundGroupSession(sessionId, senderKey, roomId) }
val existingSession = existingSessionHolder?.wrapper
@@ -762,12 +764,14 @@ internal class MXOlmDevice @Inject constructor(
* @return the decrypting result. Null if the sessionId is unknown.
*/
@Throws(MXCryptoError::class)
- suspend fun decryptGroupMessage(body: String,
- roomId: String,
- timeline: String?,
- eventId: String,
- sessionId: String,
- senderKey: String): OlmDecryptionResult {
+ suspend fun decryptGroupMessage(
+ body: String,
+ roomId: String,
+ timeline: String?,
+ eventId: String,
+ sessionId: String,
+ senderKey: String
+ ): OlmDecryptionResult {
val sessionHolder = getInboundGroupSession(sessionId, senderKey, roomId)
val wrapper = sessionHolder.wrapper
val inboundGroupSession = wrapper.olmInboundGroupSession
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ObjectSigner.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ObjectSigner.kt
index ab562d954a..3f4b633ea0 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ObjectSigner.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ObjectSigner.kt
@@ -19,8 +19,10 @@ package org.matrix.android.sdk.internal.crypto
import org.matrix.android.sdk.api.auth.data.Credentials
import javax.inject.Inject
-internal class ObjectSigner @Inject constructor(private val credentials: Credentials,
- private val olmDevice: MXOlmDevice) {
+internal class ObjectSigner @Inject constructor(
+ private val credentials: Credentials,
+ private val olmDevice: MXOlmDevice
+) {
/**
* Sign Object.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingKeyRequestManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingKeyRequestManager.kt
index d7652d0771..6b22cc09d6 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingKeyRequestManager.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingKeyRequestManager.kt
@@ -71,7 +71,8 @@ internal class OutgoingKeyRequestManager @Inject constructor(
private val inboundGroupSessionStore: InboundGroupSessionStore,
private val sendToDeviceTask: SendToDeviceTask,
private val deviceListManager: DeviceListManager,
- private val perSessionBackupQueryRateLimiter: PerSessionBackupQueryRateLimiter) {
+ private val perSessionBackupQueryRateLimiter: PerSessionBackupQueryRateLimiter
+) {
private val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
private val outgoingRequestScope = CoroutineScope(SupervisorJob() + dispatcher)
@@ -180,13 +181,15 @@ internal class OutgoingKeyRequestManager @Inject constructor(
}
}
- fun onRoomKeyForwarded(sessionId: String,
- algorithm: String,
- roomId: String,
- senderKey: String,
- fromDevice: String?,
- fromIndex: Int,
- event: Event) {
+ fun onRoomKeyForwarded(
+ sessionId: String,
+ algorithm: String,
+ roomId: String,
+ senderKey: String,
+ fromDevice: String?,
+ fromIndex: Int,
+ event: Event
+ ) {
Timber.tag(loggerTag.value).d("Key forwarded for $sessionId from ${event.senderId}|$fromDevice at index $fromIndex")
outgoingRequestScope.launch {
sequencer.post {
@@ -208,12 +211,14 @@ internal class OutgoingKeyRequestManager @Inject constructor(
}
}
- fun onRoomKeyWithHeld(sessionId: String,
- algorithm: String,
- roomId: String,
- senderKey: String,
- fromDevice: String?,
- event: Event) {
+ fun onRoomKeyWithHeld(
+ sessionId: String,
+ algorithm: String,
+ roomId: String,
+ senderKey: String,
+ fromDevice: String?,
+ event: Event
+ ) {
outgoingRequestScope.launch {
sequencer.post {
Timber.tag(loggerTag.value).d("Withheld received for $sessionId from ${event.senderId}|$fromDevice")
@@ -294,19 +299,19 @@ internal class OutgoingKeyRequestManager @Inject constructor(
}
knownRequest.forEach { request ->
when (request.state) {
- OutgoingRoomKeyRequestState.UNSENT -> {
+ OutgoingRoomKeyRequestState.UNSENT -> {
if (request.fromIndex >= localKnownChainIndex) {
// we have a good index we can cancel
cryptoStore.deleteOutgoingRoomKeyRequest(request.requestId)
}
}
- OutgoingRoomKeyRequestState.SENT -> {
+ OutgoingRoomKeyRequestState.SENT -> {
// It was already sent, and index satisfied we can cancel
if (request.fromIndex >= localKnownChainIndex) {
cryptoStore.updateOutgoingRoomKeyRequestState(request.requestId, OutgoingRoomKeyRequestState.CANCELLATION_PENDING)
}
}
- OutgoingRoomKeyRequestState.CANCELLATION_PENDING -> {
+ OutgoingRoomKeyRequestState.CANCELLATION_PENDING -> {
// It is already marked to be cancelled
}
OutgoingRoomKeyRequestState.CANCELLATION_PENDING_AND_WILL_RESEND -> {
@@ -315,7 +320,7 @@ internal class OutgoingKeyRequestManager @Inject constructor(
cryptoStore.updateOutgoingRoomKeyRequestState(request.requestId, OutgoingRoomKeyRequestState.CANCELLATION_PENDING)
}
}
- OutgoingRoomKeyRequestState.SENT_THEN_CANCELED -> {
+ OutgoingRoomKeyRequestState.SENT_THEN_CANCELED -> {
// was already canceled
// if we need a better index, should we resend?
}
@@ -346,14 +351,14 @@ internal class OutgoingKeyRequestManager @Inject constructor(
val existing = cryptoStore.getOutgoingRoomKeyRequest(requestBody)
Timber.tag(loggerTag.value).v("Queueing key request exiting is ${existing?.state}")
when (existing?.state) {
- null -> {
+ null -> {
// create a new one
cryptoStore.getOrAddOutgoingRoomKeyRequest(requestBody, recipients, fromIndex)
}
- OutgoingRoomKeyRequestState.UNSENT -> {
+ OutgoingRoomKeyRequestState.UNSENT -> {
// nothing it's new or not yet handled
}
- OutgoingRoomKeyRequestState.SENT -> {
+ OutgoingRoomKeyRequestState.SENT -> {
// it was already requested
Timber.tag(loggerTag.value).d("The session ${requestBody.sessionId} is already requested")
if (force) {
@@ -366,7 +371,7 @@ internal class OutgoingKeyRequestManager @Inject constructor(
}
}
}
- OutgoingRoomKeyRequestState.CANCELLATION_PENDING -> {
+ OutgoingRoomKeyRequestState.CANCELLATION_PENDING -> {
// request is canceled only if I got the keys so what to do here...
if (force) {
cryptoStore.updateOutgoingRoomKeyRequestState(existing.requestId, OutgoingRoomKeyRequestState.CANCELLATION_PENDING_AND_WILL_RESEND)
@@ -375,7 +380,7 @@ internal class OutgoingKeyRequestManager @Inject constructor(
OutgoingRoomKeyRequestState.CANCELLATION_PENDING_AND_WILL_RESEND -> {
// It's already going to resend
}
- OutgoingRoomKeyRequestState.SENT_THEN_CANCELED -> {
+ OutgoingRoomKeyRequestState.SENT_THEN_CANCELED -> {
if (force) {
cryptoStore.deleteOutgoingRoomKeyRequest(existing.requestId)
cryptoStore.getOrAddOutgoingRoomKeyRequest(requestBody, recipients, fromIndex)
@@ -396,11 +401,11 @@ internal class OutgoingKeyRequestManager @Inject constructor(
measureTimeMillis {
toProcess.forEach {
when (it.state) {
- OutgoingRoomKeyRequestState.UNSENT -> handleUnsentRequest(it)
- OutgoingRoomKeyRequestState.CANCELLATION_PENDING -> handleRequestToCancel(it)
+ OutgoingRoomKeyRequestState.UNSENT -> handleUnsentRequest(it)
+ OutgoingRoomKeyRequestState.CANCELLATION_PENDING -> handleRequestToCancel(it)
OutgoingRoomKeyRequestState.CANCELLATION_PENDING_AND_WILL_RESEND -> handleRequestToCancelWillResend(it)
OutgoingRoomKeyRequestState.SENT_THEN_CANCELED,
- OutgoingRoomKeyRequestState.SENT -> {
+ OutgoingRoomKeyRequestState.SENT -> {
// these are filtered out
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt
index a80bafbe79..d37e60d289 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt
@@ -85,7 +85,7 @@ internal class RoomDecryptorProvider @Inject constructor(
}
}
}
- else -> olmDecryptionFactory.create()
+ else -> olmDecryptionFactory.create()
}
if (!roomId.isNullOrEmpty()) {
synchronized(roomDecryptors) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomEncryptorsStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomEncryptorsStore.kt
index 1a8c160d9c..9f6714cc45 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomEncryptorsStore.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomEncryptorsStore.kt
@@ -49,8 +49,8 @@ internal class RoomEncryptorsStore @Inject constructor(
} else {
val alg: IMXEncrypting? = when (cryptoStore.getRoomAlgorithm(roomId)) {
MXCRYPTO_ALGORITHM_MEGOLM -> megolmEncryptionFactory.create(roomId)
- MXCRYPTO_ALGORITHM_OLM -> olmEncryptionFactory.create(roomId)
- else -> null
+ MXCRYPTO_ALGORITHM_OLM -> olmEncryptionFactory.create(roomId)
+ else -> null
}
alg?.let { roomEncryptors.put(roomId, it) }
return@synchronized alg
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt
index 6fb6914206..a79e1a8901 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt
@@ -150,14 +150,14 @@ internal class SecretShareManager @Inject constructor(
// we can share the secret
val secretValue = when (secretName) {
- MASTER_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.master
+ MASTER_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.master
SELF_SIGNING_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.selfSigned
USER_SIGNING_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.user
KEYBACKUP_SECRET_SSSS_NAME -> cryptoStore.getKeyBackupRecoveryKeyInfo()?.recoveryKey
?.let {
extractCurveKeyFromRecoveryKey(it)?.toBase64NoPadding()
}
- else -> null
+ else -> null
}
if (secretValue == null) {
Timber.tag(loggerTag.value)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt
index c728f1b682..c263192fee 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt
@@ -39,7 +39,8 @@ private val loggerTag = LoggerTag("EnsureOlmSessionsForDevicesAction", LoggerTag
internal class EnsureOlmSessionsForDevicesAction @Inject constructor(
private val olmDevice: MXOlmDevice,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
- private val oneTimeKeysForUsersDeviceTask: ClaimOneTimeKeysForUsersDeviceTask) {
+ private val oneTimeKeysForUsersDeviceTask: ClaimOneTimeKeysForUsersDeviceTask
+) {
private val ensureMutex = Mutex()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt
index 4c5720daf2..da09524668 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt
@@ -23,9 +23,11 @@ import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import timber.log.Timber
import javax.inject.Inject
-internal class EnsureOlmSessionsForUsersAction @Inject constructor(private val olmDevice: MXOlmDevice,
- private val cryptoStore: IMXCryptoStore,
- private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction) {
+internal class EnsureOlmSessionsForUsersAction @Inject constructor(
+ private val olmDevice: MXOlmDevice,
+ private val cryptoStore: IMXCryptoStore,
+ private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction
+) {
/**
* Try to make sure we have established olm sessions for the given users.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt
index 67d73c21ed..f6ab96aee6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt
@@ -33,11 +33,12 @@ import javax.inject.Inject
private val loggerTag = LoggerTag("MegolmSessionDataImporter", LoggerTag.CRYPTO)
-internal class MegolmSessionDataImporter @Inject constructor(private val olmDevice: MXOlmDevice,
- private val roomDecryptorProvider: RoomDecryptorProvider,
- private val outgoingKeyRequestManager: OutgoingKeyRequestManager,
- private val cryptoStore: IMXCryptoStore,
- private val clock: Clock,
+internal class MegolmSessionDataImporter @Inject constructor(
+ private val olmDevice: MXOlmDevice,
+ private val roomDecryptorProvider: RoomDecryptorProvider,
+ private val outgoingKeyRequestManager: OutgoingKeyRequestManager,
+ private val cryptoStore: IMXCryptoStore,
+ private val clock: Clock,
) {
/**
@@ -50,9 +51,11 @@ internal class MegolmSessionDataImporter @Inject constructor(private val olmDevi
* @return import room keys result
*/
@WorkerThread
- fun handle(megolmSessionsData: List,
- fromBackup: Boolean,
- progressListener: ProgressListener?): ImportRoomKeysResult {
+ fun handle(
+ megolmSessionsData: List,
+ fromBackup: Boolean,
+ progressListener: ProgressListener?
+ ): ImportRoomKeysResult {
val t0 = clock.epochMillis()
val totalNumbersOfKeys = megolmSessionsData.size
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MessageEncrypter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MessageEncrypter.kt
index 919e38c391..eff2132820 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MessageEncrypter.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MessageEncrypter.kt
@@ -36,7 +36,8 @@ internal class MessageEncrypter @Inject constructor(
private val userId: String,
@DeviceId
private val deviceId: String?,
- private val olmDevice: MXOlmDevice) {
+ private val olmDevice: MXOlmDevice
+) {
/**
* Encrypt an event payload for a list of devices.
* This method must be called from the getCryptoHandler() thread.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/SetDeviceVerificationAction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/SetDeviceVerificationAction.kt
index 60181138fb..6028b1a5a2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/SetDeviceVerificationAction.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/SetDeviceVerificationAction.kt
@@ -26,7 +26,8 @@ import javax.inject.Inject
internal class SetDeviceVerificationAction @Inject constructor(
private val cryptoStore: IMXCryptoStore,
@UserId private val userId: String,
- private val defaultKeysBackupService: DefaultKeysBackupService) {
+ private val defaultKeysBackupService: DefaultKeysBackupService
+) {
fun handle(trustLevel: DeviceTrustLevel, userId: String, deviceId: String) {
val device = cryptoStore.getUserDevice(userId, deviceId)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXGroupEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXGroupEncryption.kt
index 8cf01f1972..9ec78f37cf 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXGroupEncryption.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXGroupEncryption.kt
@@ -45,8 +45,10 @@ internal interface IMXGroupEncryption {
*
* @return true in case of success
*/
- suspend fun reshareKey(groupSessionId: String,
- userId: String,
- deviceId: String,
- senderKey: String): Boolean
+ suspend fun reshareKey(
+ groupSessionId: String,
+ userId: String,
+ deviceId: String,
+ senderKey: String
+ ): Boolean
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt
index 722462bf0e..141d6f74cd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt
@@ -149,7 +149,8 @@ internal class MXMegolmDecryption(
throw MXCryptoError.Base(
MXCryptoError.ErrorType.KEYS_WITHHELD,
withHeldInfo.code?.value ?: "",
- withHeldInfo.reason)
+ withHeldInfo.reason
+ )
}
if (requestKeysOnFail) {
@@ -249,9 +250,9 @@ internal class MXMegolmDecryption(
)
when (addSessionResult) {
- is MXOlmDevice.AddSessionResult.Imported -> addSessionResult.ratchetIndex
+ is MXOlmDevice.AddSessionResult.Imported -> addSessionResult.ratchetIndex
is MXOlmDevice.AddSessionResult.NotImportedHigherIndex -> addSessionResult.newIndex
- else -> null
+ else -> null
}?.let { index ->
if (event.getClearType() == EventType.FORWARDED_ROOM_KEY) {
val fromDevice = (event.content?.get("sender_key") as? String)?.let { senderDeviceIdentityKey ->
@@ -268,7 +269,8 @@ internal class MXMegolmDecryption(
senderKey = senderKey,
fromIndex = index,
fromDevice = fromDevice,
- event = event)
+ event = event
+ )
cryptoStore.saveIncomingForwardKeyAuditTrail(
roomId = roomKeyContent.roomId,
@@ -277,7 +279,8 @@ internal class MXMegolmDecryption(
algorithm = roomKeyContent.algorithm ?: "",
userId = event.senderId ?: "",
deviceId = fromDevice ?: "",
- chainIndex = index.toLong())
+ chainIndex = index.toLong()
+ )
// The index is used to decide if we cancel sent request or if we wait for a better key
outgoingKeyRequestManager.postCancelRequestForSessionIfNeeded(roomKeyContent.sessionId, roomKeyContent.roomId, senderKey, index)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt
index 096773a959..81a6fb28c0 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt
@@ -35,6 +35,7 @@ internal class MXMegolmDecryptionFactory @Inject constructor(
olmDevice,
outgoingKeyRequestManager,
cryptoStore,
- eventsManager)
+ eventsManager
+ )
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt
index 8b4e9df607..7bfbae6edf 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt
@@ -84,9 +84,11 @@ internal class MXMegolmEncryption(
private var sessionRotationPeriodMsgs: Int = 100
private var sessionRotationPeriodMs: Int = 7 * 24 * 3600 * 1000
- override suspend fun encryptEventContent(eventContent: Content,
- eventType: String,
- userIds: List): Content {
+ override suspend fun encryptEventContent(
+ eventContent: Content,
+ eventType: String,
+ userIds: List
+ ): Content {
val ts = clock.epochMillis()
Timber.tag(loggerTag.value).v("encryptEventContent : getDevicesInRoom")
val devices = getDevicesInRoom(userIds)
@@ -201,8 +203,10 @@ internal class MXMegolmEncryption(
* @param session the session info
* @param devicesByUsers the devices map
*/
- private suspend fun shareKey(session: MXOutboundSessionInfo,
- devicesByUsers: Map>) {
+ private suspend fun shareKey(
+ session: MXOutboundSessionInfo,
+ devicesByUsers: Map>
+ ) {
// nothing to send, the task is done
if (devicesByUsers.isEmpty()) {
Timber.tag(loggerTag.value).v("shareKey() : nothing more to do")
@@ -230,8 +234,10 @@ internal class MXMegolmEncryption(
* @param session the session info
* @param devicesByUser the devices map
*/
- private suspend fun shareUserDevicesKey(session: MXOutboundSessionInfo,
- devicesByUser: Map>) {
+ private suspend fun shareUserDevicesKey(
+ session: MXOutboundSessionInfo,
+ devicesByUser: Map>
+ ) {
val sessionKey = olmDevice.getSessionKey(session.sessionId)
val chainIndex = olmDevice.getMessageIndex(session.sessionId)
@@ -321,10 +327,12 @@ internal class MXMegolmEncryption(
}
}
- private suspend fun notifyKeyWithHeld(targets: List,
- sessionId: String,
- senderKey: String?,
- code: WithHeldCode) {
+ private suspend fun notifyKeyWithHeld(
+ targets: List,
+ sessionId: String,
+ senderKey: String?,
+ code: WithHeldCode
+ ) {
Timber.tag(loggerTag.value).d(
"notifyKeyWithHeld() :sending withheld for session:$sessionId and code $code to" +
" ${targets.joinToString { "${it.userId}|${it.deviceId}" }}"
@@ -435,10 +443,12 @@ internal class MXMegolmEncryption(
}
}
- override suspend fun reshareKey(groupSessionId: String,
- userId: String,
- deviceId: String,
- senderKey: String): Boolean {
+ override suspend fun reshareKey(
+ groupSessionId: String,
+ userId: String,
+ deviceId: String,
+ senderKey: String
+ ): Boolean {
Timber.tag(loggerTag.value).i("process reshareKey for $groupSessionId to $userId:$deviceId")
val deviceInfo = cryptoStore.getUserDevice(userId, deviceId) ?: return false
.also { Timber.tag(loggerTag.value).w("reshareKey: Device not found") }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt
index 61ad345c62..30fd403ce8 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt
@@ -23,7 +23,8 @@ import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
internal class SharedWithHelper(
private val roomId: String,
private val sessionId: String,
- private val cryptoStore: IMXCryptoStore) {
+ private val cryptoStore: IMXCryptoStore
+) {
fun sharedWithDevices(): MXUsersDevicesMap {
return cryptoStore.getSharedWithInfo(roomId, sessionId)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt
index 23c8f0e905..219cadac46 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt
@@ -38,7 +38,8 @@ internal class MXOlmDecryption(
// The olm device interface
private val olmDevice: MXOlmDevice,
// the matrix userId
- private val userId: String) :
+ private val userId: String
+) :
IMXDecrypting {
@Throws(MXCryptoError::class)
@@ -190,9 +191,9 @@ internal class MXOlmDecryption(
val messageBody = message["body"] as? String ?: return null
val messageType = when (val typeAsVoid = message["type"]) {
is Double -> typeAsVoid.toInt()
- is Int -> typeAsVoid
- is Long -> typeAsVoid.toInt()
- else -> return null
+ is Int -> typeAsVoid
+ is Long -> typeAsVoid.toInt()
+ else -> return null
}
// Try each session in turn
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt
index d5c5e85e41..a50ac8ca8a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt
@@ -20,8 +20,10 @@ import org.matrix.android.sdk.internal.crypto.MXOlmDevice
import org.matrix.android.sdk.internal.di.UserId
import javax.inject.Inject
-internal class MXOlmDecryptionFactory @Inject constructor(private val olmDevice: MXOlmDevice,
- @UserId private val userId: String) {
+internal class MXOlmDecryptionFactory @Inject constructor(
+ private val olmDevice: MXOlmDevice,
+ @UserId private val userId: String
+) {
fun create(): MXOlmDecryption {
return MXOlmDecryption(
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt
index bde1d65093..fb70e23b03 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt
@@ -32,7 +32,8 @@ internal class MXOlmEncryption(
private val cryptoStore: IMXCryptoStore,
private val messageEncrypter: MessageEncrypter,
private val deviceListManager: DeviceListManager,
- private val ensureOlmSessionsForUsersAction: EnsureOlmSessionsForUsersAction) :
+ private val ensureOlmSessionsForUsersAction: EnsureOlmSessionsForUsersAction
+) :
IMXEncrypting {
override suspend fun encryptEventContent(eventContent: Content, eventType: String, userIds: List): Content {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt
index 44e55900e4..012886203e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt
@@ -24,12 +24,14 @@ import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import javax.inject.Inject
-internal class MXOlmEncryptionFactory @Inject constructor(private val olmDevice: MXOlmDevice,
- private val cryptoStore: IMXCryptoStore,
- private val messageEncrypter: MessageEncrypter,
- private val deviceListManager: DeviceListManager,
- private val coroutineDispatchers: MatrixCoroutineDispatchers,
- private val ensureOlmSessionsForUsersAction: EnsureOlmSessionsForUsersAction) {
+internal class MXOlmEncryptionFactory @Inject constructor(
+ private val olmDevice: MXOlmDevice,
+ private val cryptoStore: IMXCryptoStore,
+ private val messageEncrypter: MessageEncrypter,
+ private val deviceListManager: DeviceListManager,
+ private val coroutineDispatchers: MatrixCoroutineDispatchers,
+ private val ensureOlmSessionsForUsersAction: EnsureOlmSessionsForUsersAction
+) {
fun create(roomId: String): MXOlmEncryption {
return MXOlmEncryption(
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt
index f5ead35933..d5a8bdfd7c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt
@@ -117,9 +117,11 @@ internal interface CryptoApi {
* @param body the body
*/
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "sendToDevice/{eventType}/{txnId}")
- suspend fun sendToDevice(@Path("eventType") eventType: String,
- @Path("txnId") transactionId: String,
- @Body body: SendToDeviceBody)
+ suspend fun sendToDevice(
+ @Path("eventType") eventType: String,
+ @Path("txnId") transactionId: String,
+ @Body body: SendToDeviceBody
+ )
/**
* Delete a device.
@@ -129,8 +131,10 @@ internal interface CryptoApi {
* @param params the deletion parameters
*/
@HTTP(path = NetworkConstants.URI_API_PREFIX_PATH_R0 + "devices/{device_id}", method = "DELETE", hasBody = true)
- suspend fun deleteDevice(@Path("device_id") deviceId: String,
- @Body params: DeleteDeviceParams)
+ suspend fun deleteDevice(
+ @Path("device_id") deviceId: String,
+ @Body params: DeleteDeviceParams
+ )
/**
* Update the device information.
@@ -140,8 +144,10 @@ internal interface CryptoApi {
* @param params the params
*/
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "devices/{device_id}")
- suspend fun updateDeviceInfo(@Path("device_id") deviceId: String,
- @Body params: UpdateDeviceInfoBody)
+ suspend fun updateDeviceInfo(
+ @Path("device_id") deviceId: String,
+ @Body params: UpdateDeviceInfoBody
+ )
/**
* Get the update devices list from two sync token.
@@ -151,6 +157,8 @@ internal interface CryptoApi {
* @param newToken the up-to token.
*/
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "keys/changes")
- suspend fun getKeyChanges(@Query("from") oldToken: String,
- @Query("to") newToken: String): KeyChangesResponse
+ suspend fun getKeyChanges(
+ @Query("from") oldToken: String,
+ @Query("to") newToken: String
+ ): KeyChangesResponse
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt
index 7ff08cd127..37c8e755ff 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt
@@ -41,10 +41,12 @@ internal object MXEncryptedAttachments {
private const val SECRET_KEY_SPEC_ALGORITHM = "AES"
private const val MESSAGE_DIGEST_ALGORITHM = "SHA-256"
- fun encrypt(clearStream: InputStream,
- outputFile: File,
- clock: Clock,
- progress: ((current: Int, total: Int) -> Unit)): EncryptedFileInfo {
+ fun encrypt(
+ clearStream: InputStream,
+ outputFile: File,
+ clock: Clock,
+ progress: ((current: Int, total: Int) -> Unit)
+ ): EncryptedFileInfo {
val t0 = clock.epochMillis()
val secureRandom = SecureRandom()
val initVectorBytes = ByteArray(16) { 0.toByte() }
@@ -236,10 +238,11 @@ internal object MXEncryptedAttachments {
* @param clock a clock to retrieve current time
* @return true in case of success, false in case of error
*/
- fun decryptAttachment(attachmentStream: InputStream?,
- elementToDecrypt: ElementToDecrypt?,
- outputStream: OutputStream,
- clock: Clock
+ fun decryptAttachment(
+ attachmentStream: InputStream?,
+ elementToDecrypt: ElementToDecrypt?,
+ outputStream: OutputStream,
+ clock: Clock
): Boolean {
// sanity checks
if (null == attachmentStream || elementToDecrypt == null) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/CrossSigningOlm.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/CrossSigningOlm.kt
index 4fa355cd2a..3218b99948 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/CrossSigningOlm.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/CrossSigningOlm.kt
@@ -53,13 +53,13 @@ internal class CrossSigningOlm @Inject constructor(
fun signObject(type: KeyType, strToSign: String): Map {
val myKeys = cryptoStore.getMyCrossSigningInfo()
val pubKey = when (type) {
- KeyType.SELF -> myKeys?.selfSigningKey()
- KeyType.USER -> myKeys?.userKey()
+ KeyType.SELF -> myKeys?.selfSigningKey()
+ KeyType.USER -> myKeys?.userKey()
KeyType.MASTER -> myKeys?.masterKey()
}?.unpaddedBase64PublicKey
val pkSigning = when (type) {
- KeyType.SELF -> selfSigningPkSigning
- KeyType.USER -> userPkSigning
+ KeyType.SELF -> selfSigningPkSigning
+ KeyType.USER -> userPkSigning
KeyType.MASTER -> masterPkSigning
}
if (pubKey == null || pkSigning == null) {
@@ -76,8 +76,8 @@ internal class CrossSigningOlm @Inject constructor(
?: throw NoSuchElementException("Cross Signing not configured")
val myUserID = myKeys.userId
val pubKey = when (type) {
- KeyType.SELF -> myKeys.selfSigningKey()
- KeyType.USER -> myKeys.userKey()
+ KeyType.SELF -> myKeys.selfSigningKey()
+ KeyType.USER -> myKeys.userKey()
KeyType.MASTER -> myKeys.masterKey()
}?.unpaddedBase64PublicKey ?: throw NoSuchElementException("Cross Signing not configured")
val signaturesMadeByMyKey = signatures[myUserID] // Signatures made by me
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt
index 6c198abc2e..e466def1a1 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt
@@ -261,9 +261,10 @@ internal class DefaultCrossSigningService @Inject constructor(
}
}
- override fun checkTrustFromPrivateKeys(masterKeyPrivateKey: String?,
- uskKeyPrivateKey: String?,
- sskPrivateKey: String?
+ override fun checkTrustFromPrivateKeys(
+ masterKeyPrivateKey: String?,
+ uskKeyPrivateKey: String?,
+ sskPrivateKey: String?
): UserTrustResult {
val mxCrossSigningInfo = getMyCrossSigningKeys() ?: return UserTrustResult.CrossSigningNotConfigured(userId)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt
index 74f0f5745d..f1dc060e10 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt
@@ -149,7 +149,7 @@ internal class UpdateTrustWorker(context: Context, params: WorkerParameters, ses
val trusts = otherInfos.mapValues { entry ->
when (entry.key) {
myUserId -> myTrustResult
- else -> {
+ else -> {
crossSigningService.checkOtherMSKTrusted(myCrossSigningInfo, entry.value).also {
Timber.v("## CrossSigning - user:${entry.key} result:$it")
}
@@ -276,10 +276,12 @@ internal class UpdateTrustWorker(context: Context, params: WorkerParameters, ses
}
}
- private fun computeRoomShield(myCrossSigningInfo: MXCrossSigningInfo?,
- cryptoRealm: Realm,
- activeMemberUserIds: List,
- roomSummaryEntity: RoomSummaryEntity): RoomEncryptionTrustLevel {
+ private fun computeRoomShield(
+ myCrossSigningInfo: MXCrossSigningInfo?,
+ cryptoRealm: Realm,
+ activeMemberUserIds: List,
+ roomSummaryEntity: RoomSummaryEntity
+ ): RoomEncryptionTrustLevel {
Timber.v("## CrossSigning - computeRoomShield ${roomSummaryEntity.roomId} -> ${activeMemberUserIds.logLimit()}")
// The set of “all users” depends on the type of room:
// For regular / topic rooms which have more than 2 members (including yourself) are considered when decorating a room
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt
index efd3bca824..5eaa106af3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt
@@ -151,9 +151,11 @@ internal class DefaultKeysBackupService @Inject constructor(
keysBackupStateManager.removeListener(listener)
}
- override fun prepareKeysBackupVersion(password: String?,
- progressListener: ProgressListener?,
- callback: MatrixCallback) {
+ override fun prepareKeysBackupVersion(
+ password: String?,
+ progressListener: ProgressListener?,
+ callback: MatrixCallback
+ ) {
cryptoCoroutineScope.launch(coroutineDispatchers.io) {
try {
val olmPkDecryption = OlmPkDecryption()
@@ -227,8 +229,10 @@ internal class DefaultKeysBackupService @Inject constructor(
}
}
- override fun createKeysBackupVersion(keysBackupCreationInfo: MegolmBackupCreationInfo,
- callback: MatrixCallback) {
+ override fun createKeysBackupVersion(
+ keysBackupCreationInfo: MegolmBackupCreationInfo,
+ callback: MatrixCallback
+ ) {
@Suppress("UNCHECKED_CAST")
val createKeysBackupVersionBody = CreateKeysBackupVersionBody(
algorithm = keysBackupCreationInfo.algorithm,
@@ -318,7 +322,7 @@ internal class DefaultKeysBackupService @Inject constructor(
// val hashServer = keysBackupData?.backupLastServerHash
return when {
- totalNumberOfKeysLocally < totalNumberOfKeysServer -> {
+ totalNumberOfKeysLocally < totalNumberOfKeysServer -> {
// Server contains more keys than this device
true
}
@@ -327,7 +331,7 @@ internal class DefaultKeysBackupService @Inject constructor(
// TODO We have not found any algorithm to determine if a restore is recommended here. Return false for the moment
false
}
- else -> false
+ else -> false
}
}
@@ -339,8 +343,10 @@ internal class DefaultKeysBackupService @Inject constructor(
return cryptoStore.inboundGroupSessionsCount(true)
}
- override fun backupAllGroupSessions(progressListener: ProgressListener?,
- callback: MatrixCallback?) {
+ override fun backupAllGroupSessions(
+ progressListener: ProgressListener?,
+ callback: MatrixCallback?
+ ) {
if (!isEnabled() || backupOlmPkEncryption == null || keysBackupVersion == null) {
callback?.onFailure(Throwable("Backup not enabled"))
return
@@ -391,8 +397,10 @@ internal class DefaultKeysBackupService @Inject constructor(
})
}
- override fun getKeysBackupTrust(keysBackupVersion: KeysVersionResult,
- callback: MatrixCallback) {
+ override fun getKeysBackupTrust(
+ keysBackupVersion: KeysVersionResult,
+ callback: MatrixCallback
+ ) {
// TODO Validate with François that this is correct
object : Task {
override suspend fun execute(params: KeysVersionResult): KeysBackupVersionTrust {
@@ -499,9 +507,11 @@ internal class DefaultKeysBackupService @Inject constructor(
)
}
- override fun trustKeysBackupVersion(keysBackupVersion: KeysVersionResult,
- trust: Boolean,
- callback: MatrixCallback) {
+ override fun trustKeysBackupVersion(
+ keysBackupVersion: KeysVersionResult,
+ trust: Boolean,
+ callback: MatrixCallback
+ ) {
Timber.v("trustKeyBackupVersion: $trust, version ${keysBackupVersion.version}")
// Get auth data to update it
@@ -583,9 +593,11 @@ internal class DefaultKeysBackupService @Inject constructor(
}
}
- override fun trustKeysBackupVersionWithRecoveryKey(keysBackupVersion: KeysVersionResult,
- recoveryKey: String,
- callback: MatrixCallback) {
+ override fun trustKeysBackupVersionWithRecoveryKey(
+ keysBackupVersion: KeysVersionResult,
+ recoveryKey: String,
+ callback: MatrixCallback
+ ) {
Timber.v("trustKeysBackupVersionWithRecoveryKey: version ${keysBackupVersion.version}")
cryptoCoroutineScope.launch(coroutineDispatchers.io) {
@@ -602,9 +614,11 @@ internal class DefaultKeysBackupService @Inject constructor(
}
}
- override fun trustKeysBackupVersionWithPassphrase(keysBackupVersion: KeysVersionResult,
- password: String,
- callback: MatrixCallback) {
+ override fun trustKeysBackupVersionWithPassphrase(
+ keysBackupVersion: KeysVersionResult,
+ password: String,
+ callback: MatrixCallback
+ ) {
Timber.v("trustKeysBackupVersionWithPassphrase: version ${keysBackupVersion.version}")
cryptoCoroutineScope.launch(coroutineDispatchers.io) {
@@ -701,12 +715,14 @@ internal class DefaultKeysBackupService @Inject constructor(
progressListener.onProgress(backedUpKeys, total)
}
- override fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult,
- recoveryKey: String,
- roomId: String?,
- sessionId: String?,
- stepProgressListener: StepProgressListener?,
- callback: MatrixCallback) {
+ override fun restoreKeysWithRecoveryKey(
+ keysVersionResult: KeysVersionResult,
+ recoveryKey: String,
+ roomId: String?,
+ sessionId: String?,
+ stepProgressListener: StepProgressListener?,
+ callback: MatrixCallback
+ ) {
Timber.v("restoreKeysWithRecoveryKey: From backup version: ${keysVersionResult.version}")
cryptoCoroutineScope.launch(coroutineDispatchers.io) {
@@ -800,12 +816,14 @@ internal class DefaultKeysBackupService @Inject constructor(
}
}
- override fun restoreKeyBackupWithPassword(keysBackupVersion: KeysVersionResult,
- password: String,
- roomId: String?,
- sessionId: String?,
- stepProgressListener: StepProgressListener?,
- callback: MatrixCallback) {
+ override fun restoreKeyBackupWithPassword(
+ keysBackupVersion: KeysVersionResult,
+ password: String,
+ roomId: String?,
+ sessionId: String?,
+ stepProgressListener: StepProgressListener?,
+ callback: MatrixCallback
+ ) {
Timber.v("[MXKeyBackup] restoreKeyBackup with password: From backup version: ${keysBackupVersion.version}")
cryptoCoroutineScope.launch(coroutineDispatchers.io) {
@@ -853,9 +871,11 @@ internal class DefaultKeysBackupService @Inject constructor(
* Same method as [RoomKeysRestClient.getRoomKey] except that it accepts nullable
* parameters and always returns a KeysBackupData object through the Callback.
*/
- private suspend fun getKeys(sessionId: String?,
- roomId: String?,
- version: String): KeysBackupData {
+ private suspend fun getKeys(
+ sessionId: String?,
+ roomId: String?,
+ version: String
+ ): KeysBackupData {
return if (roomId != null && sessionId != null) {
// Get key for the room and for the session
val data = getRoomSessionDataTask.execute(GetRoomSessionDataTask.Params(roomId, sessionId, version))
@@ -909,7 +929,7 @@ internal class DefaultKeysBackupService @Inject constructor(
*/
fun maybeBackupKeys() {
when {
- isStuck() -> {
+ isStuck() -> {
// If not already done, or in error case, check for a valid backup version on the homeserver.
// If there is one, maybeBackupKeys will be called again.
checkAndStartKeysBackup()
@@ -927,14 +947,16 @@ internal class DefaultKeysBackupService @Inject constructor(
uiHandler.post { backupKeys() }
}
}
- else -> {
+ else -> {
Timber.v("maybeBackupKeys: Skip it because state: ${getState()}")
}
}
}
- override fun getVersion(version: String,
- callback: MatrixCallback