diff --git a/.editorconfig b/.editorconfig
index 140cc085c5..4640e50d15 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 = 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 = 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..f012900752 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
diff --git a/.github/workflows/post-pr.yml b/.github/workflows/post-pr.yml
index 8fe51eb8d5..49669e4201 100644
--- a/.github/workflows/post-pr.yml
+++ b/.github/workflows/post-pr.yml
@@ -29,200 +29,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
@@ -282,42 +88,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 a97d532644..014139d0ba 100644
--- a/.github/workflows/quality.yml
+++ b/.github/workflows/quality.yml
@@ -5,6 +5,11 @@ on:
push:
branches: [ main, develop ]
+# Enrich gradle.properties for CI/CD
+env:
+ CI_GRADLE_ARG_PROPERTIES: >
+ -Porg.gradle.jvmargs=-Xmx4g
+
jobs:
check:
name: Project Check Suite
@@ -97,6 +102,25 @@ jobs:
comment_id: ${{ steps.fc.outputs.comment-id }}
})
+# Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin
+ dependency-analysis:
+ name: Dependency analysis
+ runs-on: ubuntu-latest
+ # Allow all jobs on main and develop. Just one per PR.
+ concurrency:
+ group: ${{ github.ref == 'refs/heads/main' && format('dep-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('dep-develop-{0}', github.sha) || format('dep-{0}', github.ref) }}
+ cancel-in-progress: true
+ steps:
+ - uses: actions/checkout@v3
+ - name: Dependency analysis
+ run: ./gradlew buildHealth $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
+
# Lint for main module
android-lint:
name: Android Linter
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/tests.yml b/.github/workflows/tests.yml
index 3e8de8979c..5959fe9bb3 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -12,73 +12,98 @@ env:
-Porg.gradle.parallel=false
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@v3
+ 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
+ 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 theCodeCoverageReport --stacktrace $CI_GRADLE_ARG_PROPERTIES
+ - 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 theCodeCoverageReport --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..43e11edca5 100644
--- a/.github/workflows/triage-priority-bugs.yml
+++ b/.github/workflows/triage-priority-bugs.yml
@@ -15,9 +15,6 @@ jobs:
!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, 'T-Defect') &&
contains(github.event.issue.labels.*.name, 'S-Critical') &&
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
diff --git a/CHANGES.md b/CHANGES.md
index 4ff45e9c62..166453dfad 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,75 @@
+Changes in Element 1.4.19 (2022-06-07)
+======================================
+
+Bugfixes 🐛
+----------
+ - Fix | performance regression on roomlist + proper display of space parents in explore rooms. ([#6233](https://github.com/vector-im/element-android/issues/6233))
+
+
+Changes in Element v1.4.18 (2022-05-31)
+=======================================
+
+Features ✨
+----------
+ - Space explore screen changes: removed space card, added rooms filtering ([#5658](https://github.com/vector-im/element-android/issues/5658))
+ - Adds space or user id as a subtitle under rooms in search ([#5860](https://github.com/vector-im/element-android/issues/5860))
+ - Adds up navigation in spaces ([#6073](https://github.com/vector-im/element-android/issues/6073))
+ - Labs flag for enabling live location sharing ([#6098](https://github.com/vector-im/element-android/issues/6098))
+ - Added support for mandatory backup or passphrase from .well-known configuration. ([#6133](https://github.com/vector-im/element-android/issues/6133))
+ - Security - Asking for user confirmation when tapping URLs which contain unicode directional overrides ([#6163](https://github.com/vector-im/element-android/issues/6163))
+ - Add settings switch to allow autoplaying animated images ([#6166](https://github.com/vector-im/element-android/issues/6166))
+ - Live Location Sharing - User List Bottom Sheet ([#6170](https://github.com/vector-im/element-android/issues/6170))
+
+Bugfixes 🐛
+----------
+ - Fix some notifications not clearing when read ([#4862](https://github.com/vector-im/element-android/issues/4862))
+ - Do not switch away from home space on notification when "Show all Rooms in Home" is selected. ([#5827](https://github.com/vector-im/element-android/issues/5827))
+ - Use fixed text size in read receipt counter ([#5856](https://github.com/vector-im/element-android/issues/5856))
+ - Revert: Use member name instead of room name in DM creation item ([#6032](https://github.com/vector-im/element-android/issues/6032))
+ - Poll refactoring with unit tests ([#6074](https://github.com/vector-im/element-android/issues/6074))
+ - Correct .well-known/matrix/client handling for server_names which include ports. ([#6095](https://github.com/vector-im/element-android/issues/6095))
+ - Glide - Use current drawable while loading new static map image ([#6103](https://github.com/vector-im/element-android/issues/6103))
+ - Fix sending multiple invites to a room reaching only one or two people ([#6109](https://github.com/vector-im/element-android/issues/6109))
+ - Prevent widget web view from reloading on screen / orientation change ([#6140](https://github.com/vector-im/element-android/issues/6140))
+ - Fix decrypting redacted event from sending errors ([#6148](https://github.com/vector-im/element-android/issues/6148))
+ - Make widget web view request system permissions for camera and microphone (PSF-1061) ([#6149](https://github.com/vector-im/element-android/issues/6149))
+
+In development 🚧
+----------------
+ - Adds email input and verification screens to the new FTUE onboarding flow ([#5278](https://github.com/vector-im/element-android/issues/5278))
+ - FTUE - Adds the redesigned Sign In screen ([#5283](https://github.com/vector-im/element-android/issues/5283))
+ - [Live location sharing] Update message in timeline during the live ([#5689](https://github.com/vector-im/element-android/issues/5689))
+ - FTUE - Overrides sign up flow ordering for matrix.org only ([#5783](https://github.com/vector-im/element-android/issues/5783))
+ - Live location sharing: navigation from timeline to map screen
+ Live location sharing: show user pins on map screen ([#6012](https://github.com/vector-im/element-android/issues/6012))
+ - FTUE - Adds homeserver login/register deeplink support ([#6023](https://github.com/vector-im/element-android/issues/6023))
+ - [Live location sharing] Update entity in DB when a live is timed out ([#6123](https://github.com/vector-im/element-android/issues/6123))
+
+SDK API changes ⚠️
+------------------
+- Notifies other devices when a verification request sent from an Android device is accepted.` ([#5724](https://github.com/vector-im/element-android/issues/5724))
+- Some `val` have been changed to `fun` to increase their visibility in the generated documentation. Just add `()` if you were using them.
+- `KeysBackupService.state` has been replaced by `KeysBackupService.getState()`
+- `KeysBackupService.isStucked` has been replaced by `KeysBackupService.isStuck()`
+- SDK documentation improved ([#5952](https://github.com/vector-im/element-android/issues/5952))
+- Improve replay attacks and reduce duplicate message index errors ([#6077](https://github.com/vector-im/element-android/issues/6077))
+- Remove `RoomSummaryQueryParams.roomId`. If you need to observe a single room, use the new API `RoomService.getRoomSummaryLive(roomId: String)`
+- `ActiveSpaceFilter` has been renamed to `SpaceFilter`
+- `RoomCategoryFilter.ALL` has been removed, just pass `null` to not filter on Room category. ([#6143](https://github.com/vector-im/element-android/issues/6143))
+
+Other changes
+-------------
+ - leaving space experience changed to be aligned with iOS ([#5728](https://github.com/vector-im/element-android/issues/5728))
+ - @Ignore a number of tests that are currently failing in CI. ([#6025](https://github.com/vector-im/element-android/issues/6025))
+ - Remove ShortcutBadger lib and usage (it was dead code) ([#6041](https://github.com/vector-im/element-android/issues/6041))
+ - Test: Ensure calling 'fail()' is not caught by the catch block ([#6089](https://github.com/vector-im/element-android/issues/6089))
+ - Excludes transitive optional non FOSS google location dependency from fdroid builds ([#6100](https://github.com/vector-im/element-android/issues/6100))
+ - Fixed grammar errors in /vector/src/main/res/values/strings.xml ([#6132](https://github.com/vector-im/element-android/issues/6132))
+ - Downgrade gradle from 7.2.0 to 7.1.3 ([#6141](https://github.com/vector-im/element-android/issues/6141))
+ - Add Lao language to the in-app settings. ([#6196](https://github.com/vector-im/element-android/issues/6196))
+ - Remove the background location permission request ([#6198](https://github.com/vector-im/element-android/issues/6198))
+
+
Changes in Element v1.4.16 (2022-05-17)
=======================================
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 25ff8b91c0..22d6f5f5ef 100644
--- a/build.gradle
+++ b/build.gradle
@@ -41,6 +41,9 @@ plugins {
id "org.jlleitschuh.gradle.ktlint" version "10.3.0"
// Detekt
id "io.gitlab.arturbosch.detekt" version "1.20.0"
+
+ // Dependency Analysis
+ id 'com.autonomousapps.dependency-analysis' version "1.5.0"
}
// https://github.com/jeremylong/DependencyCheck
@@ -177,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"
@@ -188,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/theCodeCoverageReport/theCodeCoverageReport.xml"
property "sonar.login", project.hasProperty("SONAR_LOGIN") ? SONAR_LOGIN : "invalid"
}
}
@@ -219,3 +222,61 @@ project(":library:diff-match-patch") {
// }
// }
//}
+
+dependencyAnalysis {
+ dependencies {
+ bundle("kotlin-stdlib") {
+ includeGroup("org.jetbrains.kotlin")
+ }
+ bundle("react") {
+ includeGroup("com.facebook.react")
+ }
+ }
+ issues {
+ all {
+ ignoreKtx(true)
+ onUsedTransitiveDependencies {
+ // Transitively used dependencies that should be declared directly
+ severity("ignore")
+ }
+ onUnusedDependencies {
+ severity("fail")
+ }
+ onUnusedAnnotationProcessors {
+ severity("fail")
+ exclude("com.airbnb.android:epoxy-processor", "com.google.dagger:hilt-compiler") // False positives
+ }
+ }
+ project(":library:jsonviewer") {
+ onUnusedDependencies {
+ 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(":matrix-sdk-android") {
+ onUnusedDependencies {
+ exclude("io.reactivex.rxjava2:rxkotlin") // Transitively required for mocking realm as monarchy doesn't expose Rx
+ }
+ }
+ project(":matrix-sdk-android-flow") {
+ onUnusedDependencies {
+ exclude("androidx.paging:paging-runtime-ktx") // False positive
+ }
+ }
+ project(":vector") {
+ onUnusedDependencies {
+ // False positives
+ exclude(
+ "com.vanniktech:emoji-google",
+ "com.vanniktech:emoji-material",
+ "org.maplibre.gl:android-plugin-annotation-v9",
+ "org.maplibre.gl:android-sdk",
+ )
+ }
+ }
+ }
+}
diff --git a/changelog.d/5278.wip b/changelog.d/5278.wip
deleted file mode 100644
index c6014dc9ac..0000000000
--- a/changelog.d/5278.wip
+++ /dev/null
@@ -1 +0,0 @@
-Adds email input and verification screens to the new FTUE onboarding flow
diff --git a/changelog.d/5285.wip b/changelog.d/5285.wip
new file mode 100644
index 0000000000..1dd68597be
--- /dev/null
+++ b/changelog.d/5285.wip
@@ -0,0 +1 @@
+FTUE - Adds Sign Up tracking
diff --git a/changelog.d/5528.bugfix b/changelog.d/5528.bugfix
new file mode 100644
index 0000000000..b0dc759ab0
--- /dev/null
+++ b/changelog.d/5528.bugfix
@@ -0,0 +1 @@
+Fix cases of missing, swapped, or duplicated messages
diff --git a/changelog.d/5658.feature b/changelog.d/5658.feature
deleted file mode 100644
index ba41a03207..0000000000
--- a/changelog.d/5658.feature
+++ /dev/null
@@ -1 +0,0 @@
-Space explore screen changes: removed space card, added rooms filtering
diff --git a/changelog.d/5689.wip b/changelog.d/5689.wip
deleted file mode 100644
index ccea1ec541..0000000000
--- a/changelog.d/5689.wip
+++ /dev/null
@@ -1 +0,0 @@
-[Live location sharing] Update message in timeline during the live
diff --git a/changelog.d/5724.sdk b/changelog.d/5724.sdk
deleted file mode 100644
index 5a0a37fe31..0000000000
--- a/changelog.d/5724.sdk
+++ /dev/null
@@ -1 +0,0 @@
-- Notifies other devices when a verification request sent from an Android device is accepted.`
diff --git a/changelog.d/5728.misc b/changelog.d/5728.misc
deleted file mode 100644
index 6e463fa76f..0000000000
--- a/changelog.d/5728.misc
+++ /dev/null
@@ -1 +0,0 @@
-leaving space experience changed to be aligned with iOS
diff --git a/changelog.d/5970.feature b/changelog.d/5970.feature
new file mode 100644
index 0000000000..b65decdd2d
--- /dev/null
+++ b/changelog.d/5970.feature
@@ -0,0 +1 @@
+Make read receipt avatar list more compact
diff --git a/changelog.d/6017.misc b/changelog.d/6017.misc
new file mode 100644
index 0000000000..2597f2d796
--- /dev/null
+++ b/changelog.d/6017.misc
@@ -0,0 +1 @@
+Adds support for parsing homeserver versions without a patch number
diff --git a/changelog.d/6025.misc b/changelog.d/6025.misc
deleted file mode 100644
index 2900796792..0000000000
--- a/changelog.d/6025.misc
+++ /dev/null
@@ -1 +0,0 @@
-@Ignore a number of tests that are currently failing in CI.
diff --git a/changelog.d/6029.sdk b/changelog.d/6029.sdk
new file mode 100644
index 0000000000..b39d1a6359
--- /dev/null
+++ b/changelog.d/6029.sdk
@@ -0,0 +1,5 @@
+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
diff --git a/changelog.d/6032.bugfix b/changelog.d/6032.bugfix
deleted file mode 100644
index c20d7ddd08..0000000000
--- a/changelog.d/6032.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Revert: Use member name instead of room name in DM creation item
diff --git a/changelog.d/6041.misc b/changelog.d/6041.misc
deleted file mode 100644
index 50378ea3fd..0000000000
--- a/changelog.d/6041.misc
+++ /dev/null
@@ -1 +0,0 @@
-Remove ShortcutBadger lib and usage (it was dead code)
diff --git a/changelog.d/6074.bugfix b/changelog.d/6074.bugfix
deleted file mode 100644
index 692dce28d7..0000000000
--- a/changelog.d/6074.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Poll refactoring with unit tests
diff --git a/changelog.d/6089.misc b/changelog.d/6089.misc
deleted file mode 100644
index 19b951c1a3..0000000000
--- a/changelog.d/6089.misc
+++ /dev/null
@@ -1 +0,0 @@
-Test: Ensure calling 'fail()' is not caught by the catch block
diff --git a/changelog.d/6093.sdk b/changelog.d/6093.sdk
new file mode 100644
index 0000000000..8ac5e41b61
--- /dev/null
+++ b/changelog.d/6093.sdk
@@ -0,0 +1 @@
+Allowing AuthenticationService.getLoginFlow to fail without resetting state from previously successful calls
diff --git a/changelog.d/6095.bugfix b/changelog.d/6095.bugfix
deleted file mode 100644
index 11110bfa08..0000000000
--- a/changelog.d/6095.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Correct .well-known/matrix/client handling for server_names which include ports.
diff --git a/changelog.d/6098.feature b/changelog.d/6098.feature
deleted file mode 100644
index 659da42094..0000000000
--- a/changelog.d/6098.feature
+++ /dev/null
@@ -1 +0,0 @@
-Labs flag for enabling live location sharing
diff --git a/changelog.d/6103.bugfix b/changelog.d/6103.bugfix
deleted file mode 100644
index 12e6836460..0000000000
--- a/changelog.d/6103.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Glide - Use current drawable while loading new static map image
diff --git a/changelog.d/6109.bugfix b/changelog.d/6109.bugfix
deleted file mode 100644
index 43b1d610c7..0000000000
--- a/changelog.d/6109.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Fix sending multiple invites to a room reaching only one or two people
diff --git a/changelog.d/6146.feature b/changelog.d/6146.feature
new file mode 100644
index 0000000000..9d1e117ddb
--- /dev/null
+++ b/changelog.d/6146.feature
@@ -0,0 +1 @@
+Allow .well-known configuration to override key sharing mode
diff --git a/changelog.d/6169.sdk b/changelog.d/6169.sdk
new file mode 100644
index 0000000000..dfee158c3f
--- /dev/null
+++ b/changelog.d/6169.sdk
@@ -0,0 +1 @@
+Allows new passwords to be passed at the point of confirmation when resetting a password
diff --git a/changelog.d/6209.bugfix b/changelog.d/6209.bugfix
new file mode 100644
index 0000000000..3eac2c9df6
--- /dev/null
+++ b/changelog.d/6209.bugfix
@@ -0,0 +1 @@
+Fix wrong status of live location sharing in timeline
diff --git a/changelog.d/6222.bugfix b/changelog.d/6222.bugfix
new file mode 100644
index 0000000000..ef430ee024
--- /dev/null
+++ b/changelog.d/6222.bugfix
@@ -0,0 +1 @@
+Fix StackOverflowError while recording voice message
diff --git a/changelog.d/6232.bugfix b/changelog.d/6232.bugfix
new file mode 100644
index 0000000000..df04655701
--- /dev/null
+++ b/changelog.d/6232.bugfix
@@ -0,0 +1 @@
+Text cropped: "Secure backup"
diff --git a/changelog.d/6244.feature b/changelog.d/6244.feature
new file mode 100644
index 0000000000..9b02187112
--- /dev/null
+++ b/changelog.d/6244.feature
@@ -0,0 +1 @@
+Re-organize location settings flags
diff --git a/coverage.gradle b/coverage.gradle
index b62ce0b4a0..fb2352f47f 100644
--- a/coverage.gradle
+++ b/coverage.gradle
@@ -2,7 +2,10 @@ def excludes = [ ]
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/outputs/unit_test_code_coverage/**/*.exec",
+ "**/build/outputs/code_coverage/**/coverage.ec"
+ ) }
report.reports {
xml.enabled true
@@ -18,11 +21,13 @@ def initializeReport(report, projects, classExcludes) {
switch (project) {
case { project.plugins.hasPlugin("com.android.application") }:
androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/gplayDebug")
+ androidSourceDirs.add("${project.buildDir}/generated/source/kapt/gplayDebug")
androidSourceDirs.add("${project.projectDir}/src/main/kotlin")
androidSourceDirs.add("${project.projectDir}/src/main/java")
break
case { project.plugins.hasPlugin("com.android.library") }:
androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/debug")
+ androidSourceDirs.add("${project.buildDir}/generated/source/kapt/debug")
androidSourceDirs.add("${project.projectDir}/src/main/kotlin")
androidSourceDirs.add("${project.projectDir}/src/main/java")
break
@@ -43,13 +48,17 @@ def collectProjects(predicate) {
return subprojects.findAll { it.buildFile.isFile() && predicate(it) }
}
-task allCodeCoverageReport(type: JacocoReport) {
+task theCodeCoverageReport(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 }
+ tasks.withType(Test) {
+ jacoco.includeNoLocationClasses = true
+ }
+ def projects = collectProjects { ['vector','matrix-sdk-android'].contains(it.name) }
+ dependsOn {
+ [':matrix-sdk-android:testDebugUnitTest'] +
+ [':vector:testGplayDebugUnitTest'] +
+ [':matrix-sdk-android:connectedDebugAndroidTest']
+ }
initializeReport(it, projects, excludes)
}
diff --git a/dependencies.gradle b/dependencies.gradle
index 10f9539e5a..451ad4449b 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -7,10 +7,13 @@ ext.versions = [
'targetCompat' : JavaVersion.VERSION_11,
]
-def gradle = "7.2.0"
+
+// Pinned to 7.1.3 because of https://github.com/vector-im/element-android/issues/6142
+// Please test carefully before upgrading again.
+def gradle = "7.1.3"
// Ref: https://kotlinlang.org/releases.html
def kotlin = "1.6.21"
-def kotlinCoroutines = "1.6.1"
+def kotlinCoroutines = "1.6.2"
def dagger = "2.42"
def retrofit = "2.9.0"
def arrow = "0.8.2"
@@ -23,7 +26,7 @@ def mavericks = "2.6.1"
def glide = "4.13.2"
def bigImageViewer = "1.8.1"
def jjwt = "0.11.5"
-def vanniktechEmoji = "0.9.0"
+def vanniktechEmoji = "0.15.0"
// Testing
def mockk = "1.12.4"
@@ -45,12 +48,13 @@ ext.libs = [
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
],
androidx : [
- 'appCompat' : "androidx.appcompat:appcompat:1.4.1",
- 'core' : "androidx.core:core-ktx:1.7.0",
+ 'activity' : "androidx.activity:activity:1.4.0",
+ 'appCompat' : "androidx.appcompat:appcompat:1.4.2",
+ '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",
- 'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.3",
+ 'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.4",
'work' : "androidx.work:work-runtime-ktx:2.7.1",
'autoFill' : "androidx.autofill:autofill:1.1.0",
'preferenceKtx' : "androidx.preference:preference-ktx:1.2.0",
@@ -69,10 +73,12 @@ ext.libs = [
'testRules' : "androidx.test:rules:$androidxTest",
'espressoCore' : "androidx.test.espresso:espresso-core:$espresso",
'espressoContrib' : "androidx.test.espresso:espresso-contrib:$espresso",
- 'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso"
+ 'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso",
+ 'viewpager2' : "androidx.viewpager2:viewpager2:1.0.0",
+ '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",
@@ -81,7 +87,7 @@ ext.libs = [
'hiltCompiler' : "com.google.dagger:hilt-compiler:$dagger"
],
squareup : [
- 'moshi' : "com.squareup.moshi:moshi-adapters:$moshi",
+ 'moshi' : "com.squareup.moshi:moshi:$moshi",
'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi",
'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit",
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
@@ -107,6 +113,10 @@ ext.libs = [
'mavericks' : "com.airbnb.android:mavericks:$mavericks",
'mavericksTesting' : "com.airbnb.android:mavericks-testing:$mavericks"
],
+ maplibre : [
+ 'androidSdk' : "org.maplibre.gl:android-sdk:9.5.2",
+ 'pluginAnnotation' : "org.maplibre.gl:android-plugin-annotation-v9:1.0.0"
+ ],
mockk : [
'mockk' : "io.mockk:mockk:$mockk",
'mockkAndroid' : "io.mockk:mockk-android:$mockk"
diff --git a/docs/add_threePids.md b/docs/add_threePids.md
index 6fb0aff426..8d02702ca6 100644
--- a/docs/add_threePids.md
+++ b/docs/add_threePids.md
@@ -1,5 +1,34 @@
# Adding and removing ThreePids to an account
+
+
+* [Add email](#add-email)
+ * [User enter the email](#user-enter-the-email)
+ * [The email is already added to an account](#the-email-is-already-added-to-an-account)
+ * [The email is free](#the-email-is-free)
+* [User receives an e-mail](#user-receives-an-e-mail)
+ * [User clicks on the link](#user-clicks-on-the-link)
+ * [User returns on Element](#user-returns-on-element)
+ * [User enters his password](#user-enters-his-password)
+ * [The link has not been clicked](#the-link-has-not-been-clicked)
+ * [Wrong password](#wrong-password)
+ * [The link has been clicked and the account password is correct](#the-link-has-been-clicked-and-the-account-password-is-correct)
+* [Remove email](#remove-email)
+ * [User want to remove an email from his account](#user-want-to-remove-an-email-from-his-account)
+ * [Email was not bound to an identity server](#email-was-not-bound-to-an-identity-server)
+ * [Email was bound to an identity server](#email-was-bound-to-an-identity-server)
+* [Add phone number](#add-phone-number)
+ * [The phone number is already added to an account](#the-phone-number-is-already-added-to-an-account)
+ * [The phone number is free](#the-phone-number-is-free)
+* [User receive a text message](#user-receive-a-text-message)
+ * [User enter the code to the app](#user-enter-the-code-to-the-app)
+ * [Wrong code](#wrong-code)
+ * [Correct code](#correct-code)
+* [Remove phone number](#remove-phone-number)
+ * [User wants to remove a phone number from his account](#user-wants-to-remove-a-phone-number-from-his-account)
+
+
+
## Add email
### User enter the email
diff --git a/docs/analytics.md b/docs/analytics.md
index 135ace81b0..9b2c176912 100644
--- a/docs/analytics.md
+++ b/docs/analytics.md
@@ -1,5 +1,13 @@
# Analytics in Element
+
+
+* [Solution](#solution)
+* [How to add a new Event](#how-to-add-a-new-event)
+* [Forks of Element](#forks-of-element)
+
+
+
## Solution
Element is using PostHog to send analytics event.
diff --git a/docs/color_migration_guide.md b/docs/color_migration_guide.md
index 31a531d124..f83a88e2b2 100644
--- a/docs/color_migration_guide.md
+++ b/docs/color_migration_guide.md
@@ -1,5 +1,14 @@
# Color migration
+
+
+ * [Changes](#changes)
+ * [Main change for developers](#main-change-for-developers)
+ * [Remaining work](#remaining-work)
+ * [Migration guide](#migration-guide)
+
+
+
### Changes
- use colors defined in https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=557%3A0
diff --git a/docs/design.md b/docs/design.md
index a79f19cf3e..f390725560 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -1,5 +1,31 @@
# Element Android design
+
+
+* [Introduction](#introduction)
+* [How to import from Figma to the Element Android project](#how-to-import-from-figma-to-the-element-android-project)
+ * [Colors](#colors)
+ * [Text](#text)
+ * [Dimension, position and margin](#dimension-position-and-margin)
+ * [Icons](#icons)
+ * [Export drawable from Figma](#export-drawable-from-figma)
+ * [Import in Android Studio](#import-in-android-studio)
+ * [Images](#images)
+* [Figma links](#figma-links)
+ * [Coumpound](#coumpound)
+ * [Login](#login)
+ * [Login v2](#login-v2)
+ * [Room list](#room-list)
+ * [Timeline](#timeline)
+ * [Voice message](#voice-message)
+ * [Room settings](#room-settings)
+ * [VoIP](#voip)
+ * [Presence](#presence)
+ * [Spaces](#spaces)
+ * [List to be continued...](#list-to-be-continued)
+
+
+
## Introduction
Design at element.io is done using Figma - https://www.figma.com
diff --git a/docs/identity_server.md b/docs/identity_server.md
index e765ae3949..a1ee86cb19 100644
--- a/docs/identity_server.md
+++ b/docs/identity_server.md
@@ -1,5 +1,19 @@
# Identity server
+
+
+* [Introduction](#introduction)
+* [Implementation](#implementation)
+* [Related MSCs](#related-mscs)
+* [Steps and requirements](#steps-and-requirements)
+* [Screens](#screens)
+ * [Settings](#settings)
+ * [Discovery screen](#discovery-screen)
+ * [Set identity server screen](#set-identity-server-screen)
+* [Ref:](#ref:)
+
+
+
Issue: #607
PR: #1354
diff --git a/docs/integration_tests.md b/docs/integration_tests.md
index e79f966d1f..b5a830e7ff 100644
--- a/docs/integration_tests.md
+++ b/docs/integration_tests.md
@@ -1,5 +1,18 @@
# Integration tests
+
+
+* [Pre requirements](#pre-requirements)
+* [Install and run Synapse](#install-and-run-synapse)
+* [Run the test](#run-the-test)
+* [Stop Synapse](#stop-synapse)
+* [Troubleshoot](#troubleshoot)
+ * [Android Emulator does cannot reach the homeserver](#android-emulator-does-cannot-reach-the-homeserver)
+ * [Tests partially run but some fail with "Unable to contact localhost:8080"](#tests-partially-run-but-some-fail-with-"unable-to-contact-localhost:8080")
+ * [virtualenv command fails](#virtualenv-command-fails)
+
+
+
Integration tests are useful to ensure that the code works well for any use cases.
They can also be used as sample on how to use the Matrix SDK.
diff --git a/docs/jitsi.md b/docs/jitsi.md
index 1b4e0a37b4..4dd06effdb 100644
--- a/docs/jitsi.md
+++ b/docs/jitsi.md
@@ -1,20 +1,32 @@
# Jitsi in Element Android
+
+
+* [Native Jitsi SDK](#native-jitsi-sdk)
+ * [How to build the Jitsi Meet SDK](#how-to-build-the-jitsi-meet-sdk)
+ * [Jitsi version](#jitsi-version)
+ * [Run the build script](#run-the-build-script)
+ * [Link with the new generated library](#link-with-the-new-generated-library)
+ * [Sanity tests](#sanity-tests)
+ * [Export the build library](#export-the-build-library)
+
+
+
Native Jitsi support has been added to Element Android by the PR [#1914](https://github.com/vector-im/element-android/pull/1914). The description of the PR contains some documentation about the behaviour in each possible room configuration.
Also, ensure to have a look on [the documentation from Element Web](https://github.com/vector-im/element-web/blob/develop/docs/jitsi.md)
The official documentation about how to integrate the Jitsi SDK in an Android app is available here: https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk.
-# Native Jitsi SDK
+## Native Jitsi SDK
The Jitsi SDK is built by ourselves with the flag LIBRE_BUILD, to be able to be integrated on the F-Droid version of Element Android.
The generated maven repository is then host in the project https://github.com/vector-im/jitsi_libre_maven
-## How to build the Jitsi Meet SDK
+### How to build the Jitsi Meet SDK
-### Jitsi version
+#### Jitsi version
Update the script `./tools/jitsi/build_jisti_libs.sh` with the tag of the project `https://github.com/jitsi/jitsi-meet`.
@@ -22,7 +34,7 @@ Latest tag can be found from this page: https://github.com/jitsi/jitsi-meet-rele
Currently we are building the version with the tag `android-sdk-3.10.0`.
-### Run the build script
+#### Run the build script
At the root of the Element Android, run the following script:
@@ -32,7 +44,7 @@ At the root of the Element Android, run the following script:
It will build the Jitsi Meet Android library and put every generated files in the folder `/tmp/jitsi`
-### Link with the new generated library
+#### Link with the new generated library
- Update the file `./build.gradle` to use the previously created local Maven repository. Currently we have this line:
@@ -57,7 +69,7 @@ implementation('com.facebook.react:react-native-webrtc:1.92.1-jitsi-9093212@aar'
- Perform a gradle sync and build the project
- Perform test
-### Sanity tests
+#### Sanity tests
In order to validate that the upgrade of the Jitsi and WebRTC dependency does not break anything, the following sanity tests have to be performed, using two devices:
- Make 1-1 audio call (so using WebRTC)
@@ -65,7 +77,7 @@ In order to validate that the upgrade of the Jitsi and WebRTC dependency does no
- Create and join a conference call with audio only (so using Jitsi library). Leave the conference. Join it again.
- Create and join a conference call with audio and video (so using Jitsi library) Leave the conference. Join it again.
-### Export the build library
+#### Export the build library
If all the tests are passed, you can export the generated Jitsi library to our Maven repository.
@@ -81,4 +93,4 @@ url "https://github.com/vector-im/jitsi_libre_maven/raw/master/android-sdk-3.10.
- Build the project and perform the sanity tests again.
-- Update the file `/CHANGES.md` to notify about the library upgrade, and create a regular PR for project Element Android.
\ No newline at end of file
+- Update the file `/CHANGES.md` to notify about the library upgrade, and create a regular PR for project Element Android.
diff --git a/docs/notifications.md b/docs/notifications.md
index b44984785a..612b8785b8 100644
--- a/docs/notifications.md
+++ b/docs/notifications.md
@@ -1,37 +1,42 @@
This document aims to describe how Element android displays notifications to the end user. It also clarifies notifications and background settings in the app.
# Table of Contents
-1. [Prerequisites Knowledge](#prerequisites-knowledge)
- * [How does a matrix client get a message from a homeserver?](#how-does-a-matrix-client-get-a-message-from-a-homeserver)
- * [How does a mobile app receives push notification?](#how-does-a-mobile-app-receives-push-notification)
- * [Push VS Notification](#push-vs-notification)
- * [Push in the matrix federated world](#push-in-the-matrix-federated-world)
- * [How does the homeserver know when to notify a client?](#how-does-the-homeserver-know-when-to-notify-a-client)
- * [Push vs privacy, and mitigation](#push-vs-privacy-and-mitigation)
- * [Background processing limitations](#background-processing-limitations)
-2. [Element Notification implementations](#element-notification-implementations)
- * [Requirements](#requirements)
- * [Foreground sync mode (Gplay & F-Droid)](#foreground-sync-mode-gplay-f-droid)
- * [Push (FCM) received in background](#push-fcm-received-in-background)
- * [FCM Fallback mode](#fcm-fallback-mode)
- * [F-Droid background Mode](#f-droid-background-mode)
-3. [Application Settings](#application-settings)
+
+
+
+* [Prerequisites Knowledge](#prerequisites-knowledge)
+ * [How does a matrix client get a message from a homeserver?](#how-does-a-matrix-client-get-a-message-from-a-homeserver?)
+ * [How does a mobile app receives push notification](#how-does-a-mobile-app-receives-push-notification)
+ * [Push VS Notification](#push-vs-notification)
+ * [Push in the matrix federated world](#push-in-the-matrix-federated-world)
+ * [How does the homeserver know when to notify a client?](#how-does-the-homeserver-know-when-to-notify-a-client?)
+ * [Push vs privacy, and mitigation](#push-vs-privacy-and-mitigation)
+ * [Background processing limitations](#background-processing-limitations)
+* [Element Notification implementations](#element-notification-implementations)
+ * [Requirements](#requirements)
+ * [Foreground sync mode (Gplay and F-Droid)](#foreground-sync-mode-gplay-and-f-droid)
+ * [Push (FCM) received in background](#push-fcm-received-in-background)
+ * [FCM Fallback mode](#fcm-fallback-mode)
+ * [F-Droid background Mode](#f-droid-background-mode)
+* [Application Settings](#application-settings)
+
+
First let's start with some prerequisite knowledge
-# Prerequisites Knowledge
+## Prerequisites Knowledge
-## How does a matrix client get a message from a homeserver?
+### How does a matrix client get a message from a homeserver?
In order to get messages from a homeserver, a matrix client need to perform a ``sync`` operation.
`To read events, the intended flow of operation is for clients to first call the /sync API without a since parameter. This returns the most recent message events for each room, as well as the state of the room at the start of the returned timeline. `
-The client need to call the `sync`API periodically in order to get incremental updates of the server state (new messages).
+The client need to call the `sync` API periodically in order to get incremental updates of the server state (new messages).
This mechanism is known as **HTTP long Polling**.
-Using the **HTTP Long Polling** mechanism a client polls a server requesting new information.
+Using the **HTTP Long Polling** mechanism a client polls a server requesting new information.
The server *holds the request open until new data is available*.
Once available, the server responds and sends the new information.
When the client receives the new information, it immediately sends another request, and the operation is repeated.
@@ -52,7 +57,7 @@ By default, this is 0, so the server will return immediately even if the respons
When the Element Android app is open (i.e in foreground state), the default timeout is 30 seconds, and delay is 0.
-## How does a mobile app receives push notification
+### How does a mobile app receives push notification
Push notification is used as a way to wake up a mobile application when some important information is available and should be processed.
@@ -66,22 +71,22 @@ FCM will only work on android devices that have Google plays services installed
(In simple terms, Google Play Services is a background service that runs on Android, which in turn helps in integrating Google’s advanced functionalities to other applications)
De-Googlified devices need to rely on something else in order to stay up to date with a server.
-There some cases when devices with google services cannot use FCM (network infrastructure limitations -firewalls- ,
- privacy and or independency requirement, source code licence)
+There some cases when devices with google services cannot use FCM (network infrastructure limitations -firewalls-,
+ privacy and or independence requirement, source code licence)
-## Push VS Notification
+### Push VS Notification
This need some disambiguation, because it is the source of common confusion:
-*The fact that you see a notification on your screen does not mean that you have successfully configured your PUSH plateform.*
+*The fact that you see a notification on your screen does not mean that you have successfully configured your PUSH platform.*
Technically there is a difference between a push and a notification. A notification is what you see on screen and/or in the notification Menu/Drawer (in the top bar of the phone).
Notifications are not always triggered by a push (One can display a notification locally triggered by an alarm)
-## Push in the matrix federated world
+### Push in the matrix federated world
In order to send a push to a mobile, App developers need to have a server that will use the FCM APIs, and these APIs requires authentication!
This server is called a **Push Gateway** in the matrix world
@@ -118,11 +123,11 @@ Client/Server API + | | | | |
```
Recommended reading:
- * https://thomask.sdf.org/blog/2016/12/11/riots-magical-push-notifications-in-ios.html
+* https://thomask.sdf.org/blog/2016/12/11/riots-magical-push-notifications-in-ios.html
* https://matrix.org/docs/spec/client_server/r0.4.0.html#id128
-## How does the homeserver know when to notify a client?
+### How does the homeserver know when to notify a client?
This is defined by [**push rules**](https://matrix.org/docs/spec/client_server/r0.4.0.html#push-rules-).
@@ -140,14 +145,14 @@ Of course, content patterns matching cannot be used for encrypted messages serve
That is why clients are able to **process the push rules client side** to decide what kind of notification should be presented for a given event.
-## Push vs privacy, and mitigation
+### Push vs privacy, and mitigation
As seen previously, App developers don't directly send a push to the end user's device, they use a Push Provider as intermediary. So technically this intermediary is able to read the content of what is sent.
App developers usually mitigate this by sending a `silent notification`, that is a notification with no identifiable data, or with an encrypted payload. When the push is received the app can then synchronise to it's server in order to generate a local notification.
-## Background processing limitations
+### Background processing limitations
A mobile applications process live in a managed word, meaning that its process can be limited (e.g no network access), stopped or killed at almost anytime by the Operating System.
@@ -167,15 +172,15 @@ The documentation on this subject is vague, and as per our experiments not alway
It is getting more and more complex to have reliable notifications when FCM is not used.
-# Element Notification implementations
+## Element Notification implementations
-## Requirements
+### Requirements
Element Android must work with and without FCM.
* The Element android app published on F-Droid do not rely on FCM (all related dependencies are not present)
* The Element android app published on google play rely on FCM, with a fallback mode when FCM registration has failed (e.g outdated or missing Google Play Services)
-## Foreground sync mode (Gplay & F-Droid)
+### Foreground sync mode (Gplay and F-Droid)
When in foreground, Element performs sync continuously with a timeout value set to 10 seconds (see HttpPooling).
@@ -183,9 +188,9 @@ As this mode does not need to live beyond the scope of the application, and as p
This mode is turned on when the app enters foreground, and off when enters background.
-In background, and depending on wether push is available or not, Element will use different methods to perform the syncs (Workers / Alarms / Service)
+In background, and depending on whether push is available or not, Element will use different methods to perform the syncs (Workers / Alarms / Service)
-## Push (FCM) received in background
+### Push (FCM) received in background
In order to enable Push, Element must first get a push token from the firebase SDK, then register a pusher with this token on the homeserver.
@@ -225,10 +230,10 @@ Upon reception of the FCM push, Element will perform a sync call to the homeserv
Element implements several strategies in these cases (TODO document)
-## FCM Fallback mode
+### FCM Fallback mode
It is possible that Element is not able to get a FCM push token.
-Common errors (amoung several others) that can cause that:
+Common errors (among several others) that can cause that:
* Google Play Services is outdated
* Google Play Service fails in someways with FCM servers (infamous `SERVICE_NOT_AVAILABLE`)
@@ -246,7 +251,7 @@ Usually in this mode, what happen is when you take back your phone in your hand,
The fallback mode is supposed to be a temporary state waiting for the user to fix issues for FCM, or for App Developers that has done a fork to correctly configure their FCM settings.
-## F-Droid background Mode
+### F-Droid background Mode
The F-Droid Element flavor has no dependencies to FCM, therefore cannot relies on Push.
@@ -256,7 +261,7 @@ Only solution left is to use `AlarmManager`, that offers new API to allow launch
Notice that these alarms, due to their potential impact on battery life, can still be restricted by the system. Documentation says that they will not be triggered more than every minutes under normal system operation, and when in low power mode about every 15 mn.
-These restrictions can be relaxed by requirering the app to be white listed from battery optimization.
+These restrictions can be relaxed by requiring the app to be white listed from battery optimization.
F-Droid version will schedule alarms that will then trigger a Broadcast Receiver, that in turn will launch a Service (in the classic android way), and the reschedule an alarm for next time.
@@ -266,9 +271,7 @@ That is why on Element F-Droid, the broadcast receiver will acquire a temporary
Note that foreground services require to put a notification informing the user that the app is doing something even if not launched).
-
-
-# Application Settings
+## Application Settings
**Notifications > Enable notifications for this account**
diff --git a/docs/pull_request.md b/docs/pull_request.md
index 94f8f3b6d8..d2d2bb7a3b 100644
--- a/docs/pull_request.md
+++ b/docs/pull_request.md
@@ -1,5 +1,43 @@
# Pull requests
+
+
+* [Introduction](#introduction)
+* [Who should read this document?](#who-should-read-this-document?)
+* [Submitting PR](#submitting-pr)
+ * [Who can submit pull requests?](#who-can-submit-pull-requests?)
+ * [Humans](#humans)
+ * [Draft PR?](#draft-pr?)
+ * [Base branch](#base-branch)
+ * [PR Review Assignment](#pr-review-assignment)
+ * [PR review time](#pr-review-time)
+ * [Re-request PR review](#re-request-pr-review)
+ * [When create split PR?](#when-create-split-pr?)
+ * [Avoid fixing other unrelated issue in a big PR](#avoid-fixing-other-unrelated-issue-in-a-big-pr)
+ * [Bots](#bots)
+ * [Dependabot](#dependabot)
+ * [Gradle wrapper](#gradle-wrapper)
+ * [Sync analytics plan](#sync-analytics-plan)
+* [Reviewing PR](#reviewing-pr)
+ * [Who can review pull requests?](#who-can-review-pull-requests?)
+ * [What to have in mind when reviewing a PR](#what-to-have-in-mind-when-reviewing-a-pr)
+ * [Rules](#rules)
+ * [Check the form](#check-the-form)
+ * [PR title](#pr-title)
+ * [PR description](#pr-description)
+ * [File change](#file-change)
+ * [Check the commit](#check-the-commit)
+ * [Check the substance](#check-the-substance)
+ * [Make a dedicated meeting to review the PR](#make-a-dedicated-meeting-to-review-the-pr)
+ * [What happen to the issue(s)?](#what-happen-to-the-issues?)
+ * [Merge conflict](#merge-conflict)
+ * [When and who can merge PR](#when-and-who-can-merge-pr)
+ * [Merge type](#merge-type)
+ * [Resolve conversation](#resolve-conversation)
+* [Responsibility](#responsibility)
+
+
+
## Introduction
This document gives some clue about how to efficiently manage Pull Requests (PR). This document is a first draft and may be improved later.
diff --git a/docs/signin.md b/docs/signin.md
index 0a234d2a20..65e305389f 100644
--- a/docs/signin.md
+++ b/docs/signin.md
@@ -2,6 +2,27 @@
This document describes the flow of signin to a homeserver, and also the flow when user want to reset his password. Examples come from the `matrix.org` homeserver.
+
+
+* [Sign in flows](#sign-in-flows)
+ * [Get the flow](#get-the-flow)
+ * [Login with username](#login-with-username)
+ * [Incorrect password](#incorrect-password)
+ * [Correct password:](#correct-password:)
+ * [Login with email](#login-with-email)
+ * [Unknown email](#unknown-email)
+ * [Known email, wrong password](#known-email-wrong-password)
+ * [Known email, correct password](#known-email-correct-password)
+ * [Login with Msisdn](#login-with-msisdn)
+ * [Login with SSO](#login-with-sso)
+* [Reset password](#reset-password)
+ * [Send email](#send-email)
+ * [When the email is not known](#when-the-email-is-not-known)
+ * [When the email is known](#when-the-email-is-known)
+ * [User clicks on the link](#user-clicks-on-the-link)
+
+
+
## Sign in flows
### Get the flow
@@ -322,4 +343,4 @@ curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":
{}
```
-The password has been changed, and all the existing token are invalidated. User can now login with the new password.
\ No newline at end of file
+The password has been changed, and all the existing token are invalidated. User can now login with the new password.
diff --git a/docs/signup.md b/docs/signup.md
index 97cd20a423..0b01338965 100644
--- a/docs/signup.md
+++ b/docs/signup.md
@@ -4,6 +4,20 @@ This document describes the flow of registration to a homeserver. Examples come
*Ref*: https://matrix.org/docs/spec/client_server/latest#account-registration-and-management
+
+
+* [Sign up flows](#sign-up-flows)
+ * [First step](#first-step)
+ * [Step 1: entering user name and password](#step-1:-entering-user-name-and-password)
+ * [If username already exists](#if-username-already-exists)
+ * [Step 2: entering email](#step-2:-entering-email)
+ * [Step 2 bis: user enters an email](#step-2-bis:-user-enters-an-email)
+ * [Step 3: Accepting T&C](#step-3:-accepting-t&c)
+ * [Step 4: Captcha](#step-4:-captcha)
+ * [Step 5: MSISDN](#step-5:-msisdn)
+
+
+
## Sign up flows
### First step
diff --git a/docs/ui-tests.md b/docs/ui-tests.md
index 667a6ed7fb..d0b9db6818 100644
--- a/docs/ui-tests.md
+++ b/docs/ui-tests.md
@@ -10,6 +10,20 @@ Currently the test are covering a small set of application flows:
- Self verification via emoji
- Self verification via passphrase
+
+
+* [Prerequisites:](#prerequisites:)
+* [Run the tests](#run-the-tests)
+ * [From the source code](#from-the-source-code)
+ * [From command line](#from-command-line)
+* [Recipes](#recipes)
+ * [Wait for initial sync](#wait-for-initial-sync)
+ * [Accessing current activity](#accessing-current-activity)
+ * [Interact with other session](#interact-with-other-session)
+ * [Contributing to the UiAllScreensSanityTest](#contributing-to-the-uiallscreenssanitytest)
+
+
+
## Prerequisites:
Out of the box, the tests use one of the homeservers (located at http://localhost:8080) of the "Demo Federation of Homeservers" (https://github.com/matrix-org/synapse#running-a-demo-federation-of-synapses).
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104140.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104140.txt
new file mode 100644
index 0000000000..d369efa9f2
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Zlepšení správy ignorovaných uživatelů. 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/40104180.txt b/fastlane/metadata/android/en-US/changelogs/40104180.txt
new file mode 100644
index 0000000000..61db61727a
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40104180.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/40104190.txt b/fastlane/metadata/android/en-US/changelogs/40104190.txt
new file mode 100644
index 0000000000..61db61727a
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40104190.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/es-ES/changelogs/40104140.txt b/fastlane/metadata/android/es-ES/changelogs/40104140.txt
new file mode 100644
index 0000000000..595cd6b3d4
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+Cambios principales en esta versión: Mejoras en la administración de usuarios ignorados. Varias correciones de bugs y mejoras en la estabilidad.
+Registro de cambios: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/et/changelogs/40104140.txt b/fastlane/metadata/android/et/changelogs/40104140.txt
new file mode 100644
index 0000000000..9000616f38
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: eiratud kasutajate parem haldus ning 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/40104140.txt b/fastlane/metadata/android/fa/changelogs/40104140.txt
new file mode 100644
index 0000000000..cf5d7bc6ac
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+تغییرات عمده در این نگارش: مدیریت بهبودیافتهٔ کاربران چشمپوشیده. رفع اشکالهای مختلف و بهبودهای پایداری.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104100.txt b/fastlane/metadata/android/fr-FR/changelogs/40104100.txt
new file mode 100644
index 0000000000..f2453c5539
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40104100.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Défilement dans les messages vocaux. 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/40104110.txt b/fastlane/metadata/android/fr-FR/changelogs/40104110.txt
new file mode 100644
index 0000000000..fe61fd021c
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40104110.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/40104120.txt b/fastlane/metadata/android/fr-FR/changelogs/40104120.txt
new file mode 100644
index 0000000000..accd82fe72
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40104120.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Les utilisateurs peuvent apparaître hors-ligne. Ajout d’un lecteur pour les pièces jointes audio
+Intégralité des changements : https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104130.txt b/fastlane/metadata/android/fr-FR/changelogs/40104130.txt
new file mode 100644
index 0000000000..accd82fe72
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40104130.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Les utilisateurs peuvent apparaître hors-ligne. Ajout d’un lecteur pour les pièces jointes audio
+Intégralité des changements : https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104140.txt b/fastlane/metadata/android/fr-FR/changelogs/40104140.txt
new file mode 100644
index 0000000000..087d5bc1c8
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Amélioration de la gestion des utilisateurs ignoré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/id/changelogs/40104140.txt b/fastlane/metadata/android/id/changelogs/40104140.txt
new file mode 100644
index 0000000000..174e8dcded
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Tingkatkan pengelolaan pengguna yang diabaikan. Beberapa perbaikan kutu dan stabilitas.
+Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/it-IT/changelogs/40104140.txt b/fastlane/metadata/android/it-IT/changelogs/40104140.txt
new file mode 100644
index 0000000000..ae367e72d0
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: migliorata la gestione degli utenti ignorati. Varie correzioni e miglioramenti della stabilità.
+Cronologia completa: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/lo-LA/changelogs/40104140.txt b/fastlane/metadata/android/lo-LA/changelogs/40104140.txt
new file mode 100644
index 0000000000..e8c8d84031
--- /dev/null
+++ b/fastlane/metadata/android/lo-LA/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+ການປ່ຽນແປງຫຼັກໃນສະບັບນີ້: ປັບປຸງການບໍລິຫານການລະເວັ້ນຜູ້ໃຊ້. ປັບປຸງບັກ ແລະຄວາມສະຖຽນ.
+ບັນທຶກການປ່ຽນແປງສະບັບເຕັມ: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101120.txt b/fastlane/metadata/android/pl-PL/changelogs/40101120.txt
new file mode 100644
index 0000000000..6a62f1c6a9
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40101120.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: aktualizacja motywu i stylu oraz naprawa awarii po rozmowie wideo
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.12
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101130.txt b/fastlane/metadata/android/pl-PL/changelogs/40101130.txt
new file mode 100644
index 0000000000..ec8d488eb8
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40101130.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: głównie aktualizacja stabilności i poprawki błędów.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.13
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101140.txt b/fastlane/metadata/android/pl-PL/changelogs/40101140.txt
new file mode 100644
index 0000000000..c4c102da4a
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40101140.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: naprawienie problemu z zaszyfrowanymi wiadomościami.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.14
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101150.txt b/fastlane/metadata/android/pl-PL/changelogs/40101150.txt
new file mode 100644
index 0000000000..2eb1a3f018
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40101150.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: implementacja wiadomości głosowych w ustawieniach laboratorium.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.15
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40101160.txt b/fastlane/metadata/android/pl-PL/changelogs/40101160.txt
new file mode 100644
index 0000000000..682da8be76
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Naprawiono błąd podczas wysyłania zaszyfrowanej wiadomości, jeśli ktoś w pokoju się wyloguje.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40102000.txt b/fastlane/metadata/android/pl-PL/changelogs/40102000.txt
new file mode 100644
index 0000000000..cdae0a4ba7
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Wiadomość głosowa jest domyślnie włączona.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40102010.txt b/fastlane/metadata/android/pl-PL/changelogs/40102010.txt
new file mode 100644
index 0000000000..0a825e8672
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Wiele ulepszeń w VoIP i Przestrzeniach (nadal w wersji beta).
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103000.txt b/fastlane/metadata/android/pl-PL/changelogs/40103000.txt
new file mode 100644
index 0000000000..8b408ced72
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Organizuj swoje pokoje za pomocą Przestrzeni!
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103010.txt b/fastlane/metadata/android/pl-PL/changelogs/40103010.txt
new file mode 100644
index 0000000000..0a49e7fa68
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Organizuj swoje pokoje za pomocą Przestrzeni! Wersja 1.3.1 naprawia awarię, która może wystąpić w wersji 1.3.0.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103020.txt b/fastlane/metadata/android/pl-PL/changelogs/40103020.txt
new file mode 100644
index 0000000000..3e37f64b76
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Dodano obsługę Android Auto. Wiele poprawek błędów!
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103030.txt b/fastlane/metadata/android/pl-PL/changelogs/40103030.txt
new file mode 100644
index 0000000000..8f80d95b5a
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Uwidocznij politykę(-i) serwera tożsamości w ustawieniach. Tymczasowo usunięto obsługę Androida Auto.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103040.txt b/fastlane/metadata/android/pl-PL/changelogs/40103040.txt
new file mode 100644
index 0000000000..13458a7b2d
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Dodanie obsługi obecności, dla pokoju wiadomości bezpośrednich (uwaga: obecność jest wyłączona na matrix.org). Dodano ponownie obsługę Androida Auto.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/pl-PL/changelogs/40104140.txt b/fastlane/metadata/android/pl-PL/changelogs/40104140.txt
new file mode 100644
index 0000000000..84ab57a2ac
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+Główne zmiany w tej wersji: Poprawa zarządzania ignorowanymi użytkownikami. Różne poprawki błędów i ulepszenia stabilności.
+Pełna lista zmian: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104140.txt b/fastlane/metadata/android/pt-BR/changelogs/40104140.txt
new file mode 100644
index 0000000000..ed1a53c910
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Melhorar gerenciamento de usuárias(os) ignoradas(os). 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/40104140.txt b/fastlane/metadata/android/sk/changelogs/40104140.txt
new file mode 100644
index 0000000000..e1c85961a4
--- /dev/null
+++ b/fastlane/metadata/android/sk/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+Hlavné zmeny v tejto verzii: Zlepšenie správy ignorovaných používateľov. 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/40104140.txt b/fastlane/metadata/android/sv-SE/changelogs/40104140.txt
new file mode 100644
index 0000000000..9b58878dfb
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Förbättra hantering av ignorerade användare. Diverse buggfixar och stabilitetsförbättringar.
+Full ändringslogg: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/ta-IN/changelogs/40104140.txt b/fastlane/metadata/android/ta-IN/changelogs/40104140.txt
new file mode 100644
index 0000000000..f3196b57b6
--- /dev/null
+++ b/fastlane/metadata/android/ta-IN/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+இந்த பதிப்பில் உள்ள முதன்மை மாற்றங்கள்: தவிர்க்கப்பட்ட பயனர்களின் மேலாண்மை மேம்படுத்தப்பட்டுள்ளது. வெவ்வேறு வழுக்களைச் சரிசெய்தல் மற்றும் நிலைப்புத்தன்மையை மேம்படுத்தல்.
+முழு மாற்ற அறிக்கை: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/ta-IN/full_description.txt b/fastlane/metadata/android/ta-IN/full_description.txt
new file mode 100644
index 0000000000..9aa693bda2
--- /dev/null
+++ b/fastlane/metadata/android/ta-IN/full_description.txt
@@ -0,0 +1,42 @@
+Element is both a secure messenger and a productivity team collaboration app that is ideal for group chats while remote working. This chat app uses end-to-end encryption to provide powerful video conferencing, file sharing and voice calls.
+
+Element இன் தனிச்சிறப்புகளுள் சில:
+- மேம்பட்ட இயங்கலை தொடர்பு கருவிகள்
+- தொலைநிலையில் உள்ள ஊழியர்களுக்கும், பாதுகாப்பான நிறும கருத்து பரிமாற்றங்களை அனுமதிப்பதற்காக, முழுவதுமாக மறைகுறியாக்கப்பட்ட செய்திகள்
+- MATRIX திறந்த மூல கட்டமைப்பை அடிப்படையாக கொண்டு செயல்படும் அதிகாரப்பரவலாக்கப்பட்ட அரட்டை
+- செயல்திட்டங்களை மேலாண்மை செய்யும் போது, மறைகுறியாக்கப்பட்ட தரவுடன் கூடிய பாதுகாப்பான கோப்பு பகிரல்
+- IP மூலம் குரல் (VoIP) மற்றும் திரை பகிரல் உடன் கூடிய குரல் அரட்டைகள்
+- உங்கள் மனம் கவர்ந்த இயங்கலை உடனிணைவு கருவிகள், செயல்திட்ட மேலாண்மை கருவிகள், VoIP சேவைகள் மற்றும் இதர குழு தூதுரை செயலிகள் உடன் கூடிய எளிமையான ஒருமைப்பாடு
+
+Element is completely different from other messaging and collaboration apps. It operates on Matrix, an open network for secure messaging and decentralized communication. It allows self-hosting to give users maximum ownership and control of their data and messages.
+
+தனியுரிமை மற்றும் மறைகுறியாக்கப்பட்ட செய்தி அனுப்பல்
+தேவையில்லாத விளம்பரங்கள், தரவு சுரண்டல் மற்றும் தகவல் கட்டுப்பாடு போன்றவற்றில் இருந்து Element உங்களை பாதுகாக்கிறது. மேலும், இது முனைக்கு-முனை மறைகுறியாக்கம் மற்றும் குறுக்கு-ஒப்பமிடப்பட்ட சாதன சரிபார்ப்பு ஆகியவற்றின் மூலம் உங்கள் எல்லா தரவுகள், ஒன்றுக்கொன்றான காணொளி மற்றும் குரல் அழைப்புகளை பாதுகாக்கிறது.
+
+Element gives you control over your privacy while allowing you to communicate securely with யாரோனும் ஒருவருடன் on the Matrix network, or other business collaboration tools by integrating with apps such as Slack.
+
+Element can be self-hosted
+To allow more control of your sensitive data and conversations, Element can be self-hosted or you can choose any Matrix-based host - the standard for open source, decentralized communication. Element gives you privacy, security compliance and integration flexibility.
+
+உங்கள் தரவைச் சொந்தமாக்கிக் கொள்ளுங்கள்
+தரவுகள் மற்றும் செய்திகளை எங்கு சேமித்து வைக்க வேண்டும் என்பதை நீங்கள் முடிவு செய்கிறீர்கள். இதன்மூலம், தரவு சுரண்டல் மற்றும் மூன்றாம் தரப்பினர் அனுகல் ஆகிய இடர்களை தவிர்க்கலாம்.
+
+Element வெவ்வேறு வகையில் கட்டுப்பாட்டை உங்களிடம் அளிக்கிறது:
+1. Get a free account on the matrix.org public server hosted by the Matrix developers, or choose from thousands of public servers hosted by volunteers
+2. Self-host your account by running a server on your own IT infrastructure
+3. Sign up for an account on a custom server by simply subscribing to the Element Matrix Services hosting platform
+
+திறந்த செய்தி அனுப்பல் மற்றும் ஒருமைப்பாடு
+You can chat with anyone on the Matrix network, whether they’re using Element, another Matrix app or even if they are using a different messaging app.
+
+மிகவும் பாதுகாப்பானது
+உண்மையான முனைக்கு-முனை மறைகுறியாக்கம் (உரையாடலில் உள்ளவர்கள் மட்டுமே மறைகுறியாக்கத்தை நீக்கி செய்தியை காண இயலும்) மற்றும் குறுக்கு-ஒப்பமிடப்பட்ட சாதன சரிபார்ப்பு.
+
+முழுமையான தொடர்பு மற்றும் ஒருமைப்பாடு
+செய்தி அனுப்பல், காணொளி மற்றும் குரல் அழைப்புகளை, கோப்பு பகிரல், திரை பகிரல் மற்றும் ஒருமைப்பாடுகள், இயலிகள் மற்றும் நிரல் பலகைகளின் மொத்த கொத்து. அறைகள், குழுக்களை உருவாக்கி, அவர்களுடன் உரையாடி, வேலையை எளிமையாக்கவும்.
+
+எங்கு விட்டு சென்றீர்களோ அதிலிருந்த துவங்கவும்
+Stay in touch wherever you are with fully synchronised message history across all your devices and on the web at https://app.element.io
+
+திறந்த மூலம்
+Element Android ஒரு திறந்த மூல செயல் திட்டமாகும். இது GitHub இல் தொகுத்து வழங்கப்பட்டுள்ளது. வழுக்கள் ஏதேனும் கண்டறிந்தால் மற்றும்/அல்லது இதன் வளர்ச்சிக்கு பங்களிக்க விரும்பினால், https://github.com/vector-im/element-android என்னும் தளத்திற்கு வருகை தரவும்.
diff --git a/fastlane/metadata/android/ta-IN/short_description.txt b/fastlane/metadata/android/ta-IN/short_description.txt
new file mode 100644
index 0000000000..9c7afb2a37
--- /dev/null
+++ b/fastlane/metadata/android/ta-IN/short_description.txt
@@ -0,0 +1 @@
+மறைகுறியாக்கப்பட்ட செய்தி அனுப்பல், குழு அரட்டை மற்றும் காணொளி அழைப்புகள்
diff --git a/fastlane/metadata/android/ta-IN/title.txt b/fastlane/metadata/android/ta-IN/title.txt
new file mode 100644
index 0000000000..ecb9a01c06
--- /dev/null
+++ b/fastlane/metadata/android/ta-IN/title.txt
@@ -0,0 +1 @@
+Element - பாதுகாப்பான தூதுரை சேவை
diff --git a/fastlane/metadata/android/uk/changelogs/40104140.txt b/fastlane/metadata/android/uk/changelogs/40104140.txt
new file mode 100644
index 0000000000..293ad117e4
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+Основні зміни у цій версії: Удосконалено керування нехтуваними користувачами. Різні виправлення помилок та поліпшення стабільності.
+Вичерпний журнал змін: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104140.txt b/fastlane/metadata/android/zh-TW/changelogs/40104140.txt
new file mode 100644
index 0000000000..ff830dab7c
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40104140.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:改善被忽略使用者的管理。多個臭蟲修復與穩定性改善。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases
diff --git a/library/attachment-viewer/build.gradle b/library/attachment-viewer/build.gradle
index 048710f62c..8bbafd3387 100644
--- a/library/attachment-viewer/build.gradle
+++ b/library/attachment-viewer/build.gradle
@@ -55,5 +55,6 @@ dependencies {
implementation libs.androidx.appCompat
implementation libs.androidx.recyclerview
- implementation libs.google.material
-}
\ No newline at end of file
+ api libs.androidx.viewpager2
+ implementation libs.androidx.transition
+}
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..85d7c13398 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
}
}
diff --git a/library/core-utils/build.gradle b/library/core-utils/build.gradle
index d3afd8d29b..0f7789a2a8 100644
--- a/library/core-utils/build.gradle
+++ b/library/core-utils/build.gradle
@@ -50,6 +50,5 @@ android {
}
dependencies {
- implementation libs.androidx.appCompat
implementation libs.jetbrains.coroutinesAndroid
}
diff --git a/library/jsonviewer/build.gradle b/library/jsonviewer/build.gradle
index 2110747feb..e1a3b0c9ee 100644
--- a/library/jsonviewer/build.gradle
+++ b/library/jsonviewer/build.gradle
@@ -52,6 +52,7 @@ dependencies {
implementation libs.androidx.appCompat
implementation libs.androidx.core
+ implementation libs.androidx.recyclerview
implementation libs.airbnb.epoxy
kapt libs.airbnb.epoxyProcessor
@@ -60,7 +61,6 @@ dependencies {
// Span utils
implementation 'me.gujun.android:span:1.7'
- implementation libs.google.material
implementation libs.jetbrains.coroutinesCore
implementation libs.jetbrains.coroutinesAndroid
diff --git a/library/multipicker/build.gradle b/library/multipicker/build.gradle
index bb98a2f852..2de99d5c20 100644
--- a/library/multipicker/build.gradle
+++ b/library/multipicker/build.gradle
@@ -38,9 +38,9 @@ android {
}
dependencies {
- implementation libs.androidx.appCompat
- implementation libs.androidx.fragmentKtx
+ api libs.androidx.activity
implementation libs.androidx.exifinterface
+ implementation libs.androidx.core
// Log
implementation libs.jakewharton.timber
diff --git a/library/ui-styles/build.gradle b/library/ui-styles/build.gradle
index 0ac513b252..31cfdd24c7 100644
--- a/library/ui-styles/build.gradle
+++ b/library/ui-styles/build.gradle
@@ -60,4 +60,4 @@ dependencies {
implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta12'
// dialpad dimen
implementation 'im.dlg:android-dialer:1.2.5'
-}
\ No newline at end of file
+}
diff --git a/library/ui-styles/src/main/res/drawable/bg_pin_key.xml b/library/ui-styles/src/main/res/drawable/bg_pin_key.xml
index d4a54577be..5bf293aab0 100644
--- a/library/ui-styles/src/main/res/drawable/bg_pin_key.xml
+++ b/library/ui-styles/src/main/res/drawable/bg_pin_key.xml
@@ -10,4 +10,4 @@
android:height="70dp" />
-
\ No newline at end of file
+
diff --git a/library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml b/library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml
index 1827a7682b..879cac15ca 100644
--- a/library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml
+++ b/library/ui-styles/src/main/res/drawable/pin_code_dot_empty.xml
@@ -10,4 +10,4 @@
-
\ No newline at end of file
+
diff --git a/library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml b/library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml
index 799ea30174..83bdac5126 100644
--- a/library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml
+++ b/library/ui-styles/src/main/res/drawable/pin_code_dot_fill.xml
@@ -9,4 +9,4 @@
-
\ No newline at end of file
+
diff --git a/library/ui-styles/src/main/res/drawable/pin_code_dots.xml b/library/ui-styles/src/main/res/drawable/pin_code_dots.xml
index 29e445e511..c4b1073f85 100644
--- a/library/ui-styles/src/main/res/drawable/pin_code_dots.xml
+++ b/library/ui-styles/src/main/res/drawable/pin_code_dots.xml
@@ -6,4 +6,4 @@
android:drawable="@drawable/pin_code_dot_fill"/>
-
\ 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 7571265241..9d9fc862f6 100644
--- a/library/ui-styles/src/main/res/values/styles_location.xml
+++ b/library/ui-styles/src/main/res/values/styles_location.xml
@@ -18,4 +18,26 @@
- 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 2b6c113359..cb22863694 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
@@ -41,4 +41,4 @@
- ?vctr_content_primary
-
\ No newline at end of file
+
diff --git a/library/ui-styles/src/main/res/values/styles_timeline.xml b/library/ui-styles/src/main/res/values/styles_timeline.xml
index c86eeb8efb..20c375c2d6 100644
--- a/library/ui-styles/src/main/res/values/styles_timeline.xml
+++ b/library/ui-styles/src/main/res/values/styles_timeline.xml
@@ -1,5 +1,5 @@
-
+
+
-
\ No newline at end of file
+
diff --git a/matrix-sdk-android-flow/build.gradle b/matrix-sdk-android-flow/build.gradle
index ea43ce20c8..fb69af2d82 100644
--- a/matrix-sdk-android-flow/build.gradle
+++ b/matrix-sdk-android-flow/build.gradle
@@ -31,9 +31,7 @@ android {
}
dependencies {
-
implementation project(":matrix-sdk-android")
- implementation libs.androidx.appCompat
implementation libs.jetbrains.coroutinesCore
implementation libs.jetbrains.coroutinesAndroid
@@ -41,7 +39,4 @@ dependencies {
// Paging
implementation libs.androidx.pagingRuntimeKtx
-
- // Logging
- implementation libs.jakewharton.timber
}
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 9f260858f6..1086928dc6 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
@@ -45,6 +45,13 @@ import org.matrix.android.sdk.api.util.toOptional
class FlowSession(private val session: Session) {
+ fun liveRoomSummary(roomId: String): Flow> {
+ return session.roomService().getRoomSummaryLive(roomId).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.roomService().getRoomSummary(roomId).toOptional()
+ }
+ }
+
fun liveRoomSummaries(queryParams: RoomSummaryQueryParams, sortOrder: RoomSortOrder = RoomSortOrder.NONE): Flow> {
return session.roomService().getRoomSummariesLive(queryParams, sortOrder).asFlow()
.startWith(session.coroutineDispatchers.io) {
@@ -81,7 +88,7 @@ class FlowSession(private val session: Session) {
}
fun liveSyncState(): Flow {
- return session.getSyncStateLive().asFlow()
+ return session.syncService().getSyncStateLive().asFlow()
}
fun livePushers(): Flow> {
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index 33798d1357..ec376effbe 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -56,7 +56,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
- buildConfigField "String", "SDK_VERSION", "\"1.4.18\""
+ buildConfigField "String", "SDK_VERSION", "\"1.4.20\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
@@ -74,6 +74,7 @@ android {
buildTypes {
debug {
+ testCoverageEnabled true
// 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
@@ -136,7 +137,6 @@ dependencies {
implementation libs.jetbrains.coroutinesCore
implementation libs.jetbrains.coroutinesAndroid
- implementation libs.androidx.appCompat
implementation libs.androidx.core
// Lifecycle
@@ -155,12 +155,11 @@ dependencies {
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.3"))
implementation 'com.squareup.okhttp3:okhttp'
implementation 'com.squareup.okhttp3:logging-interceptor'
- implementation 'com.squareup.okhttp3:okhttp-urlconnection'
implementation libs.squareup.moshi
kapt libs.squareup.moshiKotlin
- implementation libs.markwon.core
+ api "com.atlassian.commonmark:commonmark:0.13.0"
// Image
implementation libs.androidx.exifinterface
@@ -176,12 +175,8 @@ dependencies {
// Work
implementation libs.androidx.work
- // FP
- implementation libs.arrow.core
- implementation libs.arrow.instances
-
// 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
@@ -198,11 +193,9 @@ dependencies {
implementation libs.apache.commonsImaging
// Phone number https://github.com/google/libphonenumber
- implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.48'
+ implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.49'
testImplementation libs.tests.junit
- testImplementation 'org.robolectric:robolectric:4.7.3'
- //testImplementation 'org.robolectric:shadows-support-v4:3.0'
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
testImplementation libs.mockk.mockk
testImplementation libs.tests.kluent
diff --git a/matrix-sdk-android/docs/packages.md b/matrix-sdk-android/docs/packages.md
index ae7bee1b4e..19f7c15a7a 100644
--- a/matrix-sdk-android/docs/packages.md
+++ b/matrix-sdk-android/docs/packages.md
@@ -1,3 +1,7 @@
+# Package org.matrix.android.sdk.userstories
+
+This package contains some user stories (**Us** prefix) of the SDK usage. You will find example of what it is possible to do with the SDK and the API which can be used to do it.
+
# Package org.matrix.android.sdk.api
This is the root package of the API exposed by this SDK.
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/account/AccountCreationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/AccountCreationTest.kt
index 486bc02769..7e4fc4768f 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/AccountCreationTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/AccountCreationTest.kt
@@ -24,8 +24,8 @@ 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.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
@@ -34,32 +34,22 @@ import org.matrix.android.sdk.common.TestConstants
@LargeTest
class AccountCreationTest : InstrumentedTest {
- private val commonTestHelper = CommonTestHelper(context())
- private val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
-
@Test
- fun createAccountTest() {
- val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
-
- commonTestHelper.signOutAndClose(session)
+ fun createAccountTest() = runSessionTest(context()) { commonTestHelper ->
+ commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
}
@Test
@Ignore("This test will be ignored until it is fixed")
- fun createAccountAndLoginAgainTest() {
+ fun createAccountAndLoginAgainTest() = runSessionTest(context()) { commonTestHelper ->
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
// Log again to the same account
- val session2 = commonTestHelper.logIntoAccount(session.myUserId, SessionTestParams(withInitialSync = true))
-
- commonTestHelper.signOutAndClose(session)
- commonTestHelper.signOutAndClose(session2)
+ commonTestHelper.logIntoAccount(session.myUserId, SessionTestParams(withInitialSync = true))
}
@Test
- fun simpleE2eTest() {
- val res = cryptoTestHelper.doE2ETestWithAliceInARoom()
-
- res.cleanUp(commonTestHelper)
+ fun simpleE2eTest() = runCryptoTest(context()) { cryptoTestHelper, _ ->
+ cryptoTestHelper.doE2ETestWithAliceInARoom()
}
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt
index 6d740c5a34..260e8dbe05 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt
@@ -25,7 +25,7 @@ import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.failure.isInvalidPassword
-import org.matrix.android.sdk.common.CommonTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
@@ -34,14 +34,12 @@ import org.matrix.android.sdk.common.TestConstants
@Ignore("This test will be ignored until it is fixed")
class ChangePasswordTest : InstrumentedTest {
- private val commonTestHelper = CommonTestHelper(context())
-
companion object {
private const val NEW_PASSWORD = "this is a new password"
}
@Test
- fun changePasswordTest() {
+ fun changePasswordTest() = runSessionTest(context()) { commonTestHelper ->
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false))
// Change password
@@ -54,9 +52,6 @@ class ChangePasswordTest : InstrumentedTest {
throwable.isInvalidPassword().shouldBeTrue()
// Try to login with the new password, should work
- val session2 = commonTestHelper.logIntoAccount(session.myUserId, NEW_PASSWORD, SessionTestParams(withInitialSync = false))
-
- commonTestHelper.signOutAndClose(session)
- commonTestHelper.signOutAndClose(session2)
+ commonTestHelper.logIntoAccount(session.myUserId, NEW_PASSWORD, SessionTestParams(withInitialSync = false))
}
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt
index d2dfe4d945..0b21f85742 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt
@@ -29,7 +29,7 @@ import org.matrix.android.sdk.api.auth.UserPasswordAuth
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.MatrixError
-import org.matrix.android.sdk.common.CommonTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
import kotlin.coroutines.Continuation
@@ -39,10 +39,8 @@ import kotlin.coroutines.resume
@FixMethodOrder(MethodSorters.JVM)
class DeactivateAccountTest : InstrumentedTest {
- private val commonTestHelper = CommonTestHelper(context())
-
@Test
- fun deactivateAccountTest() {
+ fun deactivateAccountTest() = runSessionTest(context(), false /* session will be deactivated */) { commonTestHelper ->
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
// Deactivate the account
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/network/ApiInterceptorTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/network/ApiInterceptorTest.kt
index 9371154aaf..8dbff82015 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/network/ApiInterceptorTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/network/ApiInterceptorTest.kt
@@ -23,7 +23,7 @@ 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.common.CommonTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
import timber.log.Timber
@@ -32,10 +32,8 @@ import timber.log.Timber
@FixMethodOrder(MethodSorters.JVM)
class ApiInterceptorTest : InstrumentedTest {
- private val commonTestHelper = CommonTestHelper(context())
-
@Test
- fun apiInterceptorTest() {
+ fun apiInterceptorTest() = runSessionTest(context()) { commonTestHelper ->
val responses = mutableListOf()
val listener = object : ApiInterceptorListener {
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 96ea99d92f..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
@@ -54,12 +54,39 @@ import java.util.concurrent.TimeUnit
* This class exposes methods to be used in common cases
* Registration, login, Sync, Sending messages...
*/
-class CommonTestHelper(context: Context) {
+class CommonTestHelper private constructor(context: Context) {
+
+ companion object {
+ internal fun runSessionTest(context: Context, autoSignoutOnClose: Boolean = true, block: (CommonTestHelper) -> Unit) {
+ val testHelper = CommonTestHelper(context)
+ return try {
+ block(testHelper)
+ } finally {
+ if (autoSignoutOnClose) {
+ testHelper.cleanUpOpenedSessions()
+ }
+ }
+ }
+
+ internal fun runCryptoTest(context: Context, autoSignoutOnClose: Boolean = true, block: (CryptoTestHelper, CommonTestHelper) -> Unit) {
+ val testHelper = CommonTestHelper(context)
+ val cryptoTestHelper = CryptoTestHelper(testHelper)
+ return try {
+ block(cryptoTestHelper, testHelper)
+ } finally {
+ if (autoSignoutOnClose) {
+ testHelper.cleanUpOpenedSessions()
+ }
+ }
+ }
+ }
internal val matrix: TestMatrix
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
private var accountNumber = 0
+ private val trackedSessions = mutableListOf()
+
fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor
init {
@@ -84,6 +111,15 @@ class CommonTestHelper(context: Context) {
return logIntoAccount(userId, TestConstants.PASSWORD, testParams)
}
+ fun cleanUpOpenedSessions() {
+ trackedSessions.forEach {
+ runBlockingTest {
+ it.signOutService().signOut(true)
+ }
+ }
+ trackedSessions.clear()
+ }
+
/**
* Create a homeserver configuration, with Http connection allowed for test
*/
@@ -101,11 +137,11 @@ class CommonTestHelper(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)
}
@@ -124,10 +160,10 @@ class CommonTestHelper(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()
@@ -135,7 +171,7 @@ class CommonTestHelper(context: Context) {
}
}
syncLiveData.observeForever(syncObserver)
- session.startSync(true)
+ session.syncService().startSync(true)
}
}
@@ -216,7 +252,8 @@ class CommonTestHelper(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)
@@ -236,16 +273,20 @@ class CommonTestHelper(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,
testParams
)
assertNotNull(session)
- return session
+ return session.also {
+ trackedSessions.add(session)
+ }
}
/**
@@ -256,12 +297,16 @@ class CommonTestHelper(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
+ return session.also {
+ trackedSessions.add(session)
+ }
}
/**
@@ -271,9 +316,11 @@ class CommonTestHelper(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 {
@@ -309,9 +356,11 @@ class CommonTestHelper(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 {
@@ -337,8 +386,10 @@ class CommonTestHelper(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 {
@@ -379,8 +430,8 @@ class CommonTestHelper(context: Context) {
*/
fun await(latch: CountDownLatch, timeout: Long? = TestConstants.timeOutMillis) {
assertTrue(
- "Timed out after " + timeout + "ms waiting for something to happen. See stacktrace for cause.",
- latch.await(timeout ?: TestConstants.timeOutMillis, TimeUnit.MILLISECONDS)
+ "Timed out after " + timeout + "ms waiting for something to happen. See stacktrace for cause.",
+ latch.await(timeout ?: TestConstants.timeOutMillis, TimeUnit.MILLISECONDS)
)
}
@@ -436,6 +487,7 @@ class CommonTestHelper(context: Context) {
fun Iterable.signOutAndClose() = forEach { signOutAndClose(it) }
fun signOutAndClose(session: Session) {
+ trackedSessions.remove(session)
runBlockingTest(timeout = 60_000) {
session.signOutService().signOut(true)
}
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/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt
index 348841313b..5fd86d4fdb 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt
@@ -58,7 +58,7 @@ import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner
-import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService
+import org.matrix.android.sdk.api.session.securestorage.KeyRef
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.api.util.awaitCallback
import org.matrix.android.sdk.api.util.toBase64NoPadding
@@ -66,7 +66,7 @@ import java.util.UUID
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
-class CryptoTestHelper(private val testHelper: CommonTestHelper) {
+class CryptoTestHelper(val testHelper: CommonTestHelper) {
private val messagesFromAlice: List = listOf("0 - Hello I'm Alice!", "4 - Go!")
private val messagesFromBob: List = listOf("1 - Hello I'm Bob!", "2 - Isn't life grand?", "3 - Let's go to the opera.")
@@ -361,19 +361,19 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
ssssService.storeSecret(
MASTER_KEY_SSSS_NAME,
session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.master!!,
- listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec))
+ listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec))
)
ssssService.storeSecret(
SELF_SIGNING_KEY_SSSS_NAME,
session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.selfSigned!!,
- listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec))
+ listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec))
)
ssssService.storeSecret(
USER_SIGNING_KEY_SSSS_NAME,
session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.user!!,
- listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec))
+ listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec))
)
// set up megolm backup
@@ -390,7 +390,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
ssssService.storeSecret(
KEYBACKUP_SECRET_SSSS_NAME,
secret,
- listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec))
+ listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec))
)
}
}
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/RetryTestRule.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/RetryTestRule.kt
index b16ab98e6c..39f49a9ccc 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/RetryTestRule.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/RetryTestRule.kt
@@ -40,6 +40,9 @@ class RetryTestRule(val retryCount: Int = 3) : TestRule {
for (i in 0 until retryCount) {
try {
base.evaluate()
+ if (i > 0) {
+ println("Retried test $i times")
+ }
return
} catch (t: Throwable) {
caughtThrowable = t
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..daf6b73313 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
@@ -47,7 +47,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/DecryptRedactedEventTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/DecryptRedactedEventTest.kt
new file mode 100644
index 0000000000..a48b45a1f5
--- /dev/null
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/DecryptRedactedEventTest.kt
@@ -0,0 +1,75 @@
+/*
+ * 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.internal.crypto
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Assert
+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.session.events.model.Event
+import org.matrix.android.sdk.api.session.events.model.toModel
+import org.matrix.android.sdk.api.session.getRoom
+import org.matrix.android.sdk.api.session.room.getTimelineEvent
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
+
+@RunWith(AndroidJUnit4::class)
+@FixMethodOrder(MethodSorters.JVM)
+class DecryptRedactedEventTest : InstrumentedTest {
+
+ @Test
+ fun doNotFailToDecryptRedactedEvent() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
+ val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
+ val e2eRoomID = testData.roomId
+ val aliceSession = testData.firstSession
+ val bobSession = testData.secondSession!!
+
+ val roomALicePOV = aliceSession.getRoom(e2eRoomID)!!
+ val timelineEvent = testHelper.sendTextMessage(roomALicePOV, "Hello", 1).first()
+ val redactionReason = "Wrong Room"
+ roomALicePOV.sendService().redactEvent(timelineEvent.root, redactionReason)
+
+ // get the event from bob
+ testHelper.waitWithLatch {
+ testHelper.retryPeriodicallyWithLatch(it) {
+ bobSession.getRoom(e2eRoomID)?.getTimelineEvent(timelineEvent.eventId)?.root?.isRedacted() == true
+ }
+ }
+
+ val eventBobPov = bobSession.getRoom(e2eRoomID)?.getTimelineEvent(timelineEvent.eventId)!!
+
+ testHelper.runBlockingTest {
+ try {
+ val result = bobSession.cryptoService().decryptEvent(eventBobPov.root, "")
+ Assert.assertEquals(
+ "Unexpected redacted reason",
+ redactionReason,
+ result.clearEvent.toModel()?.unsignedData?.redactedEvent?.content?.get("reason")
+ )
+ Assert.assertEquals(
+ "Unexpected Redacted event id",
+ timelineEvent.eventId,
+ result.clearEvent.toModel()?.unsignedData?.redactedEvent?.redacts
+ )
+ } catch (failure: Throwable) {
+ Assert.fail("Should not throw when decrypting a redacted event")
+ }
+ }
+ }
+}
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 552936971f..010383dab8 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
@@ -23,6 +23,7 @@ import org.amshove.kluent.fail
import org.amshove.kluent.internal.assertEquals
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
@@ -57,7 +58,8 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
import org.matrix.android.sdk.common.RetryTestRule
import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
@@ -68,6 +70,7 @@ import java.util.concurrent.CountDownLatch
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
+@Ignore("This test fails with an unhandled exception thrown from a coroutine which terminates the entire test run.")
class E2eeSanityTests : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)
@@ -82,9 +85,7 @@ class E2eeSanityTests : InstrumentedTest {
* Alice sends a new message, then check that the new one can be decrypted
*/
@Test
- fun testSendingE2EEMessages() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testSendingE2EEMessages() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val aliceSession = cryptoTestData.firstSession
@@ -198,21 +199,12 @@ class E2eeSanityTests : InstrumentedTest {
}
}
}
-
- otherAccounts.forEach {
- testHelper.signOutAndClose(it)
- }
- newAccount.forEach { testHelper.signOutAndClose(it) }
-
- cryptoTestData.cleanUp(testHelper)
}
@Test
- fun testKeyGossipingIsEnabledByDefault() {
- val testHelper = CommonTestHelper(context())
+ fun testKeyGossipingIsEnabledByDefault() = runSessionTest(context()) { testHelper ->
val session = testHelper.createAccount("alice", SessionTestParams(true))
Assert.assertTrue("Key gossiping should be enabled by default", session.cryptoService().isKeyGossipingEnabled())
- testHelper.signOutAndClose(session)
}
/**
@@ -230,9 +222,7 @@ class E2eeSanityTests : InstrumentedTest {
* 9. Check that new session can decrypt
*/
@Test
- fun testBasicBackupImport() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testBasicBackupImport() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val aliceSession = cryptoTestData.firstSession
@@ -344,8 +334,6 @@ class E2eeSanityTests : InstrumentedTest {
// ensure bob can now decrypt
cryptoTestHelper.ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText)
-
- testHelper.signOutAndClose(newBobSession)
}
/**
@@ -353,9 +341,7 @@ class E2eeSanityTests : InstrumentedTest {
* get them from an older one.
*/
@Test
- fun testSimpleGossip() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testSimpleGossip() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val aliceSession = cryptoTestData.firstSession
@@ -449,18 +435,13 @@ class E2eeSanityTests : InstrumentedTest {
}
cryptoTestHelper.ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText)
-
- cryptoTestData.cleanUp(testHelper)
- testHelper.signOutAndClose(newBobSession)
}
/**
* Test that if a better key is forwarded (lower index, it is then used)
*/
@Test
- fun testForwardBetterKey() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testForwardBetterKey() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val aliceSession = cryptoTestData.firstSession
@@ -576,10 +557,6 @@ class E2eeSanityTests : InstrumentedTest {
canDecryptFirst && canDecryptSecond
}
}
-
- testHelper.signOutAndClose(aliceSession)
- testHelper.signOutAndClose(bobSessionWithBetterKey)
- testHelper.signOutAndClose(newBobSession)
}
private fun sendMessageInRoom(testHelper: CommonTestHelper, aliceRoomPOV: Room, text: String): String? {
@@ -610,9 +587,7 @@ class E2eeSanityTests : InstrumentedTest {
* Test that if a better key is forwared (lower index, it is then used)
*/
@Test
- fun testSelfInteractiveVerificationAndGossip() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testASelfInteractiveVerificationAndGossip() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val aliceSession = testHelper.createAccount("alice", SessionTestParams(true))
cryptoTestHelper.bootstrapSecurity(aliceSession)
@@ -751,9 +726,6 @@ class E2eeSanityTests : InstrumentedTest {
aliceSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.version,
aliceNewSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.version
)
-
- testHelper.signOutAndClose(aliceSession)
- testHelper.signOutAndClose(aliceNewSession)
}
private fun ensureMembersHaveJoined(testHelper: CommonTestHelper, aliceSession: Session, otherAccounts: List, e2eRoomID: String) {
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/PreShareKeysTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt
index 93aa78a305..e37ae5be86 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt
@@ -30,18 +30,14 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class PreShareKeysTest : InstrumentedTest {
- private val testHelper = CommonTestHelper(context())
- private val cryptoTestHelper = CryptoTestHelper(testHelper)
-
@Test
- fun ensure_outbound_session_happy_path() {
+ fun ensure_outbound_session_happy_path() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val e2eRoomID = testData.roomId
val aliceSession = testData.firstSession
@@ -94,7 +90,5 @@ class PreShareKeysTest : InstrumentedTest {
bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEvent.eventId)?.root?.getClearType() == EventType.MESSAGE
}
}
-
- testData.cleanUp(testHelper)
}
}
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 0f3a4b4181..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
@@ -38,8 +39,7 @@ import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
import org.matrix.android.sdk.common.TestConstants
import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper
import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm
@@ -60,11 +60,10 @@ import kotlin.coroutines.resume
*/
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
+@Ignore
class UnwedgingTest : InstrumentedTest {
private lateinit var messagesReceivedByBob: List
- private val testHelper = CommonTestHelper(context())
- private val cryptoTestHelper = CryptoTestHelper(testHelper)
@Before
fun init() {
@@ -85,7 +84,7 @@ class UnwedgingTest : InstrumentedTest {
* -> This is automatically fixed after SDKs restarted the olm session
*/
@Test
- fun testUnwedging() {
+ fun testUnwedging() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
@@ -240,8 +239,6 @@ class UnwedgingTest : InstrumentedTest {
}
bobTimeline.dispose()
-
- cryptoTestData.cleanUp(testHelper)
}
private fun createEventListener(latch: CountDownLatch, expectedNumberOfMessages: Int): Timeline.Listener {
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 abcf1714b8..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
@@ -37,8 +38,8 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.isCrossSignedVerif
import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
import kotlin.coroutines.Continuation
@@ -47,13 +48,11 @@ import kotlin.coroutines.resume
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@LargeTest
+@Ignore
class XSigningTest : InstrumentedTest {
- private val testHelper = CommonTestHelper(context())
- private val cryptoTestHelper = CryptoTestHelper(testHelper)
-
@Test
- fun test_InitializeAndStoreKeys() {
+ fun test_InitializeAndStoreKeys() = runSessionTest(context()) { testHelper ->
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
testHelper.doSync {
@@ -87,7 +86,7 @@ class XSigningTest : InstrumentedTest {
}
@Test
- fun test_CrossSigningCheckBobSeesTheKeys() {
+ fun test_CrossSigningCheckBobSeesTheKeys() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
@@ -137,12 +136,10 @@ class XSigningTest : InstrumentedTest {
)
assertFalse("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV.isTrusted())
-
- cryptoTestData.cleanUp(testHelper)
}
@Test
- fun test_CrossSigningTestAliceTrustBobNewDevice() {
+ fun test_CrossSigningTestAliceTrustBobNewDevice() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
@@ -216,9 +213,5 @@ class XSigningTest : InstrumentedTest {
val result = aliceSession.cryptoService().crossSigningService().checkDeviceTrust(bobUserId, bobSecondDeviceId, null)
assertTrue("Bob second device should be trusted from alice POV", result.isCrossSignedVerified())
-
- testHelper.signOutAndClose(aliceSession)
- testHelper.signOutAndClose(bobSession)
- testHelper.signOutAndClose(bobSession2)
}
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt
index 85b6c21df3..5f26fda946 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt
@@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.common.CommonTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
import org.matrix.android.sdk.common.CryptoTestHelper
import java.util.concurrent.CountDownLatch
@@ -42,35 +43,36 @@ import java.util.concurrent.CountDownLatch
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class EncryptionTest : InstrumentedTest {
- private val testHelper = CommonTestHelper(context())
- private val cryptoTestHelper = CryptoTestHelper(testHelper)
-
@Test
fun test_EncryptionEvent() {
- performTest(roomShouldBeEncrypted = false) { room ->
- // Send an encryption Event as an Event (and not as a state event)
- room.sendService().sendEvent(
- eventType = EventType.STATE_ROOM_ENCRYPTION,
- content = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
- )
- }
- }
-
- @Test
- fun test_EncryptionStateEvent() {
- performTest(roomShouldBeEncrypted = true) { room ->
- runBlocking {
- // Send an encryption Event as a State Event
- room.stateService().sendStateEvent(
+ runCryptoTest(context()) { cryptoTestHelper, testHelper ->
+ performTest(cryptoTestHelper, testHelper, roomShouldBeEncrypted = false) { room ->
+ // Send an encryption Event as an Event (and not as a state event)
+ room.sendService().sendEvent(
eventType = EventType.STATE_ROOM_ENCRYPTION,
- stateKey = "",
- body = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
+ content = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
)
}
}
}
- private fun performTest(roomShouldBeEncrypted: Boolean, action: (Room) -> Unit) {
+ @Test
+ fun test_EncryptionStateEvent() {
+ runCryptoTest(context()) { cryptoTestHelper, testHelper ->
+ performTest(cryptoTestHelper, testHelper, roomShouldBeEncrypted = true) { room ->
+ runBlocking {
+ // Send an encryption Event as a State Event
+ room.stateService().sendStateEvent(
+ eventType = EventType.STATE_ROOM_ENCRYPTION,
+ stateKey = "",
+ body = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
+ )
+ }
+ }
+ }
+ }
+
+ private fun performTest(cryptoTestHelper: CryptoTestHelper, testHelper: CommonTestHelper, roomShouldBeEncrypted: Boolean, action: (Room) -> Unit) {
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(encryptedRoom = false)
val aliceSession = cryptoTestData.firstSession
@@ -109,6 +111,5 @@ class EncryptionTest : InstrumentedTest {
room.roomCryptoService().isEncrypted() shouldBe roomShouldBeEncrypted
it.countDown()
}
- cryptoTestData.cleanUp(testHelper)
}
}
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 895f95aeac..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
@@ -41,8 +42,7 @@ import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
import org.matrix.android.sdk.common.RetryTestRule
import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
@@ -51,14 +51,13 @@ import org.matrix.android.sdk.mustFail
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
+@Ignore
class KeyShareTests : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)
@Test
- fun test_DoNotSelfShareIfNotTrusted() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun test_DoNotSelfShareIfNotTrusted() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val aliceSession = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
Log.v("TEST", "=======> AliceSession 1 is ${aliceSession.sessionParams.deviceId}")
@@ -194,9 +193,7 @@ class KeyShareTests : InstrumentedTest {
* if the key was originally shared with him
*/
@Test
- fun test_reShareIfWasIntendedToBeShared() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun test_reShareIfWasIntendedToBeShared() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val aliceSession = testData.firstSession
@@ -227,9 +224,7 @@ class KeyShareTests : InstrumentedTest {
* if the key was originally shared with him
*/
@Test
- fun test_reShareToUnverifiedIfWasIntendedToBeShared() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun test_reShareToUnverifiedIfWasIntendedToBeShared() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val testData = cryptoTestHelper.doE2ETestWithAliceInARoom(true)
val aliceSession = testData.firstSession
@@ -266,9 +261,7 @@ class KeyShareTests : InstrumentedTest {
* Tests that keys reshared with own verified session are done from the earliest known index
*/
@Test
- fun test_reShareFromTheEarliestKnownIndexWithOwnVerifiedSession() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun test_reShareFromTheEarliestKnownIndexWithOwnVerifiedSession() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val aliceSession = testData.firstSession
@@ -388,10 +381,7 @@ class KeyShareTests : InstrumentedTest {
* Tests that we don't cancel a request to early on first forward if the index is not good enough
*/
@Test
- fun test_dontCancelToEarly() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
-
+ fun test_dontCancelToEarly() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val aliceSession = testData.firstSession
val bobSession = testData.secondSession!!
@@ -434,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)
@@ -442,7 +432,7 @@ class KeyShareTests : InstrumentedTest {
// Should get a reply from bob and not from alice
commonTestHelper.waitWithLatch { latch ->
commonTestHelper.retryPeriodicallyWithLatch(latch) {
- // Log.d("#TEST", "outgoing key requests :${aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().joinToString { it.sessionId ?: "?" }}")
+ // Log.d("#TEST", "outgoing key requests :${aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().joinToString { it.sessionId ?: "?" }}")
val outgoing = aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession }
val bobReply = outgoing?.results?.firstOrNull { it.userId == bobSession.myUserId }
val result = bobReply?.result
@@ -457,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 13133b726c..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
@@ -36,8 +37,7 @@ import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
import org.matrix.android.sdk.common.MockOkHttpInterceptor
import org.matrix.android.sdk.common.RetryTestRule
import org.matrix.android.sdk.common.SessionTestParams
@@ -47,14 +47,13 @@ import org.matrix.android.sdk.mustFail
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
+@Ignore
class WithHeldTests : InstrumentedTest {
@get:Rule val rule = RetryTestRule(3)
@Test
- fun test_WithHeldUnverifiedReason() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_WithHeldUnverifiedReason() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
// =============================
// ARRANGE
@@ -153,16 +152,10 @@ class WithHeldTests : InstrumentedTest {
bobUnverifiedSession.cryptoService().decryptEvent(eventBobPOV.root, "")
}
}
-
- testHelper.signOutAndClose(aliceSession)
- testHelper.signOutAndClose(bobSession)
- testHelper.signOutAndClose(bobUnverifiedSession)
}
@Test
- fun test_WithHeldNoOlm() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_WithHeldNoOlm() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = testData.firstSession
@@ -239,14 +232,10 @@ class WithHeldTests : InstrumentedTest {
Assert.assertEquals("Alice should have marked bob's device for this session", 1, chainIndex2)
aliceInterceptor.clearRules()
- testData.cleanUp(testHelper)
- testHelper.signOutAndClose(bobSecondSession)
}
@Test
- fun test_WithHeldKeyRequest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_WithHeldKeyRequest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = testData.firstSession
@@ -293,8 +282,5 @@ class WithHeldTests : InstrumentedTest {
wc?.code == WithHeldCode.UNAUTHORISED
}
}
-
- testHelper.signOutAndClose(aliceSession)
- testHelper.signOutAndClose(bobSecondSession)
}
}
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 9136272b1e..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,8 @@ 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
import org.junit.runners.MethodSorters
@@ -43,8 +45,9 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreation
import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult
import org.matrix.android.sdk.api.session.getRoom
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
+import org.matrix.android.sdk.common.RetryTestRule
import org.matrix.android.sdk.common.TestConstants
import org.matrix.android.sdk.common.TestMatrixCallback
import java.util.Collections
@@ -53,17 +56,18 @@ import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
+@Ignore
class KeysBackupTest : InstrumentedTest {
+ @get:Rule val rule = RetryTestRule(3)
+
/**
* - From doE2ETestWithAliceAndBobInARoomWithEncryptedMessages, we should have no backed up keys
* - Check backup keys after having marked one as backed up
* - Reset keys backup markers
*/
@Test
- fun roomKeysTest_testBackupStore_ok() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun roomKeysTest_testBackupStore_ok() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
@@ -102,8 +106,7 @@ class KeysBackupTest : InstrumentedTest {
* Check that prepareKeysBackupVersionWithPassword returns valid data
*/
@Test
- fun prepareKeysBackupVersionTest() {
- val testHelper = CommonTestHelper(context())
+ fun prepareKeysBackupVersionTest() = runSessionTest(context()) { testHelper ->
val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams)
@@ -113,7 +116,7 @@ class KeysBackupTest : InstrumentedTest {
val stateObserver = StateObserver(keysBackup)
- assertFalse(keysBackup.isEnabled)
+ assertFalse(keysBackup.isEnabled())
val megolmBackupCreationInfo = testHelper.doSync {
keysBackup.prepareKeysBackupVersion(null, null, it)
@@ -125,16 +128,13 @@ class KeysBackupTest : InstrumentedTest {
assertNotNull(megolmBackupCreationInfo.recoveryKey)
stateObserver.stopAndCheckStates(null)
- testHelper.signOutAndClose(bobSession)
}
/**
* Test creating a keys backup version and check that createKeysBackupVersion() returns valid data
*/
@Test
- fun createKeysBackupVersionTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun createKeysBackupVersionTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams)
cryptoTestHelper.initializeCrossSigning(bobSession)
@@ -143,13 +143,13 @@ class KeysBackupTest : InstrumentedTest {
val stateObserver = StateObserver(keysBackup)
- assertFalse(keysBackup.isEnabled)
+ assertFalse(keysBackup.isEnabled())
val megolmBackupCreationInfo = testHelper.doSync {
keysBackup.prepareKeysBackupVersion(null, null, it)
}
- assertFalse(keysBackup.isEnabled)
+ assertFalse(keysBackup.isEnabled())
// Create the version
val version = testHelper.doSync {
@@ -157,7 +157,7 @@ class KeysBackupTest : InstrumentedTest {
}
// Backup must be enable now
- assertTrue(keysBackup.isEnabled)
+ assertTrue(keysBackup.isEnabled())
// Check that it's signed with MSK
val versionResult = testHelper.doSync {
@@ -193,7 +193,6 @@ class KeysBackupTest : InstrumentedTest {
}
stateObserver.stopAndCheckStates(null)
- testHelper.signOutAndClose(bobSession)
}
/**
@@ -201,9 +200,7 @@ class KeysBackupTest : InstrumentedTest {
* - Check the backup completes
*/
@Test
- fun backupAfterCreateKeysBackupVersionTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun backupAfterCreateKeysBackupVersionTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
@@ -238,16 +235,13 @@ class KeysBackupTest : InstrumentedTest {
KeysBackupState.ReadyToBackUp
)
)
- cryptoTestData.cleanUp(testHelper)
}
/**
* Check that backupAllGroupSessions() returns valid data
*/
@Test
- fun backupAllGroupSessionsTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun backupAllGroupSessionsTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
@@ -281,7 +275,6 @@ class KeysBackupTest : InstrumentedTest {
assertEquals("All keys must have been marked as backed up", nbOfKeys, backedUpKeys)
stateObserver.stopAndCheckStates(null)
- cryptoTestData.cleanUp(testHelper)
}
/**
@@ -293,9 +286,7 @@ class KeysBackupTest : InstrumentedTest {
* - Compare the decrypted megolm key with the original one
*/
@Test
- fun testEncryptAndDecryptKeysBackupData() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testEncryptAndDecryptKeysBackupData() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
@@ -330,7 +321,6 @@ class KeysBackupTest : InstrumentedTest {
keysBackupTestHelper.assertKeysEquals(session.exportKeys(), sessionData)
stateObserver.stopAndCheckStates(null)
- cryptoTestData.cleanUp(testHelper)
}
/**
@@ -340,9 +330,7 @@ class KeysBackupTest : InstrumentedTest {
* - Restore must be successful
*/
@Test
- fun restoreKeysBackupTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun restoreKeysBackupTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null)
@@ -428,9 +416,7 @@ class KeysBackupTest : InstrumentedTest {
* - It must be trusted and must have with 2 signatures now
*/
@Test
- fun trustKeyBackupVersionTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun trustKeyBackupVersionTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
// - Do an e2e backup to the homeserver with a recovery key
@@ -441,8 +427,8 @@ class KeysBackupTest : InstrumentedTest {
// - The new device must see the previous backup as not trusted
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
- assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
- assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
+ assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
+ assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
// - Trust the backup from the new device
testHelper.doSync {
@@ -458,7 +444,7 @@ class KeysBackupTest : InstrumentedTest {
// - Backup must be enabled on the new device, on the same version
assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version)
- assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
+ assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
// - Retrieve the last version from the server
val keysVersionResult = testHelper.doSync {
@@ -477,7 +463,6 @@ class KeysBackupTest : InstrumentedTest {
assertEquals(2, keysBackupVersionTrust.signatures.size)
stateObserver.stopAndCheckStates(null)
- testData.cleanUp(testHelper)
}
/**
@@ -491,9 +476,7 @@ class KeysBackupTest : InstrumentedTest {
* - It must be trusted and must have with 2 signatures now
*/
@Test
- fun trustKeyBackupVersionWithRecoveryKeyTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun trustKeyBackupVersionWithRecoveryKeyTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
// - Do an e2e backup to the homeserver with a recovery key
@@ -504,8 +487,8 @@ class KeysBackupTest : InstrumentedTest {
// - The new device must see the previous backup as not trusted
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
- assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
- assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
+ assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
+ assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
// - Trust the backup from the new device with the recovery key
testHelper.doSync {
@@ -521,7 +504,7 @@ class KeysBackupTest : InstrumentedTest {
// - Backup must be enabled on the new device, on the same version
assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version)
- assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
+ assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
// - Retrieve the last version from the server
val keysVersionResult = testHelper.doSync {
@@ -540,7 +523,6 @@ class KeysBackupTest : InstrumentedTest {
assertEquals(2, keysBackupVersionTrust.signatures.size)
stateObserver.stopAndCheckStates(null)
- testData.cleanUp(testHelper)
}
/**
@@ -552,9 +534,7 @@ class KeysBackupTest : InstrumentedTest {
* - The backup must still be untrusted and disabled
*/
@Test
- fun trustKeyBackupVersionWithWrongRecoveryKeyTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun trustKeyBackupVersionWithWrongRecoveryKeyTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
// - Do an e2e backup to the homeserver with a recovery key
@@ -565,8 +545,8 @@ class KeysBackupTest : InstrumentedTest {
// - The new device must see the previous backup as not trusted
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
- assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
- assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
+ assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
+ assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
// - Try to trust the backup from the new device with a wrong recovery key
val latch = CountDownLatch(1)
@@ -579,11 +559,10 @@ class KeysBackupTest : InstrumentedTest {
// - The new device must still see the previous backup as not trusted
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
- assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
- assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
+ assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
+ assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
stateObserver.stopAndCheckStates(null)
- testData.cleanUp(testHelper)
}
/**
@@ -597,9 +576,7 @@ class KeysBackupTest : InstrumentedTest {
* - It must be trusted and must have with 2 signatures now
*/
@Test
- fun trustKeyBackupVersionWithPasswordTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun trustKeyBackupVersionWithPasswordTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
val password = "Password"
@@ -612,8 +589,8 @@ class KeysBackupTest : InstrumentedTest {
// - The new device must see the previous backup as not trusted
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
- assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
- assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
+ assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
+ assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
// - Trust the backup from the new device with the password
testHelper.doSync {
@@ -629,7 +606,7 @@ class KeysBackupTest : InstrumentedTest {
// - Backup must be enabled on the new device, on the same version
assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version)
- assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
+ assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
// - Retrieve the last version from the server
val keysVersionResult = testHelper.doSync {
@@ -648,7 +625,6 @@ class KeysBackupTest : InstrumentedTest {
assertEquals(2, keysBackupVersionTrust.signatures.size)
stateObserver.stopAndCheckStates(null)
- testData.cleanUp(testHelper)
}
/**
@@ -660,9 +636,7 @@ class KeysBackupTest : InstrumentedTest {
* - The backup must still be untrusted and disabled
*/
@Test
- fun trustKeyBackupVersionWithWrongPasswordTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun trustKeyBackupVersionWithWrongPasswordTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
val password = "Password"
@@ -676,8 +650,8 @@ class KeysBackupTest : InstrumentedTest {
// - The new device must see the previous backup as not trusted
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
- assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
- assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
+ assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
+ assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
// - Try to trust the backup from the new device with a wrong password
val latch = CountDownLatch(1)
@@ -690,11 +664,10 @@ class KeysBackupTest : InstrumentedTest {
// - The new device must still see the previous backup as not trusted
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
- assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
- assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
+ assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
+ assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
stateObserver.stopAndCheckStates(null)
- testData.cleanUp(testHelper)
}
/**
@@ -704,9 +677,7 @@ class KeysBackupTest : InstrumentedTest {
* - It must fail
*/
@Test
- fun restoreKeysBackupWithAWrongRecoveryKeyTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun restoreKeysBackupWithAWrongRecoveryKeyTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null)
@@ -730,8 +701,6 @@ class KeysBackupTest : InstrumentedTest {
// onSuccess may not have been called
assertNull(importRoomKeysResult)
-
- testData.cleanUp(testHelper)
}
/**
@@ -741,9 +710,7 @@ class KeysBackupTest : InstrumentedTest {
* - Restore must be successful
*/
@Test
- fun testBackupWithPassword() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testBackupWithPassword() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
val password = "password"
@@ -790,8 +757,6 @@ class KeysBackupTest : InstrumentedTest {
assertEquals(100, (steps[104] as StepProgressListener.Step.ImportingKey).progress)
keysBackupTestHelper.checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys)
-
- testData.cleanUp(testHelper)
}
/**
@@ -801,9 +766,7 @@ class KeysBackupTest : InstrumentedTest {
* - It must fail
*/
@Test
- fun restoreKeysBackupWithAWrongPasswordTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun restoreKeysBackupWithAWrongPasswordTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
val password = "password"
@@ -830,8 +793,6 @@ class KeysBackupTest : InstrumentedTest {
// onSuccess may not have been called
assertNull(importRoomKeysResult)
-
- testData.cleanUp(testHelper)
}
/**
@@ -841,9 +802,7 @@ class KeysBackupTest : InstrumentedTest {
* - Restore must be successful
*/
@Test
- fun testUseRecoveryKeyToRestoreAPasswordBasedKeysBackup() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testUseRecoveryKeyToRestoreAPasswordBasedKeysBackup() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
val password = "password"
@@ -863,8 +822,6 @@ class KeysBackupTest : InstrumentedTest {
}
keysBackupTestHelper.checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys)
-
- testData.cleanUp(testHelper)
}
/**
@@ -874,9 +831,7 @@ class KeysBackupTest : InstrumentedTest {
* - It must fail
*/
@Test
- fun testUsePasswordToRestoreARecoveryKeyBasedKeysBackup() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testUsePasswordToRestoreARecoveryKeyBasedKeysBackup() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null)
@@ -900,8 +855,6 @@ class KeysBackupTest : InstrumentedTest {
// onSuccess may not have been called
assertNull(importRoomKeysResult)
-
- testData.cleanUp(testHelper)
}
/**
@@ -909,9 +862,7 @@ class KeysBackupTest : InstrumentedTest {
* - Check the returned KeysVersionResult is trusted
*/
@Test
- fun testIsKeysBackupTrusted() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testIsKeysBackupTrusted() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
// - Create a backup version
@@ -945,7 +896,6 @@ class KeysBackupTest : InstrumentedTest {
assertEquals(signature.device!!.deviceId, cryptoTestData.firstSession.sessionParams.deviceId)
stateObserver.stopAndCheckStates(null)
- cryptoTestData.cleanUp(testHelper)
}
/**
@@ -957,9 +907,7 @@ class KeysBackupTest : InstrumentedTest {
* -> That must fail and her backup state must be WrongBackUpVersion
*/
@Test
- fun testBackupWhenAnotherBackupWasCreated() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testBackupWhenAnotherBackupWasCreated() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
// - Create a backup version
@@ -969,7 +917,7 @@ class KeysBackupTest : InstrumentedTest {
val stateObserver = StateObserver(keysBackup)
- assertFalse(keysBackup.isEnabled)
+ assertFalse(keysBackup.isEnabled())
// Wait for keys backup to be finished
val latch0 = CountDownLatch(1)
@@ -993,7 +941,7 @@ class KeysBackupTest : InstrumentedTest {
// - Make alice back up her keys to her homeserver
keysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
- assertTrue(keysBackup.isEnabled)
+ assertTrue(keysBackup.isEnabled())
testHelper.await(latch0)
@@ -1012,11 +960,10 @@ class KeysBackupTest : InstrumentedTest {
testHelper.await(latch2)
// -> That must fail and her backup state must be WrongBackUpVersion
- assertEquals(KeysBackupState.WrongBackUpVersion, keysBackup.state)
- assertFalse(keysBackup.isEnabled)
+ assertEquals(KeysBackupState.WrongBackUpVersion, keysBackup.getState())
+ assertFalse(keysBackup.isEnabled())
stateObserver.stopAndCheckStates(null)
- cryptoTestData.cleanUp(testHelper)
}
/**
@@ -1032,9 +979,7 @@ class KeysBackupTest : InstrumentedTest {
* -> It must success
*/
@Test
- fun testBackupAfterVerifyingADevice() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun testBackupAfterVerifyingADevice() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
// - Create a backup version
@@ -1069,7 +1014,7 @@ class KeysBackupTest : InstrumentedTest {
// - Try to backup all in aliceSession2, it must fail
val keysBackup2 = aliceSession2.cryptoService().keysBackupService()
- assertFalse("Backup should not be enabled", keysBackup2.isEnabled)
+ assertFalse("Backup should not be enabled", keysBackup2.isEnabled())
val stateObserver2 = StateObserver(keysBackup2)
@@ -1088,8 +1033,8 @@ class KeysBackupTest : InstrumentedTest {
assertFalse(isSuccessful)
// Backup state must be NotTrusted
- assertEquals("Backup state must be NotTrusted", KeysBackupState.NotTrusted, keysBackup2.state)
- assertFalse("Backup should not be enabled", keysBackup2.isEnabled)
+ assertEquals("Backup state must be NotTrusted", KeysBackupState.NotTrusted, keysBackup2.getState())
+ assertFalse("Backup should not be enabled", keysBackup2.isEnabled())
// - Validate the old device from the new one
aliceSession2.cryptoService().setDeviceVerification(
@@ -1103,7 +1048,7 @@ class KeysBackupTest : InstrumentedTest {
keysBackup2.addListener(object : KeysBackupStateListener {
override fun onStateChange(newState: KeysBackupState) {
// Check the backup completes
- if (keysBackup2.state == KeysBackupState.ReadyToBackUp) {
+ if (keysBackup2.getState() == KeysBackupState.ReadyToBackUp) {
// Remove itself from the list of listeners
keysBackup2.removeListener(this)
@@ -1121,12 +1066,10 @@ class KeysBackupTest : InstrumentedTest {
}
// -> It must success
- assertTrue(aliceSession2.cryptoService().keysBackupService().isEnabled)
+ assertTrue(aliceSession2.cryptoService().keysBackupService().isEnabled())
stateObserver.stopAndCheckStates(null)
stateObserver2.stopAndCheckStates(null)
- testHelper.signOutAndClose(aliceSession2)
- cryptoTestData.cleanUp(testHelper)
}
/**
@@ -1134,9 +1077,7 @@ class KeysBackupTest : InstrumentedTest {
* - Delete the backup
*/
@Test
- fun deleteKeysBackupTest() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun deleteKeysBackupTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
// - Create a backup version
@@ -1146,19 +1087,18 @@ class KeysBackupTest : InstrumentedTest {
val stateObserver = StateObserver(keysBackup)
- assertFalse(keysBackup.isEnabled)
+ assertFalse(keysBackup.isEnabled())
val keyBackupCreationInfo = keysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
- assertTrue(keysBackup.isEnabled)
+ assertTrue(keysBackup.isEnabled())
// Delete the backup
testHelper.doSync { keysBackup.deleteBackup(keyBackupCreationInfo.version, it) }
// Backup is now disabled
- assertFalse(keysBackup.isEnabled)
+ assertFalse(keysBackup.isEnabled())
stateObserver.stopAndCheckStates(null)
- cryptoTestData.cleanUp(testHelper)
}
}
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 2220536e28..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 {
@@ -106,7 +109,7 @@ internal class KeysBackupTestHelper(
Assert.assertNotNull(megolmBackupCreationInfo)
- Assert.assertFalse("Key backup should not be enabled before creation", keysBackup.isEnabled)
+ Assert.assertFalse("Key backup should not be enabled before creation", keysBackup.isEnabled())
// Create the version
val keysVersion = testHelper.doSync {
@@ -116,7 +119,7 @@ internal class KeysBackupTestHelper(
Assert.assertNotNull("Key backup version should not be null", keysVersion.version)
// Backup must be enable now
- Assert.assertTrue(keysBackup.isEnabled)
+ Assert.assertTrue(keysBackup.isEnabled())
stateObserver.stopAndCheckStates(null)
return PrepareKeysBackupDataResult(megolmBackupCreationInfo, keysVersion.version)
@@ -128,7 +131,7 @@ internal class KeysBackupTestHelper(
*/
fun waitForKeysBackupToBeInState(session: Session, state: KeysBackupState) {
// If already in the wanted state, return
- if (session.cryptoService().keysBackupService().state == state) {
+ if (session.cryptoService().keysBackupService().getState() == state) {
return
}
@@ -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/replayattack/ReplayAttackTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/replayattack/ReplayAttackTest.kt
new file mode 100644
index 0000000000..53cf802b91
--- /dev/null
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/replayattack/ReplayAttackTest.kt
@@ -0,0 +1,109 @@
+/*
+ * 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.internal.crypto.replayattack
+
+import androidx.test.filters.LargeTest
+import org.amshove.kluent.internal.assertFailsWith
+import org.junit.Assert
+import org.junit.Assert.assertEquals
+import org.junit.Assert.fail
+import org.junit.FixMethodOrder
+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.session.crypto.MXCryptoError
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
+
+@RunWith(JUnit4::class)
+@FixMethodOrder(MethodSorters.JVM)
+@LargeTest
+class ReplayAttackTest : InstrumentedTest {
+
+ @Test
+ fun replayAttackAlreadyDecryptedEventTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
+ val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
+
+ val e2eRoomID = cryptoTestData.roomId
+
+ // Alice
+ val aliceSession = cryptoTestData.firstSession
+ val aliceRoomPOV = aliceSession.roomService().getRoom(e2eRoomID)!!
+
+ // Bob
+ val bobSession = cryptoTestData.secondSession
+ val bobRoomPOV = bobSession!!.roomService().getRoom(e2eRoomID)!!
+ assertEquals(bobRoomPOV.roomSummary()?.joinedMembersCount, 2)
+
+ // Alice will send a message
+ val sentEvents = testHelper.sendTextMessage(aliceRoomPOV, "Hello I will be decrypted twice", 1)
+ assertEquals(1, sentEvents.size)
+
+ val fakeEventId = sentEvents[0].eventId + "_fake"
+ val fakeEventWithTheSameIndex =
+ sentEvents[0].copy(eventId = fakeEventId, root = sentEvents[0].root.copy(eventId = fakeEventId))
+
+ testHelper.runBlockingTest {
+ // Lets assume we are from the main timelineId
+ val timelineId = "timelineId"
+ // Lets decrypt the original event
+ aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId)
+ // Lets decrypt the fake event that will have the same message index
+ val exception = assertFailsWith {
+ // An exception should be thrown while the same index would have been used for the previous decryption
+ aliceSession.cryptoService().decryptEvent(fakeEventWithTheSameIndex.root, timelineId)
+ }
+ assertEquals(MXCryptoError.ErrorType.DUPLICATED_MESSAGE_INDEX, exception.errorType)
+ }
+ cryptoTestData.cleanUp(testHelper)
+ }
+
+ @Test
+ fun replayAttackSameEventTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
+ val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
+
+ val e2eRoomID = cryptoTestData.roomId
+
+ // Alice
+ val aliceSession = cryptoTestData.firstSession
+ val aliceRoomPOV = aliceSession.roomService().getRoom(e2eRoomID)!!
+
+ // Bob
+ val bobSession = cryptoTestData.secondSession
+ val bobRoomPOV = bobSession!!.roomService().getRoom(e2eRoomID)!!
+ assertEquals(bobRoomPOV.roomSummary()?.joinedMembersCount, 2)
+
+ // Alice will send a message
+ val sentEvents = testHelper.sendTextMessage(aliceRoomPOV, "Hello I will be decrypted twice", 1)
+ Assert.assertTrue("Message should be sent", sentEvents.size == 1)
+ assertEquals(sentEvents.size, 1)
+
+ testHelper.runBlockingTest {
+ // Lets assume we are from the main timelineId
+ val timelineId = "timelineId"
+ // Lets decrypt the original event
+ aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId)
+ try {
+ // Lets try to decrypt the same event
+ aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId)
+ } catch (ex: Throwable) {
+ fail("Shouldn't throw a decryption error for same event")
+ }
+ }
+ }
+}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt
index c758050fc9..c8be6aae74 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt
@@ -31,15 +31,16 @@ import org.matrix.android.sdk.api.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent
+import org.matrix.android.sdk.api.session.securestorage.KeyRef
import org.matrix.android.sdk.api.session.securestorage.KeySigner
import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
import org.matrix.android.sdk.api.session.securestorage.SecretStorageKeyContent
import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageError
-import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService
import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.api.util.toBase64NoPadding
import org.matrix.android.sdk.common.CommonTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService
@@ -55,8 +56,7 @@ class QuadSTests : InstrumentedTest {
}
@Test
- fun test_Generate4SKey() {
- val testHelper = CommonTestHelper(context())
+ fun test_Generate4SKey() = runSessionTest(context()) { testHelper ->
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
@@ -108,12 +108,11 @@ class QuadSTests : InstrumentedTest {
}
@Test
- fun test_StoreSecret() {
- val testHelper = CommonTestHelper(context())
+ fun test_StoreSecret() = runSessionTest(context()) { testHelper ->
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
val keyId = "My.Key"
- val info = generatedSecret(aliceSession, keyId, true)
+ val info = generatedSecret(testHelper, aliceSession, keyId, true)
val keySpec = RawBytesKeySpec.fromRecoveryKey(info.recoveryKey)
@@ -123,11 +122,11 @@ class QuadSTests : InstrumentedTest {
aliceSession.sharedSecretStorageService().storeSecret(
"secret.of.life",
clearSecret,
- listOf(SharedSecretStorageService.KeyRef(null, keySpec)) // default key
+ listOf(KeyRef(null, keySpec)) // default key
)
}
- val secretAccountData = assertAccountData(aliceSession, "secret.of.life")
+ val secretAccountData = assertAccountData(testHelper, aliceSession, "secret.of.life")
val encryptedContent = secretAccountData.content["encrypted"] as? Map<*, *>
assertNotNull("Element should be encrypted", encryptedContent)
@@ -149,12 +148,10 @@ class QuadSTests : InstrumentedTest {
}
assertEquals("Secret mismatch", clearSecret, decryptedSecret)
- testHelper.signOutAndClose(aliceSession)
}
@Test
- fun test_SetDefaultLocalEcho() {
- val testHelper = CommonTestHelper(context())
+ fun test_SetDefaultLocalEcho() = runSessionTest(context()) { testHelper ->
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
@@ -170,19 +167,16 @@ class QuadSTests : InstrumentedTest {
testHelper.runBlockingTest {
quadS.setDefaultKey(TEST_KEY_ID)
}
-
- testHelper.signOutAndClose(aliceSession)
}
@Test
- fun test_StoreSecretWithMultipleKey() {
- val testHelper = CommonTestHelper(context())
+ fun test_StoreSecretWithMultipleKey() = runSessionTest(context()) { testHelper ->
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
val keyId1 = "Key.1"
- val key1Info = generatedSecret(aliceSession, keyId1, true)
+ val key1Info = generatedSecret(testHelper, aliceSession, keyId1, true)
val keyId2 = "Key2"
- val key2Info = generatedSecret(aliceSession, keyId2, true)
+ val key2Info = generatedSecret(testHelper, aliceSession, keyId2, true)
val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
@@ -191,8 +185,8 @@ class QuadSTests : InstrumentedTest {
"my.secret",
mySecretText.toByteArray().toBase64NoPadding(),
listOf(
- SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)),
- SharedSecretStorageService.KeyRef(keyId2, RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey))
+ KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)),
+ KeyRef(keyId2, RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey))
)
)
}
@@ -221,19 +215,16 @@ class QuadSTests : InstrumentedTest {
RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey)!!
)
}
-
- testHelper.signOutAndClose(aliceSession)
}
@Test
@Ignore("Test is working locally, not in GitHub actions")
- fun test_GetSecretWithBadPassphrase() {
- val testHelper = CommonTestHelper(context())
+ fun test_GetSecretWithBadPassphrase() = runSessionTest(context()) { testHelper ->
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
val keyId1 = "Key.1"
val passphrase = "The good pass phrase"
- val key1Info = generatedSecretFromPassphrase(aliceSession, passphrase, keyId1, true)
+ val key1Info = generatedSecretFromPassphrase(testHelper, aliceSession, passphrase, keyId1, true)
val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
@@ -241,7 +232,7 @@ class QuadSTests : InstrumentedTest {
aliceSession.sharedSecretStorageService().storeSecret(
"my.secret",
mySecretText.toByteArray().toBase64NoPadding(),
- listOf(SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)))
+ listOf(KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)))
)
}
@@ -275,13 +266,9 @@ class QuadSTests : InstrumentedTest {
)
)
}
-
- testHelper.signOutAndClose(aliceSession)
}
- private fun assertAccountData(session: Session, type: String): UserAccountDataEvent {
- val testHelper = CommonTestHelper(context())
-
+ private fun assertAccountData(testHelper: CommonTestHelper, session: Session, type: String): UserAccountDataEvent {
var accountData: UserAccountDataEvent? = null
testHelper.waitWithLatch {
val liveAccountData = session.accountDataService().getLiveUserAccountDataEvent(type)
@@ -297,29 +284,27 @@ class QuadSTests : InstrumentedTest {
return accountData!!
}
- private fun generatedSecret(session: Session, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
+ private fun generatedSecret(testHelper: CommonTestHelper, session: Session, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
val quadS = session.sharedSecretStorageService()
- val testHelper = CommonTestHelper(context())
val creationInfo = testHelper.runBlockingTest {
quadS.generateKey(keyId, null, keyId, emptyKeySigner)
}
- assertAccountData(session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
+ assertAccountData(testHelper, session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
if (asDefault) {
testHelper.runBlockingTest {
quadS.setDefaultKey(keyId)
}
- assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
+ assertAccountData(testHelper, session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
}
return creationInfo
}
- private fun generatedSecretFromPassphrase(session: Session, passphrase: String, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
+ private fun generatedSecretFromPassphrase(testHelper: CommonTestHelper, session: Session, passphrase: String, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
val quadS = session.sharedSecretStorageService()
- val testHelper = CommonTestHelper(context())
val creationInfo = testHelper.runBlockingTest {
quadS.generateKeyWithPassphrase(
@@ -331,12 +316,12 @@ class QuadSTests : InstrumentedTest {
)
}
- assertAccountData(session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
+ assertAccountData(testHelper, session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
if (asDefault) {
testHelper.runBlockingTest {
quadS.setDefaultKey(keyId)
}
- assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
+ assertAccountData(testHelper, session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
}
return creationInfo
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 2892cf8464..d524774a35 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
@@ -44,8 +44,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransa
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.toModel
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationCancel
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationStart
import org.matrix.android.sdk.internal.crypto.model.rest.toValue
@@ -53,12 +52,11 @@ import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Ignore
class SASTest : InstrumentedTest {
@Test
- fun test_aliceStartThenAliceCancel() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_aliceStartThenAliceCancel() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
@@ -135,15 +133,11 @@ class SASTest : InstrumentedTest {
assertNull(bobVerificationService.getExistingTransaction(aliceSession.myUserId, txID))
assertNull(aliceVerificationService.getExistingTransaction(bobSession.myUserId, txID))
-
- cryptoTestData.cleanUp(testHelper)
}
@Test
@Ignore("This test will be ignored until it is fixed")
- fun test_key_agreement_protocols_must_include_curve25519() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_key_agreement_protocols_must_include_curve25519() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
fail("Not passing for the moment")
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
@@ -195,15 +189,11 @@ class SASTest : InstrumentedTest {
testHelper.await(cancelLatch)
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod, cancelReason)
-
- cryptoTestData.cleanUp(testHelper)
}
@Test
@Ignore("This test will be ignored until it is fixed")
- fun test_key_agreement_macs_Must_include_hmac_sha256() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_key_agreement_macs_Must_include_hmac_sha256() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
fail("Not passing for the moment")
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
@@ -236,15 +226,11 @@ class SASTest : InstrumentedTest {
val cancelReq = canceledToDeviceEvent!!.content.toModel()!!
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
-
- cryptoTestData.cleanUp(testHelper)
}
@Test
@Ignore("This test will be ignored until it is fixed")
- fun test_key_agreement_short_code_include_decimal() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_key_agreement_short_code_include_decimal() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
fail("Not passing for the moment")
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
@@ -277,18 +263,18 @@ class SASTest : InstrumentedTest {
val cancelReq = canceledToDeviceEvent!!.content.toModel()!!
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
-
- cryptoTestData.cleanUp(testHelper)
}
- 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(),
@@ -314,9 +300,7 @@ class SASTest : InstrumentedTest {
// any two devices may only have at most one key verification in flight at a time.
// If a device has two verifications in progress with the same device, then it should cancel both verifications.
@Test
- fun test_aliceStartTwoRequests() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_aliceStartTwoRequests() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
@@ -357,9 +341,7 @@ class SASTest : InstrumentedTest {
*/
@Test
@Ignore("This test will be ignored until it is fixed")
- fun test_aliceAndBobAgreement() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_aliceAndBobAgreement() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
@@ -413,14 +395,10 @@ class SASTest : InstrumentedTest {
accepted!!.shortAuthenticationStrings.forEach {
assertTrue("all agreed Short Code should be known by alice", startReq!!.shortAuthenticationStrings.contains(it))
}
-
- cryptoTestData.cleanUp(testHelper)
}
@Test
- fun test_aliceAndBobSASCode() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_aliceAndBobSASCode() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
@@ -473,14 +451,10 @@ class SASTest : InstrumentedTest {
"Should have same SAS", aliceTx.getShortCodeRepresentation(SasMode.DECIMAL),
bobTx.getShortCodeRepresentation(SasMode.DECIMAL)
)
-
- cryptoTestData.cleanUp(testHelper)
}
@Test
- fun test_happyPath() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_happyPath() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
@@ -553,13 +527,10 @@ class SASTest : InstrumentedTest {
assertTrue("alice device should be verified from bob point of view", aliceDeviceInfoFromBobPOV!!.isVerified)
assertTrue("bob device should be verified from alice point of view", bobDeviceInfoFromAlicePOV!!.isVerified)
- cryptoTestData.cleanUp(testHelper)
}
@Test
- fun test_ConcurrentStart() {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(testHelper)
+ fun test_ConcurrentStart() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
@@ -646,7 +617,5 @@ class SASTest : InstrumentedTest {
bobPovTx?.state == VerificationTxState.ShortCodeReady
}
}
-
- cryptoTestData.cleanUp(testHelper)
}
}
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 ceebc3cd01..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
@@ -31,8 +32,8 @@ import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
import java.util.concurrent.CountDownLatch
@@ -41,6 +42,7 @@ import kotlin.coroutines.resume
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
+@Ignore
class VerificationTest : InstrumentedTest {
data class ExpectedResult(
@@ -151,12 +153,12 @@ class VerificationTest : InstrumentedTest {
// TODO Add tests without SAS
- private fun doTest(aliceSupportedMethods: List,
- bobSupportedMethods: List,
- expectedResultForAlice: ExpectedResult,
- expectedResultForBob: ExpectedResult) {
- val testHelper = CommonTestHelper(context())
- val cryptoTestHelper = 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
@@ -251,14 +253,11 @@ class VerificationTest : InstrumentedTest {
pr.otherCanShowQrCode() shouldBe expectedResultForBob.otherCanShowQrCode
pr.otherCanScanQrCode() shouldBe expectedResultForBob.otherCanScanQrCode
}
-
- cryptoTestData.cleanUp(testHelper)
}
@Test
- fun test_selfVerificationAcceptedCancelsItForOtherSessions() {
+ fun test_selfVerificationAcceptedCancelsItForOtherSessions() = runSessionTest(context()) { testHelper ->
val defaultSessionParams = SessionTestParams(true)
- val testHelper = CommonTestHelper(context())
val aliceSessionToVerify = testHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams)
val aliceSessionThatVerifies = testHelper.logIntoAccount(aliceSessionToVerify.myUserId, TestConstants.PASSWORD, defaultSessionParams)
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/session/room/threads/ThreadMessagingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt
index a2984dd27e..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
@@ -34,8 +34,7 @@ import org.matrix.android.sdk.api.session.events.model.isThread
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
import java.util.concurrent.CountDownLatch
@RunWith(JUnit4::class)
@@ -44,9 +43,7 @@ import java.util.concurrent.CountDownLatch
class ThreadMessagingTest : InstrumentedTest {
@Test
- fun reply_in_thread_should_create_a_thread() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun reply_in_thread_should_create_a_thread() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
val aliceSession = cryptoTestData.firstSession
@@ -86,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 ->
@@ -100,13 +97,11 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
- aliceSession.stopSync()
+ aliceSession.syncService().stopSync()
}
@Test
- fun reply_in_thread_should_create_a_thread_from_other_user() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun reply_in_thread_should_create_a_thread_from_other_user() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
val aliceSession = cryptoTestData.firstSession
@@ -149,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 ->
@@ -161,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 ->
@@ -175,13 +170,11 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
- bobSession.stopSync()
+ bobSession.syncService().stopSync()
}
@Test
- fun reply_in_thread_to_timeline_message_multiple_times() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun reply_in_thread_to_timeline_message_multiple_times() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
val aliceSession = cryptoTestData.firstSession
@@ -224,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 ->
@@ -240,13 +233,11 @@ class ThreadMessagingTest : InstrumentedTest {
timeline.addListener(eventsListener)
commonTestHelper.await(lock, 600_000)
}
- aliceSession.stopSync()
+ aliceSession.syncService().stopSync()
}
@Test
- fun thread_summary_advanced_validation_after_multiple_messages_in_multiple_threads() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun thread_summary_advanced_validation_after_multiple_messages_in_multiple_threads() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
val aliceSession = cryptoTestData.firstSession
@@ -323,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 ->
@@ -347,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..986d58741c 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
@@ -154,9 +154,11 @@ internal class ChunkEntityTest : InstrumentedTest {
}
}
- 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 61ab6d4b40..5252e50e15 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
@@ -38,8 +38,7 @@ import org.matrix.android.sdk.api.session.room.model.message.PollType
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
import java.util.concurrent.CountDownLatch
@RunWith(JUnit4::class)
@@ -47,9 +46,7 @@ import java.util.concurrent.CountDownLatch
class PollAggregationTest : InstrumentedTest {
@Test
- fun testAllPollUseCases() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun testAllPollUseCases() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
val aliceSession = cryptoTestData.firstSession
@@ -60,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()
@@ -136,9 +133,8 @@ class PollAggregationTest : InstrumentedTest {
aliceTimeline.removeAllListeners()
- aliceSession.stopSync()
+ aliceSession.syncService().stopSync()
aliceTimeline.dispose()
- cryptoTestData.cleanUp(commonTestHelper)
}
private fun testInitialPollConditions(pollContent: MessagePollContent, pollSummary: PollResponseAggregatedSummary?) {
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 e407c1b42d..3dd3f5fa2a 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
@@ -34,8 +34,7 @@ import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
import org.matrix.android.sdk.common.checkSendOrder
import timber.log.Timber
import java.util.concurrent.CountDownLatch
@@ -53,9 +52,7 @@ class TimelineForwardPaginationTest : InstrumentedTest {
* This test ensure that if we click to permalink, we will be able to go back to the live
*/
@Test
- fun forwardPaginationTest() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun forwardPaginationTest() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val numberOfMessagesToSend = 90
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
@@ -177,7 +174,5 @@ class TimelineForwardPaginationTest : InstrumentedTest {
}
aliceTimeline.dispose()
-
- cryptoTestData.cleanUp(commonTestHelper)
}
}
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 1a36adec44..03ab6e6767 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
@@ -33,7 +33,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.common.checkSendOrder
import timber.log.Timber
import java.util.concurrent.CountDownLatch
@@ -48,9 +47,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
*/
@Test
- fun previousLastForwardTest() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun previousLastForwardTest() = CommonTestHelper.runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
val aliceSession = cryptoTestData.firstSession
@@ -91,7 +88,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
}
// Bob stop to sync
- bobSession.stopSync()
+ bobSession.syncService().stopSync()
val firstMessage = "First messages from Alice"
// Alice sends 30 messages
@@ -104,7 +101,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
.eventId
// Bob start to sync
- bobSession.startSync(true)
+ bobSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
@@ -128,7 +125,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
}
// Bob stop to sync
- bobSession.stopSync()
+ bobSession.syncService().stopSync()
val secondMessage = "Second messages from Alice"
// Alice sends again 30 messages
@@ -139,7 +136,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
)
// Bob start to sync
- bobSession.startSync(true)
+ bobSession.syncService().startSync(true)
run {
val lock = CountDownLatch(1)
@@ -242,7 +239,5 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
}
bobTimeline.dispose()
-
- cryptoTestData.cleanUp(commonTestHelper)
}
}
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 42f710d7cf..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
@@ -32,19 +33,17 @@ import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
import org.matrix.android.sdk.common.TestConstants
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@LargeTest
+@Ignore
class TimelineSimpleBackPaginationTest : InstrumentedTest {
@Test
- fun timeline_backPaginate_shouldReachEndOfTimeline() {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ fun timeline_backPaginate_shouldReachEndOfTimeline() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val numberOfMessagesToSent = 200
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
@@ -102,6 +101,5 @@ class TimelineSimpleBackPaginationTest : InstrumentedTest {
assertEquals(numberOfMessagesToSent, onlySentEvents.size)
bobTimeline.dispose()
- cryptoTestData.cleanUp(commonTestHelper)
}
}
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 02430dda74..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
@@ -30,8 +30,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
import java.util.concurrent.CountDownLatch
/** !! Not working with the new timeline
@@ -47,15 +46,12 @@ class TimelineWithManyMembersTest : InstrumentedTest {
private const val NUMBER_OF_MEMBERS = 6
}
- private val commonTestHelper = CommonTestHelper(context())
- private val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
-
/**
* Ensures when someone sends a message to a crowded room, everyone can decrypt the message.
*/
@Test
- fun everyone_should_decrypt_message_in_a_crowded_room() {
+ fun everyone_should_decrypt_message_in_a_crowded_room() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithManyMembers(NUMBER_OF_MEMBERS)
val sessionForFirstMember = cryptoTestData.firstSession
@@ -75,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)
@@ -96,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/search/SearchMessagesTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt
index e17b7efbd6..7c97426c39 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt
@@ -26,9 +26,8 @@ import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.search.SearchResult
-import org.matrix.android.sdk.common.CommonTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
import org.matrix.android.sdk.common.CryptoTestData
-import org.matrix.android.sdk.common.CryptoTestHelper
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@@ -74,9 +73,7 @@ class SearchMessagesTest : InstrumentedTest {
}
}
- private fun doTest(block: suspend (CryptoTestData) -> SearchResult) {
- val commonTestHelper = CommonTestHelper(context())
- val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
+ private fun doTest(block: suspend (CryptoTestData) -> SearchResult) = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
val aliceSession = cryptoTestData.firstSession
val aliceRoomId = cryptoTestData.roomId
@@ -99,7 +96,5 @@ class SearchMessagesTest : InstrumentedTest {
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
}.orFalse()
)
-
- cryptoTestData.cleanUp(commonTestHelper)
}
}
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 b9760c1bfc..0cc0ef57c4 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,6 +22,7 @@ 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
@@ -40,7 +41,7 @@ import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
import org.matrix.android.sdk.api.session.space.JoinSpaceResult
-import org.matrix.android.sdk.common.CommonTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
import org.matrix.android.sdk.common.SessionTestParams
@RunWith(JUnit4::class)
@@ -49,8 +50,7 @@ import org.matrix.android.sdk.common.SessionTestParams
class SpaceCreationTest : InstrumentedTest {
@Test
- fun createSimplePublicSpace() {
- val commonTestHelper = CommonTestHelper(context())
+ fun createSimplePublicSpace() = runSessionTest(context()) { commonTestHelper ->
val session = commonTestHelper.createAccount("Hubble", SessionTestParams(true))
val roomName = "My Space"
val topic = "A public space for test"
@@ -96,13 +96,11 @@ class SpaceCreationTest : InstrumentedTest {
?.toModel()?.historyVisibility
assertEquals("Public space room should be world readable", RoomHistoryVisibility.WORLD_READABLE, historyVisibility)
-
- commonTestHelper.signOutAndClose(session)
}
@Test
- fun testJoinSimplePublicSpace() {
- val commonTestHelper = CommonTestHelper(context())
+ @Ignore
+ fun testJoinSimplePublicSpace() = runSessionTest(context()) { commonTestHelper ->
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
val bobSession = commonTestHelper.createAccount("bob", SessionTestParams(true))
@@ -134,8 +132,7 @@ class SpaceCreationTest : InstrumentedTest {
}
@Test
- fun testSimplePublicSpaceWithChildren() {
- val commonTestHelper = CommonTestHelper(context())
+ fun testSimplePublicSpaceWithChildren() = runSessionTest(context()) { commonTestHelper ->
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
val bobSession = commonTestHelper.createAccount("bob", SessionTestParams(true))
@@ -204,8 +201,5 @@ class SpaceCreationTest : InstrumentedTest {
// ).size
//
// assertEquals("Unexpected number of joined children", 1, childCount)
-
- commonTestHelper.signOutAndClose(aliceSession)
- commonTestHelper.signOutAndClose(bobSession)
}
}
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 6a17cb74ad..5396251438 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
@@ -29,8 +29,8 @@ 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.ActiveSpaceFilter
import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.query.SpaceFilter
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toContent
@@ -48,6 +48,7 @@ import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
import org.matrix.android.sdk.api.session.room.powerlevels.Role
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
import org.matrix.android.sdk.common.CommonTestHelper
+import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
import org.matrix.android.sdk.common.SessionTestParams
@RunWith(JUnit4::class)
@@ -55,8 +56,7 @@ import org.matrix.android.sdk.common.SessionTestParams
class SpaceHierarchyTest : InstrumentedTest {
@Test
- fun createCanonicalChildRelation() {
- val commonTestHelper = CommonTestHelper(context())
+ fun createCanonicalChildRelation() = runSessionTest(context()) { commonTestHelper ->
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
val spaceName = "My Space"
@@ -173,8 +173,7 @@ class SpaceHierarchyTest : InstrumentedTest {
// }
@Test
- fun testFilteringBySpace() {
- val commonTestHelper = CommonTestHelper(context())
+ fun testFilteringBySpace() = CommonTestHelper.runSessionTest(context()) { commonTestHelper ->
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
val spaceAInfo = createPublicSpace(
@@ -185,12 +184,12 @@ class SpaceHierarchyTest : InstrumentedTest {
)
/* val spaceBInfo = */ createPublicSpace(
- session, "SpaceB", listOf(
- Triple("B1", true /*auto-join*/, true/*canonical*/),
- Triple("B2", true, true),
- Triple("B3", true, true)
- )
- )
+ session, "SpaceB", listOf(
+ Triple("B1", true /*auto-join*/, true/*canonical*/),
+ Triple("B2", true, true),
+ Triple("B3", true, true)
+ )
+ )
val spaceCInfo = createPublicSpace(
session, "SpaceC", listOf(
@@ -249,15 +248,14 @@ class SpaceHierarchyTest : InstrumentedTest {
Thread.sleep(6_000)
val orphansUpdate = session.roomService().getRoomSummaries(roomSummaryQueryParams {
- activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(null)
+ spaceFilter = SpaceFilter.OrphanRooms
})
assertEquals("Unexpected number of orphan rooms ${orphansUpdate.map { it.name }}", 2, orphansUpdate.size)
}
@Test
@Ignore("This test will be ignored until it is fixed")
- fun testBreakCycle() {
- val commonTestHelper = CommonTestHelper(context())
+ fun testBreakCycle() = CommonTestHelper.runSessionTest(context()) { commonTestHelper ->
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
val spaceAInfo = createPublicSpace(
@@ -302,8 +300,7 @@ class SpaceHierarchyTest : InstrumentedTest {
}
@Test
- fun testLiveFlatChildren() {
- val commonTestHelper = CommonTestHelper(context())
+ fun testLiveFlatChildren() = CommonTestHelper.runSessionTest(context()) { commonTestHelper ->
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
val spaceAInfo = createPublicSpace(
@@ -390,84 +387,87 @@ 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 {
- val commonTestHelper = CommonTestHelper(context())
var spaceId = ""
var roomIds: List = emptyList()
- commonTestHelper.waitWithLatch { latch ->
- spaceId = session.spaceService().createSpace(spaceName, "Test Topic", null, true)
- val syncedSpace = session.spaceService().getSpace(spaceId)
- val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
+ runSessionTest(context()) { commonTestHelper ->
+ commonTestHelper.waitWithLatch { latch ->
+ spaceId = session.spaceService().createSpace(spaceName, "Test Topic", null, true)
+ val syncedSpace = session.spaceService().getSpace(spaceId)
+ val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
- roomIds = childInfo.map { entry ->
- session.roomService().createRoom(CreateRoomParams().apply { name = entry.first })
- }
- roomIds.forEachIndexed { index, roomId ->
- syncedSpace!!.addChildren(roomId, viaServers, null, childInfo[index].second)
- val canonical = childInfo[index].third
- if (canonical != null) {
- session.spaceService().setSpaceParent(roomId, spaceId, canonical, viaServers)
+ roomIds = childInfo.map { entry ->
+ session.roomService().createRoom(CreateRoomParams().apply { name = entry.first })
}
+ roomIds.forEachIndexed { index, roomId ->
+ syncedSpace!!.addChildren(roomId, viaServers, null, childInfo[index].second)
+ val canonical = childInfo[index].third
+ if (canonical != null) {
+ session.spaceService().setSpaceParent(roomId, spaceId, canonical, viaServers)
+ }
+ }
+ latch.countDown()
}
- latch.countDown()
}
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 {
- val commonTestHelper = CommonTestHelper(context())
var spaceId = ""
var roomIds: List = emptyList()
- commonTestHelper.waitWithLatch { latch ->
- spaceId = session.spaceService().createSpace(spaceName, "My Private Space", null, false)
- val syncedSpace = session.spaceService().getSpace(spaceId)
- val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
- roomIds =
- childInfo.map { entry ->
- val homeServerCapabilities = session
- .homeServerCapabilitiesService()
- .getHomeServerCapabilities()
- session.roomService().createRoom(CreateRoomParams().apply {
- name = entry.first
- this.featurePreset = RestrictedRoomPreset(
- homeServerCapabilities,
- listOf(
- RoomJoinRulesAllowEntry.restrictedToRoom(spaceId)
- )
- )
- })
+ runSessionTest(context()) { commonTestHelper ->
+ commonTestHelper.waitWithLatch { latch ->
+ spaceId = session.spaceService().createSpace(spaceName, "My Private Space", null, false)
+ val syncedSpace = session.spaceService().getSpace(spaceId)
+ val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
+ roomIds =
+ childInfo.map { entry ->
+ val homeServerCapabilities = session
+ .homeServerCapabilitiesService()
+ .getHomeServerCapabilities()
+ session.roomService().createRoom(CreateRoomParams().apply {
+ name = entry.first
+ this.featurePreset = RestrictedRoomPreset(
+ homeServerCapabilities,
+ listOf(
+ RoomJoinRulesAllowEntry.restrictedToRoom(spaceId)
+ )
+ )
+ })
+ }
+ roomIds.forEachIndexed { index, roomId ->
+ syncedSpace!!.addChildren(roomId, viaServers, null, childInfo[index].second)
+ val canonical = childInfo[index].third
+ if (canonical != null) {
+ session.spaceService().setSpaceParent(roomId, spaceId, canonical, viaServers)
}
- roomIds.forEachIndexed { index, roomId ->
- syncedSpace!!.addChildren(roomId, viaServers, null, childInfo[index].second)
- val canonical = childInfo[index].third
- if (canonical != null) {
- session.spaceService().setSpaceParent(roomId, spaceId, canonical, viaServers)
}
+ latch.countDown()
}
- latch.countDown()
}
return TestSpaceCreationResult(spaceId, roomIds)
}
@Test
- fun testRootSpaces() {
- val commonTestHelper = CommonTestHelper(context())
+ fun testRootSpaces() = runSessionTest(context()) { commonTestHelper ->
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
/* val spaceAInfo = */ createPublicSpace(
- session, "SpaceA", listOf(
- Triple("A1", true /*auto-join*/, true/*canonical*/),
- Triple("A2", true, true)
- )
- )
+ session, "SpaceA", listOf(
+ Triple("A1", true /*auto-join*/, true/*canonical*/),
+ Triple("A2", true, true)
+ )
+ )
val spaceBInfo = createPublicSpace(
session, "SpaceB", listOf(
@@ -506,13 +506,10 @@ class SpaceHierarchyTest : InstrumentedTest {
}
assertEquals("Unexpected number of root spaces ${rootSpaces.map { it.name }}", 2, rootSpaces.size)
-
- commonTestHelper.signOutAndClose(session)
}
@Test
- fun testParentRelation() {
- val commonTestHelper = CommonTestHelper(context())
+ fun testParentRelation() = runSessionTest(context()) { commonTestHelper ->
val aliceSession = commonTestHelper.createAccount("Alice", SessionTestParams(true))
val bobSession = commonTestHelper.createAccount("Bib", SessionTestParams(true))
@@ -604,8 +601,5 @@ class SpaceHierarchyTest : InstrumentedTest {
bobSession.getRoomSummary(bobRoomId)?.flattenParentIds?.contains(spaceAInfo.spaceId) == true
}
}
-
- commonTestHelper.signOutAndClose(aliceSession)
- commonTestHelper.signOutAndClose(bobSession)
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/RoomDisplayNameFallbackProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/RoomDisplayNameFallbackProvider.kt
index a34dbcc196..3c376b55ee 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/RoomDisplayNameFallbackProvider.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/RoomDisplayNameFallbackProvider.kt
@@ -16,6 +16,14 @@
package org.matrix.android.sdk.api
+/**
+ * This interface exists to let the implementation provide localized room display name fallback.
+ * The methods can be called when the room has no name, i.e. its `m.room.name` state event does not exist or
+ * the name in it is an empty String.
+ * It allows the SDK to store the room name fallback into the local storage and so let the client do
+ * queries on the room name.
+ * *Limitation*: if the locale of the device changes, the methods will not be called again.
+ */
interface RoomDisplayNameFallbackProvider {
fun getNameForRoomInvite(): String
fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List): String
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 5a19df90c4..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
@@ -66,7 +68,7 @@ interface AuthenticationService {
/**
* True when login and password has been sent with success to the homeserver.
*/
- val isRegistrationStarted: Boolean
+ fun isRegistrationStarted(): Boolean
/**
* Cancel pending login or pending registration.
@@ -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..c840a7453d 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")
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..5b8d2328c7 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,14 @@ 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
*/
- suspend fun resetPasswordMailConfirmed()
+ suspend fun resetPasswordMailConfirmed(newPassword: String)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt
index 439b4beb41..9e6b2b3ad9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationResult.kt
@@ -18,13 +18,31 @@ package org.matrix.android.sdk.api.auth.registration
import org.matrix.android.sdk.api.session.Session
-// Either a session or an object containing data about registration stages
+/**
+ * Either a session or an object containing data about registration stages.
+ */
sealed class RegistrationResult {
+ /**
+ * The registration is successful, the [Session] is provided.
+ */
data class Success(val session: Session) : RegistrationResult()
+
+ /**
+ * The registration still miss some steps. See [FlowResult] to know the details.
+ */
data class FlowResponse(val flowResult: FlowResult) : RegistrationResult()
}
+/**
+ * Information about the missing and completed [Stage].
+ */
data class FlowResult(
+ /**
+ * List of missing stages.
+ */
val missingStages: List,
+ /**
+ * List of completed stages.
+ */
val completedStages: List
)
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 0cda64499f..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.
@@ -109,14 +111,14 @@ interface RegistrationWizard {
suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult
/**
- * This is the current ThreePid, waiting for validation. The SDK will store it in database, so it can be
+ * Returns the current ThreePid, waiting for validation. The SDK will store it in database, so it can be
* restored even if the app has been killed during the registration
*/
- val currentThreePid: String?
+ fun getCurrentThreePid(): String?
/**
- * True when login and password have been sent with success to the homeserver, i.e. [createAccount] has been
+ * Return true when login and password have been sent with success to the homeserver, i.e. [createAccount] has been
* called successfully.
*/
- val isRegistrationStarted: Boolean
+ fun isRegistrationStarted(): Boolean
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt
index c21b667cf7..281b0c2808 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/Stage.kt
@@ -16,25 +16,40 @@
package org.matrix.android.sdk.api.auth.registration
+/**
+ * Registration stages.
+ */
sealed class Stage(open val mandatory: Boolean) {
- // m.login.recaptcha
+ /**
+ * m.login.recaptcha stage.
+ */
data class ReCaptcha(override val mandatory: Boolean, val publicKey: String) : Stage(mandatory)
- // m.login.email.identity
+ /**
+ * m.login.email.identity stage.
+ */
data class Email(override val mandatory: Boolean) : Stage(mandatory)
- // m.login.msisdn
+ /**
+ * m.login.msisdn stage.
+ */
data class Msisdn(override val mandatory: Boolean) : Stage(mandatory)
- // m.login.dummy, can be mandatory if there is no other stages. In this case the account cannot be created by just sending a username
- // and a password, the dummy stage has to be done
+ /**
+ * m.login.dummy, can be mandatory if there is no other stages. In this case the account cannot be created by just sending a username
+ * and a password, the dummy stage has to be done.
+ */
data class Dummy(override val mandatory: Boolean) : Stage(mandatory)
- // Undocumented yet: m.login.terms
+ /**
+ * Undocumented yet: m.login.terms stage.
+ */
data class Terms(override val mandatory: Boolean, val policies: TermPolicies) : Stage(mandatory)
- // For unknown stages
+ /**
+ * For unknown stages.
+ */
data class Other(override val mandatory: Boolean, val type: String, val params: Map<*, *>?) : Stage(mandatory)
}
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/cache/CacheStrategy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/cache/CacheStrategy.kt
index 2880d851d6..ddf76d6e42 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/cache/CacheStrategy.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/cache/CacheStrategy.kt
@@ -17,13 +17,19 @@
package org.matrix.android.sdk.api.cache
sealed class CacheStrategy {
- // Data is always fetched from the server
+ /**
+ * Data is always fetched from the server.
+ */
object NoCache : CacheStrategy()
- // Once data is retrieved, it is stored for the provided amount of time.
- // In case of error, and if strict is set to false, the cache can be returned if available
+ /**
+ * Once data is retrieved, it is stored for the provided amount of time.
+ * In case of error, and if strict is set to false, the cache can be returned if available
+ */
data class TtlCache(val validityDurationInMillis: Long, val strict: Boolean) : CacheStrategy()
- // Once retrieved, the data is stored in cache and will be always get from the cache
+ /**
+ * Once retrieved, the data is stored in cache and will be always get from the cache.
+ */
object InfiniteCache : CacheStrategy()
}
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..2a8848e80a 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
@@ -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/failure/Failure.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt
index be139fd82b..7d4f553bed 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt
@@ -37,7 +37,9 @@ sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) {
data class ServerError(val error: MatrixError, val httpCode: Int) : Failure(RuntimeException(error.toString()))
object SuccessError : Failure(RuntimeException(RuntimeException("SuccessResult is false")))
- // When server send an error, but it cannot be interpreted as a MatrixError
+ /**
+ * When server send an error, but it cannot be interpreted as a MatrixError.
+ */
data class OtherServerError(val errorBody: String, val httpCode: Int) : Failure(RuntimeException("HTTP $httpCode: $errorBody"))
data class RegistrationFlowError(val registrationFlowResponse: RegistrationFlowResponse) : Failure(RuntimeException(registrationFlowResponse.toString()))
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 368ff98661..f08c86885d 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
@@ -20,20 +20,52 @@ package org.matrix.android.sdk.api.query
* Basic query language. All these cases are mutually exclusive.
*/
sealed interface QueryStringValue {
+ /**
+ * No condition, i.e. there will be no test on the tested field.
+ */
+ object NoCondition : QueryStringValue
+
+ /**
+ * The tested field has to be null.
+ */
+ object IsNull : QueryStringValue
+
+ /**
+ * The tested field has to be not null.
+ */
+ object IsNotNull : QueryStringValue
+
+ /**
+ * The tested field has to be empty.
+ */
+ object IsEmpty : QueryStringValue
+
+ /**
+ * The tested field has to not empty.
+ */
+ object IsNotEmpty : QueryStringValue
+
+ /**
+ * Interface to check String content.
+ */
sealed interface ContentQueryStringValue : QueryStringValue {
val string: String
val case: Case
}
- object NoCondition : QueryStringValue
- object IsNull : QueryStringValue
- object IsNotNull : QueryStringValue
- object IsEmpty : QueryStringValue
- object IsNotEmpty : QueryStringValue
-
+ /**
+ * The tested field must match the [string].
+ */
data class Equals(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue
+
+ /**
+ * The tested field must contain the [string].
+ */
data class Contains(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue
+ /**
+ * Case enum for [ContentQueryStringValue].
+ */
enum class Case {
/**
* Match query sensitive to case.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/RoomCategoryFilter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/RoomCategoryFilter.kt
index c8ccc4c8a3..c2117adbd3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/RoomCategoryFilter.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/RoomCategoryFilter.kt
@@ -16,9 +16,23 @@
package org.matrix.android.sdk.api.query
+/**
+ * To filter by Room category.
+ * @see [org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams]
+ */
enum class RoomCategoryFilter {
+ /**
+ * Get only the DM, i.e. the rooms referenced in `m.direct` account data.
+ */
ONLY_DM,
+
+ /**
+ * Get only the Room, not the DM, i.e. the rooms not referenced in `m.direct` account data.
+ */
ONLY_ROOMS,
+
+ /**
+ * Get the room with non-0 notifications.
+ */
ONLY_WITH_NOTIFICATIONS,
- ALL
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/RoomTagQueryFilter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/RoomTagQueryFilter.kt
index 613916bc18..73947f8f7a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/RoomTagQueryFilter.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/RoomTagQueryFilter.kt
@@ -16,8 +16,22 @@
package org.matrix.android.sdk.api.query
+/**
+ * Filter room by their tag.
+ * @see [org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams]
+ * @see [org.matrix.android.sdk.api.session.room.model.tag.RoomTag]
+ */
data class RoomTagQueryFilter(
+ /**
+ * Set to true to get the rooms which have the tag "m.favourite".
+ */
val isFavorite: Boolean?,
+ /**
+ * Set to true to get the rooms which have the tag "m.lowpriority".
+ */
val isLowPriority: Boolean?,
- val isServerNotice: Boolean?
+ /**
+ * Set to true to get the rooms which have the tag "m.server_notice".
+ */
+ val isServerNotice: Boolean?,
)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/SpaceFilter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/SpaceFilter.kt
new file mode 100644
index 0000000000..6383412ffb
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/SpaceFilter.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 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.query
+
+/**
+ * Filter to be used to do room queries regarding the space hierarchy.
+ * @see [org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams]
+ */
+sealed interface SpaceFilter {
+ /**
+ * Used to get all the rooms that are not in any space.
+ */
+ object OrphanRooms : SpaceFilter
+
+ /**
+ * Used to get all the rooms that have the provided space in their parent hierarchy.
+ */
+ data class ActiveSpace(val spaceId: String) : SpaceFilter
+
+ /**
+ * Used to get all the rooms that do not have the provided space in their parent hierarchy.
+ */
+ data class ExcludeSpace(val spaceId: String) : SpaceFilter
+}
+
+/**
+ * Return a [SpaceFilter.ActiveSpace] if the String is not null, or [SpaceFilter.OrphanRooms].
+ */
+fun String?.toActiveSpaceOrOrphanRooms(): SpaceFilter = this?.let { SpaceFilter.ActiveSpace(it) } ?: SpaceFilter.OrphanRooms
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..b3a629094c 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,6 @@
package org.matrix.android.sdk.api.session
import androidx.annotation.MainThread
-import androidx.lifecycle.LiveData
-import kotlinx.coroutines.flow.SharedFlow
import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.auth.data.SessionParams
@@ -37,7 +35,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
@@ -55,8 +52,7 @@ 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,9 +195,9 @@ interface Session {
fun termsService(): TermsService
/**
- * Returns the SyncStatusService associated with the session.
+ * Returns the SyncService associated with the session.
*/
- fun syncStatusService(): SyncStatusService
+ fun syncService(): SyncService
/**
* Returns the SecureStorageService associated with the session.
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..e3d52adfc5 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
@@ -27,8 +27,10 @@ interface AccountService {
* @param password Current password.
* @param newPassword New password
*/
- suspend fun changePassword(password: String,
- newPassword: String)
+ suspend fun changePassword(
+ password: String,
+ newPassword: String
+ )
/**
* 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..9cc87b6f71 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)
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/KeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt
index 9029c7f8a3..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,11 +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 onSecretKeyGossip(secret: String)
+ fun trustKeysBackupVersionWithPassphrase(
+ keysBackupVersion: KeysVersionResult,
+ password: String,
+ callback: MatrixCallback
+ )
/**
* Restore a backup with a recovery key from a given backup version stored on the homeserver.
@@ -180,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.
@@ -196,18 +215,23 @@ 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?
+
val currentBackupVersion: String?
- val isEnabled: Boolean
- val isStucked: Boolean
- val state: KeysBackupState
+ get() = keysBackupVersion?.version
+
+ fun isEnabled(): Boolean
+ fun isStuck(): Boolean
+ fun getState(): KeysBackupState
// For gossiping
fun saveBackupRecoveryKey(recoveryKey: String?, version: String?)
@@ -215,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/KeysBackupState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupState.kt
index a4cc133398..a867d573de 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupState.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupState.kt
@@ -51,33 +51,51 @@ package org.matrix.android.sdk.api.session.crypto.keysbackup
*
*/
enum class KeysBackupState {
- // Need to check the current backup version on the homeserver
+ /**
+ * Need to check the current backup version on the homeserver.
+ */
Unknown,
- // Checking if backup is enabled on homeserver
+ /**
+ * Checking if backup is enabled on homeserver.
+ */
CheckingBackUpOnHomeserver,
- // Backup has been stopped because a new backup version has been detected on the homeserver
+ /**
+ * Backup has been stopped because a new backup version has been detected on the homeserver.
+ */
WrongBackUpVersion,
- // Backup from this device is not enabled
+ /**
+ * Backup from this device is not enabled.
+ */
Disabled,
- // There is a backup available on the homeserver but it is not trusted.
- // It is not trusted because the signature is invalid or the device that created it is not verified
- // Use [KeysBackup.getKeysBackupTrust()] to get trust details.
- // Consequently, the backup from this device is not enabled.
+ /**
+ * There is a backup available on the homeserver but it is not trusted.
+ * It is not trusted because the signature is invalid or the device that created it is not verified.
+ * Use [KeysBackup.getKeysBackupTrust()] to get trust details.
+ * Consequently, the backup from this device is not enabled.
+ */
NotTrusted,
- // Backup is being enabled: the backup version is being created on the homeserver
+ /**
+ * Backup is being enabled: the backup version is being created on the homeserver.
+ */
Enabling,
- // Backup is enabled and ready to send backup to the homeserver
+ /**
+ * Backup is enabled and ready to send backup to the homeserver.
+ */
ReadyToBackUp,
- // e2e keys are going to be sent to the homeserver
+ /**
+ * e2e keys are going to be sent to the homeserver.
+ */
WillBackUp,
- // e2e keys are being sent to the homeserver
+ /**
+ * e2e keys are being sent to the homeserver.
+ */
BackingUp
}
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/model/RoomEncryptionTrustLevel.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt
index 68c7496d58..78724819a3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt
@@ -20,15 +20,23 @@ package org.matrix.android.sdk.api.session.crypto.model
* RoomEncryptionTrustLevel represents the trust level in an encrypted room.
*/
enum class RoomEncryptionTrustLevel {
- // No one in the room has been verified -> Black shield
+ /**
+ * No one in the room has been verified -> Black shield.
+ */
Default,
- // There are one or more device un-verified -> the app should display a red shield
+ /**
+ * There are one or more device un-verified -> the app should display a red shield.
+ */
Warning,
- // All devices in the room are verified -> the app should display a green shield
+ /**
+ * All devices in the room are verified -> the app should display a green shield.
+ */
Trusted,
- // e2e is active but with an unsupported algorithm
+ /**
+ * e2e is active but with an unsupported algorithm.
+ */
E2EWithUnsupportedAlgorithm
}
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/VerificationMethod.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt
index f2de2c4b47..0ab47a2ecd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt
@@ -20,12 +20,18 @@ package org.matrix.android.sdk.api.session.crypto.verification
* Verification methods.
*/
enum class VerificationMethod {
- // Use it when your application supports the SAS verification method
+ /**
+ * Use it when your application supports the SAS verification method.
+ */
SAS,
- // Use it if your application is able to display QR codes
+ /**
+ * Use it if your application is able to display QR codes.
+ */
QR_CODE_SHOW,
- // Use it if your application is able to scan QR codes
+ /**
+ * Use it if your application is able to scan QR codes.
+ */
QR_CODE_SCAN
}
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/crypto/verification/VerificationTxState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt
index 39de2cc712..30e4c66937 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt
@@ -17,10 +17,14 @@
package org.matrix.android.sdk.api.session.crypto.verification
sealed class VerificationTxState {
- // Uninitialized state
+ /**
+ * Uninitialized state.
+ */
object None : VerificationTxState()
- // Specific for SAS
+ /**
+ * Specific for SAS.
+ */
abstract class VerificationSasTxState : VerificationTxState()
object SendingStart : VerificationSasTxState()
@@ -38,18 +42,26 @@ sealed class VerificationTxState {
object MacSent : VerificationSasTxState()
object Verifying : VerificationSasTxState()
- // Specific for QR code
+ /**
+ * Specific for QR code.
+ */
abstract class VerificationQrTxState : VerificationTxState()
- // Will be used to ask the user if the other user has correctly scanned
+ /**
+ * Will be used to ask the user if the other user has correctly scanned.
+ */
object QrScannedByOther : VerificationQrTxState()
object WaitingOtherReciprocateConfirm : VerificationQrTxState()
- // Terminal states
+ /**
+ * Terminal states.
+ */
abstract class TerminalTxState : VerificationTxState()
object Verified : TerminalTxState()
- // Cancelled by me or by other
+ /**
+ * Cancelled by me or by other.
+ */
data class Cancelled(val cancelCode: CancelCode, val byMe: Boolean) : TerminalTxState()
}
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/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/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/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/HttpPusher.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/HttpPusher.kt
new file mode 100644
index 0000000000..1ae23e2b70
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/HttpPusher.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.pushers
+
+data class HttpPusher(
+ /**
+ * This is a unique identifier for this pusher. The value you should use for
+ * this is the routing or destination address information for the notification,
+ * for example, the APNS token for APNS or the Registration ID for GCM. If your
+ * notification client has no such concept, use any unique identifier. Max length, 512 chars.
+ */
+ val pushkey: String,
+
+ /**
+ * The application id
+ * This is a reverse-DNS style identifier for the application. It is recommended
+ * that this end with the platform, such that different platform versions get
+ * different app identifiers. Max length, 64 chars.
+ */
+ val appId: String,
+
+ /**
+ * This string determines which set of device specific rules this pusher executes.
+ */
+ val profileTag: String,
+
+ /**
+ * The preferred language for receiving notifications (e.g. "en" or "en-US").
+ */
+ val lang: String,
+
+ /**
+ * A human readable string that will allow the user to identify what application owns this pusher.
+ */
+ val appDisplayName: String,
+
+ /**
+ * A human readable string that will allow the user to identify what device owns this pusher.
+ */
+ val deviceDisplayName: String,
+
+ /**
+ * The URL to use to send notifications to. MUST be an HTTPS URL with a path of /_matrix/push/v1/notify.
+ */
+ val url: String,
+
+ /**
+ * If true, the homeserver should add another pusher with the given pushkey and App ID in addition
+ * to any others with different user IDs. Otherwise, the homeserver must remove any other pushers
+ * with the same App ID and pushkey for different users.
+ */
+ val append: Boolean,
+
+ /**
+ * true to limit the push content to only id and not message content
+ * Ref: https://matrix.org/docs/spec/push_gateway/r0.1.1#homeserver-behaviour
+ */
+ val withEventIdOnly: Boolean
+)
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 5cb7857021..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.
@@ -107,61 +111,4 @@ interface PushersService {
* Get the current pushers.
*/
fun getPushers(): List
-
- data class HttpPusher(
-
- /**
- * This is a unique identifier for this pusher. The value you should use for
- * this is the routing or destination address information for the notification,
- * for example, the APNS token for APNS or the Registration ID for GCM. If your
- * notification client has no such concept, use any unique identifier. Max length, 512 chars.
- */
- val pushkey: String,
-
- /**
- * The application id
- * This is a reverse-DNS style identifier for the application. It is recommended
- * that this end with the platform, such that different platform versions get
- * different app identifiers. Max length, 64 chars.
- */
- val appId: String,
-
- /**
- * This string determines which set of device specific rules this pusher executes.
- */
- val profileTag: String,
-
- /**
- * The preferred language for receiving notifications (e.g. "en" or "en-US").
- */
- val lang: String,
-
- /**
- * A human readable string that will allow the user to identify what application owns this pusher.
- */
- val appDisplayName: String,
-
- /**
- * A human readable string that will allow the user to identify what device owns this pusher.
- */
- val deviceDisplayName: String,
-
- /**
- * The URL to use to send notifications to. MUST be an HTTPS URL with a path of /_matrix/push/v1/notify.
- */
- val url: String,
-
- /**
- * If true, the homeserver should add another pusher with the given pushkey and App ID in addition
- * to any others with different user IDs. Otherwise, the homeserver must remove any other pushers
- * with the same App ID and pushkey for different users.
- */
- val append: Boolean,
-
- /**
- * true to limit the push content to only id and not message content
- * Ref: https://matrix.org/docs/spec/push_gateway/r0.1.1#homeserver-behaviour
- */
- val withEventIdOnly: Boolean
- )
}
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/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/room/Room.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt
index 3a18cf1497..5d2769ac3c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt
@@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataServic
import org.matrix.android.sdk.api.session.room.alias.AliasService
import org.matrix.android.sdk.api.session.room.call.RoomCallService
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
+import org.matrix.android.sdk.api.session.room.location.LocationSharingService
import org.matrix.android.sdk.api.session.room.members.MembershipService
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.relation.RelationService
@@ -163,4 +164,9 @@ interface Room {
* Get the RoomVersionService associated to this Room.
*/
fun roomVersionService(): RoomVersionService
+
+ /**
+ * Get the LocationSharingService associated to this Room.
+ */
+ fun locationSharingService(): LocationSharingService
}
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/RoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt
index 6d5551ddf0..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
@@ -97,19 +99,29 @@ interface RoomService {
*/
fun getRoomSummary(roomIdOrAlias: String): RoomSummary?
+ /**
+ * A live [RoomSummary] associated with the room with id [roomId].
+ * You can observe this summary to get dynamic data from this room, even if the room is not joined yet
+ */
+ fun getRoomSummaryLive(roomId: String): LiveData>
+
/**
* 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.
@@ -139,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.
@@ -205,16 +219,27 @@ 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>
/**
- * TODO Doc.
+ * Get's a live paged list from a filter that can be dynamically updated.
+ *
+ * @param queryParams The filter to use
+ * @param pagedListConfig The paged list configuration (page size, initial load, prefetch distance...)
+ * @param sortOrder defines how to sort the results
+ * @param getFlattenParents When true, the list of known parents and grand parents summaries will be resolved.
+ * This can have significant impact on performance, better be used only on manageable list (filtered by displayName, ..).
*/
- fun getFilteredPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams,
- pagedListConfig: PagedList.Config = defaultPagedListConfig,
- sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): UpdatableLivePageResult
+ fun getFilteredPagedRoomSummariesLive(
+ queryParams: RoomSummaryQueryParams,
+ pagedListConfig: PagedList.Config = defaultPagedListConfig,
+ sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY,
+ getFlattenParents: Boolean = false,
+ ): UpdatableLivePageResult
/**
* Return a LiveData on the number of rooms.
@@ -240,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/RoomSortOrder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSortOrder.kt
index e721abd6a0..9368ad6bf4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSortOrder.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSortOrder.kt
@@ -16,9 +16,28 @@
package org.matrix.android.sdk.api.session.room
+/**
+ * Enum to sort room list.
+ */
enum class RoomSortOrder {
+ /**
+ * Sort room list by room ascending name.
+ */
NAME,
+
+ /**
+ * Sort room list by room descending last activity.
+ */
ACTIVITY,
+
+ /**
+ * Sort room list by room priority and last activity: favorite room first, low priority room last,
+ * then descending last activity.
+ */
PRIORITY_AND_ACTIVITY,
+
+ /**
+ * Do not sort room list. Useful if the order does not matter. Order can be indeterminate.
+ */
NONE
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt
index 5c74dcced1..3d943473e4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt
@@ -16,60 +16,99 @@
package org.matrix.android.sdk.api.session.room
-import org.matrix.android.sdk.api.query.ActiveSpaceFilter
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.query.RoomCategoryFilter
import org.matrix.android.sdk.api.query.RoomTagQueryFilter
+import org.matrix.android.sdk.api.query.SpaceFilter
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomType
import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
+/**
+ * Create a [RoomSummaryQueryParams] object, calling [init] with a [RoomSummaryQueryParams.Builder].
+ */
fun roomSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = {}): RoomSummaryQueryParams {
- return RoomSummaryQueryParams.Builder().apply(init).build()
-}
-
-fun spaceSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = {}): SpaceSummaryQueryParams {
return RoomSummaryQueryParams.Builder()
.apply(init)
- .apply {
- includeType = listOf(RoomType.SPACE)
- excludeType = null
- roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS
- }
.build()
}
/**
- * This class can be used to filter room summaries to use with:
- * [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService].
+ * Create a [SpaceSummaryQueryParams] object (which is a [RoomSummaryQueryParams]), calling [init] with a [RoomSummaryQueryParams.Builder].
+ * This is specific for spaces, other filters will be applied after invoking [init]
+ */
+fun spaceSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = {}): SpaceSummaryQueryParams {
+ return roomSummaryQueryParams {
+ init()
+ includeType = listOf(RoomType.SPACE)
+ excludeType = null
+ roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS
+ }
+}
+
+/**
+ * This class can be used to filter room summaries to use with [RoomService].
+ * It provides a [Builder].
+ * [roomSummaryQueryParams] and [spaceSummaryQueryParams] can also be used to build an instance of this class.
*/
data class RoomSummaryQueryParams(
- val roomId: QueryStringValue,
+ /**
+ * Query for the displayName of the room. The display name can be the value of the state event,
+ * or a value returned by [org.matrix.android.sdk.api.RoomDisplayNameFallbackProvider].
+ */
val displayName: QueryStringValue,
+ /**
+ * Query for the canonical alias of the room.
+ */
val canonicalAlias: QueryStringValue,
+ /**
+ * Used to filter room by membership.
+ */
val memberships: List,
+ /**
+ * Used to filter room by room category.
+ */
val roomCategoryFilter: RoomCategoryFilter?,
+ /**
+ * Used to filter room by room tag.
+ */
val roomTagQueryFilter: RoomTagQueryFilter?,
+ /**
+ * Used to filter room by room type.
+ * @see [includeType]
+ */
val excludeType: List?,
+ /**
+ * Used to filter room by room type.
+ * @see [excludeType]
+ */
val includeType: List?,
- val activeSpaceFilter: ActiveSpaceFilter?,
+ /**
+ * Used to filter room using the current space.
+ */
+ val spaceFilter: SpaceFilter?,
+ /**
+ * Used to filter room using the current group.
+ */
val activeGroupId: String? = null
) {
+ /**
+ * Builder for [RoomSummaryQueryParams].
+ * [roomSummaryQueryParams] and [spaceSummaryQueryParams] can also be used to build an instance of [RoomSummaryQueryParams].
+ */
class Builder {
- var roomId: QueryStringValue = QueryStringValue.IsNotEmpty
- var displayName: QueryStringValue = QueryStringValue.IsNotEmpty
+ var displayName: QueryStringValue = QueryStringValue.NoCondition
var canonicalAlias: QueryStringValue = QueryStringValue.NoCondition
var memberships: List = Membership.all()
- var roomCategoryFilter: RoomCategoryFilter? = RoomCategoryFilter.ALL
+ var roomCategoryFilter: RoomCategoryFilter? = null
var roomTagQueryFilter: RoomTagQueryFilter? = null
var excludeType: List? = listOf(RoomType.SPACE)
var includeType: List? = null
- var activeSpaceFilter: ActiveSpaceFilter = ActiveSpaceFilter.None
+ var spaceFilter: SpaceFilter? = null
var activeGroupId: String? = null
fun build() = RoomSummaryQueryParams(
- roomId = roomId,
displayName = displayName,
canonicalAlias = canonicalAlias,
memberships = memberships,
@@ -77,7 +116,7 @@ data class RoomSummaryQueryParams(
roomTagQueryFilter = roomTagQueryFilter,
excludeType = excludeType,
includeType = includeType,
- activeSpaceFilter = activeSpaceFilter,
+ spaceFilter = spaceFilter,
activeGroupId = activeGroupId
)
}
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
new file mode 100644
index 0000000000..dd48d51f45
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt
@@ -0,0 +1,27 @@
+/*
+ * 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
+
+import androidx.lifecycle.LiveData
+import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary
+
+/**
+ * Manage all location sharing related features.
+ */
+interface LocationSharingService {
+ fun getRunningLiveLocationShareSummaries(): LiveData>
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt
index 71c1d8303e..1ab23b7a11 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt
@@ -28,65 +28,200 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
* It can be retrieved by [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService]
*/
data class RoomSummary(
+ /**
+ * The roomId of the room.
+ */
val roomId: String,
- // Computed display name
+ /**
+ * Computed display name. The value of the state event `m.room.name` if not empty, else can be the value returned
+ * by [org.matrix.android.sdk.api.RoomDisplayNameFallbackProvider].
+ */
val displayName: String = "",
+ /**
+ * The value of the live state event `m.room.name`.
+ */
val name: String = "",
+ /**
+ * The value of the live state event `m.room.topic`.
+ */
val topic: String = "",
+ /**
+ * The value of the live state event `m.room.avatar`.
+ */
val avatarUrl: String = "",
+ /**
+ * The value of the live state event `m.room.canonical_alias`.
+ */
val canonicalAlias: String? = null,
+ /**
+ * The list of all the aliases of this room. Content of the live state event `m.room.aliases`.
+ */
val aliases: List = emptyList(),
+ /**
+ * The value of the live state event `m.room.join_rules`.
+ */
val joinRules: RoomJoinRules? = null,
+ /**
+ * True is this room is referenced in the account data `m.direct`.
+ */
val isDirect: Boolean = false,
+ /**
+ * If [isDirect] is true, this is the id of the first other member of this room.
+ */
val directUserId: String? = null,
+ /**
+ * If [isDirect] is true, this it the presence of the first other member of this room.
+ */
val directUserPresence: UserPresence? = null,
+ /**
+ * Number of members who have joined this room.
+ */
val joinedMembersCount: Int? = 0,
+ /**
+ * Number of members who are invited to this room.
+ */
val invitedMembersCount: Int? = 0,
+ /**
+ * Latest [TimelineEvent] which can be displayed in this room. Can be used in the room list.
+ */
val latestPreviewableEvent: TimelineEvent? = null,
+ /**
+ * List of other member ids of this room.
+ */
val otherMemberIds: List = emptyList(),
+ /**
+ * Number of unread message in this room.
+ */
val notificationCount: Int = 0,
+ /**
+ * Number of unread and highlighted message in this room.
+ */
val highlightCount: Int = 0,
+ /**
+ * True if this room has unread messages.
+ */
val hasUnreadMessages: Boolean = false,
+ /**
+ * List of tags in this room.
+ */
val tags: List = emptyList(),
+ /**
+ * Current user membership in this room.
+ */
val membership: Membership = Membership.NONE,
+ /**
+ * Versioning state of this room.
+ */
val versioningState: VersioningState = VersioningState.NONE,
+ /**
+ * Value of `m.fully_read` for this room.
+ */
val readMarkerId: String? = null,
+ /**
+ * Message saved as draft for this room.
+ */
val userDrafts: List = emptyList(),
+ /**
+ * True if this room is encrypted.
+ */
val isEncrypted: Boolean,
+ /**
+ * Timestamp of the `m.room.encryption` state event.
+ */
val encryptionEventTs: Long?,
+ /**
+ * List of users who are currently typing on this room.
+ */
val typingUsers: List,
+ /**
+ * UserId of the user who has invited the current user to this room.
+ */
val inviterId: String? = null,
+ /**
+ * Breadcrumb index, util to sort rooms by last seen.
+ */
val breadcrumbsIndex: Int = NOT_IN_BREADCRUMBS,
+ /**
+ * The room encryption trust level.
+ * @see [RoomEncryptionTrustLevel]
+ */
val roomEncryptionTrustLevel: RoomEncryptionTrustLevel? = null,
+ /**
+ * True if a message has not been sent in this room.
+ */
val hasFailedSending: Boolean = false,
+ /**
+ * The type of the room. Null for regular room.
+ * @see [RoomType]
+ */
val roomType: String? = null,
+ /**
+ * List of parent spaces.
+ */
val spaceParents: List? = null,
+ /**
+ * List of children space.
+ */
val spaceChildren: List? = null,
+ /**
+ * List of all the space parents. Will be empty by default, you have to explicitly request it.
+ */
+ val flattenParents: List = emptyList(),
+ /**
+ * List of all the space parent Ids.
+ */
val flattenParentIds: List = emptyList(),
- val roomEncryptionAlgorithm: RoomEncryptionAlgorithm? = null
+ /**
+ * Information about the encryption algorithm, if this room is encrypted.
+ */
+ val roomEncryptionAlgorithm: RoomEncryptionAlgorithm? = null,
) {
-
+ /**
+ * True if [versioningState] is not [VersioningState.NONE].
+ */
val isVersioned: Boolean
get() = versioningState != VersioningState.NONE
+ /**
+ * True if [notificationCount] is not `0`.
+ */
val hasNewMessages: Boolean
get() = notificationCount != 0
+ /**
+ * True if the room has the tag `m.lowpriority`.
+ */
val isLowPriority: Boolean
get() = hasTag(RoomTag.ROOM_TAG_LOW_PRIORITY)
+ /**
+ * True if the room has the tag `m.favourite`.
+ */
val isFavorite: Boolean
get() = hasTag(RoomTag.ROOM_TAG_FAVOURITE)
+ /**
+ * True if [joinRules] is [RoomJoinRules.PUBLIC].
+ */
val isPublic: Boolean
get() = joinRules == RoomJoinRules.PUBLIC
+ /**
+ * Test if the room has the provided [tag].
+ */
fun hasTag(tag: String) = tags.any { it.name == tag }
+ /**
+ * True if a 1-1 call can be started, i.e. the room has exactly 2 joined members.
+ */
val canStartCall: Boolean
get() = joinedMembersCount == 2
companion object {
+ /**
+ * Constant to indicated that the room is not on the breadcrumbs.
+ * Used by [breadcrumbsIndex].
+ */
const val NOT_IN_BREADCRUMBS = -1
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/VersioningState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/VersioningState.kt
index b4e7b10d44..2e1668ebbb 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/VersioningState.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/VersioningState.kt
@@ -16,8 +16,22 @@
package org.matrix.android.sdk.api.session.room.model
+/**
+ * Enum for the versioning state of a room.
+ */
enum class VersioningState {
+ /**
+ * The room is not versioned.
+ */
NONE,
+
+ /**
+ * The room has been upgraded, but the new room is not joined yet.
+ */
UPGRADED_ROOM_NOT_JOINED,
- UPGRADED_ROOM_JOINED
+
+ /**
+ * The room has been upgraded, and the new room has been joined.
+ */
+ UPGRADED_ROOM_JOINED,
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationShareAggregatedSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationShareAggregatedSummary.kt
index 0b28d62f56..5ad1a48217 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationShareAggregatedSummary.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationShareAggregatedSummary.kt
@@ -22,6 +22,10 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocati
* Aggregation info concerning a live location share.
*/
data class LiveLocationShareAggregatedSummary(
+ val userId: String?,
+ /**
+ * Indicate whether the live is currently running.
+ */
val isActive: Boolean?,
val endOfLiveTimestampMillis: Long?,
val lastLocationDataContent: MessageBeaconLocationDataContent?,
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/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/send/SendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt
index c2e3ded2fa..661c3be5bd 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.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt
index 7c806bf35b..d058ff2840 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt
@@ -17,27 +17,44 @@
package org.matrix.android.sdk.api.session.room.send
enum class SendState {
+ /**
+ * The state is unknown.
+ */
UNKNOWN,
- // the event has not been sent
+ /**
+ * The event has not been sent.
+ */
UNSENT,
- // the event is encrypting
+ /**
+ * The event is encrypting.
+ */
ENCRYPTING,
- // the event is currently sending
+ /**
+ * The event is currently sending.
+ */
SENDING,
- // the event has been sent
+ /**
+ * The event has been sent.
+ */
SENT,
- // the event has been received from server
+ /**
+ * The event has been received from server.
+ */
SYNCED,
- // The event failed to be sent
+ /**
+ * The event failed to be sent.
+ */
UNDELIVERED,
- // the event failed to be sent because some unknown devices have been found while encrypting it
+ /**
+ * The event failed to be sent because some unknown devices have been found while encrypting it.
+ */
FAILED_UNKNOWN_DEVICES;
internal companion object {
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/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/KeyRef.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/KeyRef.kt
new file mode 100644
index 0000000000..5a1bf67fdd
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/KeyRef.kt
@@ -0,0 +1,22 @@
+/*
+ * 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.securestorage
+
+data class KeyRef(
+ val keyId: String?,
+ val keySpec: SsssKeySpec?
+)
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 e3a9860523..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
@@ -132,9 +136,4 @@ interface SharedSecretStorageService {
fun checkShouldBeAbleToAccessSecrets(secretNames: List, keyId: String?): IntegrityResult
suspend fun requestSecret(name: String, myOtherDeviceId: String)
-
- data class KeyRef(
- val keyId: String?,
- val keySpec: SsssKeySpec?
- )
}
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..50da34b319 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
@@ -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/threads/ThreadNotificationState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt
index c110802d23..6825f8c279 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt
@@ -20,14 +20,19 @@ package org.matrix.android.sdk.api.session.threads
* This class defines the state of a thread notification.
*/
enum class ThreadNotificationState {
-
- // There are no new message
+ /**
+ * There are no new message.
+ */
NO_NEW_MESSAGE,
- // There is at least one new message
+ /**
+ * There is at least one new message.
+ */
NEW_MESSAGE,
- // The is at least one new message that should be highlighted
- // ex. "Hello @aris.kotsomitopoulos"
+ /**
+ * The is at least one new message that should be highlighted.
+ * ex. "Hello @aris.kotsomitopoulos"
+ */
NEW_HIGHLIGHTED_MESSAGE;
}
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 8a29d00380..ec775d640e 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()
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..bd2dac9e3c 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()
@@ -53,7 +55,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 02dfce04b5..c64f451a2c 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
@@ -130,16 +130,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)
}
@@ -323,8 +314,7 @@ internal class DefaultAuthenticationService @Inject constructor(
}
}
- override val isRegistrationStarted: Boolean
- get() = currentRegistrationWizard?.isRegistrationStarted == true
+ override fun isRegistrationStarted() = currentRegistrationWizard?.isRegistrationStarted() == true
override fun getLoginWizard(): LoginWizard {
return currentLoginWizard
@@ -368,13 +358,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
}
@@ -392,11 +386,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..20b056f1c7 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,16 @@ 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) {
+ 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
)
executeRequest(null) {
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/registration/DefaultRegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt
index 8f00f3440c..b45c4e87f0 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
@@ -49,29 +49,29 @@ internal class DefaultRegistrationWizard(
private val validateCodeTask: ValidateCodeTask = DefaultValidateCodeTask(authAPI)
private val registerCustomTask: RegisterCustomTask = DefaultRegisterCustomTask(authAPI)
- override val currentThreePid: String?
- get() {
- return when (val threePid = pendingSessionData.currentThreePidData?.threePid) {
- 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
+ override fun getCurrentThreePid(): String? {
+ return when (val threePid = pendingSessionData.currentThreePidData?.threePid) {
+ 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
}
+ }
- override val isRegistrationStarted: Boolean
- get() = pendingSessionData.isRegistrationStarted
+ override fun isRegistrationStarted() = pendingSessionData.isRegistrationStarted
override suspend fun getRegistrationFlow(): RegistrationResult {
val params = RegistrationParams()
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/ThreePidData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidData.kt
index c8f71af306..70615809d8 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,9 +40,11 @@ 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 ->
ThreePidData(threePid.email, "", "", 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..239adfdbbd 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
@@ -38,14 +40,14 @@ internal data class HomeServerVersion(
}
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
)
}
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..a5afe3f81d 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
@@ -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)
@@ -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)
@@ -879,8 +883,10 @@ 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 -> {
crossSigningService.onSecretMSKGossip(secretValue)
@@ -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")
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt
index cb61bbe1de..c1d04eb22b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt
@@ -29,6 +29,7 @@ import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.content.OlmEventContent
+import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction
import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
@@ -42,7 +43,7 @@ import javax.inject.Inject
private const val SEND_TO_DEVICE_RETRY_COUNT = 3
-private val loggerTag = LoggerTag("CryptoSyncHandler", LoggerTag.CRYPTO)
+private val loggerTag = LoggerTag("EventDecryptor", LoggerTag.CRYPTO)
@SessionScope
internal class EventDecryptor @Inject constructor(
@@ -110,6 +111,16 @@ internal class EventDecryptor @Inject constructor(
if (eventContent == null) {
Timber.tag(loggerTag.value).e("decryptEvent : empty event content")
throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_ENCRYPTED_MESSAGE, MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON)
+ } else if (event.isRedacted()) {
+ // we shouldn't attempt to decrypt a redacted event because the content is cleared and decryption will fail because of null algorithm
+ return MXEventDecryptionResult(
+ clearEvent = mapOf(
+ "room_id" to event.roomId.orEmpty(),
+ "type" to EventType.MESSAGE,
+ "content" to emptyMap(),
+ "unsigned" to event.unsignedData.toContent()
+ )
+ )
} else {
val algorithm = eventContent["algorithm"]?.toString()
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(event.roomId, algorithm)
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..f8baab7c06 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
@@ -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/MXOlmDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt
index 6c18f29307..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
@@ -96,8 +96,9 @@ internal class MXOlmDevice @Inject constructor(
// So, store these message indexes per timeline id.
//
// The first level keys are timeline ids.
- // The second level keys are strings of form "||"
- private val inboundGroupSessionMessageIndexes: MutableMap> = HashMap()
+ // The second level values is a Map that represents:
+ // "|||" --> eventId
+ private val inboundGroupSessionMessageIndexes: MutableMap> = HashMap()
init {
// Retrieve the account from the store
@@ -599,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
@@ -755,67 +758,74 @@ internal class MXOlmDevice @Inject constructor(
* @param body the base64-encoded body of the encrypted message.
* @param roomId the room in which the message was received.
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
+ * @param eventId the eventId of the message that will be decrypted
* @param sessionId the session identifier.
* @param senderKey the base64-encoded curve25519 key of the sender.
- * @return the decrypting result. Nil if the sessionId is unknown.
+ * @return the decrypting result. Null if the sessionId is unknown.
*/
@Throws(MXCryptoError::class)
- suspend fun decryptGroupMessage(body: String,
- roomId: String,
- timeline: 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
?: throw MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_DECRYPT, "Session is null")
- // Check that the room id matches the original one for the session. This stops
- // the HS pretending a message was targeting a different room.
- if (roomId == wrapper.roomId) {
- val decryptResult = try {
- sessionHolder.mutex.withLock {
- inboundGroupSession.decryptMessage(body)
- }
- } catch (e: OlmException) {
- Timber.tag(loggerTag.value).e(e, "## decryptGroupMessage () : decryptMessage failed")
- throw MXCryptoError.OlmError(e)
- }
-
- if (timeline?.isNotBlank() == true) {
- val timelineSet = inboundGroupSessionMessageIndexes.getOrPut(timeline) { mutableSetOf() }
-
- val messageIndexKey = senderKey + "|" + sessionId + "|" + decryptResult.mIndex
-
- if (timelineSet.contains(messageIndexKey)) {
- val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex)
- Timber.tag(loggerTag.value).e("## decryptGroupMessage() timelineId=$timeline: $reason")
- throw MXCryptoError.Base(MXCryptoError.ErrorType.DUPLICATED_MESSAGE_INDEX, reason)
- }
-
- timelineSet.add(messageIndexKey)
- }
-
- inboundGroupSessionStore.storeInBoundGroupSession(sessionHolder, sessionId, senderKey)
- val payload = try {
- val adapter = MoshiProvider.providesMoshi().adapter(JSON_DICT_PARAMETERIZED_TYPE)
- val payloadString = convertFromUTF8(decryptResult.mDecryptedMessage)
- adapter.fromJson(payloadString)
- } catch (e: Exception) {
- Timber.tag(loggerTag.value).e("## decryptGroupMessage() : fails to parse the payload")
- throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_DECRYPTED_FORMAT, MXCryptoError.BAD_DECRYPTED_FORMAT_TEXT_REASON)
- }
-
- return OlmDecryptionResult(
- payload,
- wrapper.keysClaimed,
- senderKey,
- wrapper.forwardingCurve25519KeyChain
- )
- } else {
+ if (roomId != wrapper.roomId) {
+ // Check that the room id matches the original one for the session. This stops
+ // the HS pretending a message was targeting a different room.
val reason = String.format(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_REASON, roomId, wrapper.roomId)
Timber.tag(loggerTag.value).e("## decryptGroupMessage() : $reason")
throw MXCryptoError.Base(MXCryptoError.ErrorType.INBOUND_SESSION_MISMATCH_ROOM_ID, reason)
}
+ val decryptResult = try {
+ sessionHolder.mutex.withLock {
+ inboundGroupSession.decryptMessage(body)
+ }
+ } catch (e: OlmException) {
+ Timber.tag(loggerTag.value).e(e, "## decryptGroupMessage () : decryptMessage failed")
+ throw MXCryptoError.OlmError(e)
+ }
+
+ val messageIndexKey = senderKey + "|" + sessionId + "|" + roomId + "|" + decryptResult.mIndex
+ Timber.tag(loggerTag.value).v("##########################################################")
+ Timber.tag(loggerTag.value).v("## decryptGroupMessage() timeline: $timeline")
+ Timber.tag(loggerTag.value).v("## decryptGroupMessage() senderKey: $senderKey")
+ Timber.tag(loggerTag.value).v("## decryptGroupMessage() sessionId: $sessionId")
+ Timber.tag(loggerTag.value).v("## decryptGroupMessage() roomId: $roomId")
+ Timber.tag(loggerTag.value).v("## decryptGroupMessage() eventId: $eventId")
+ Timber.tag(loggerTag.value).v("## decryptGroupMessage() mIndex: ${decryptResult.mIndex}")
+
+ if (timeline?.isNotBlank() == true) {
+ val replayAttackMap = inboundGroupSessionMessageIndexes.getOrPut(timeline) { mutableMapOf() }
+ if (replayAttackMap.contains(messageIndexKey) && replayAttackMap[messageIndexKey] != eventId) {
+ val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex)
+ Timber.tag(loggerTag.value).e("## decryptGroupMessage() timelineId=$timeline: $reason")
+ throw MXCryptoError.Base(MXCryptoError.ErrorType.DUPLICATED_MESSAGE_INDEX, reason)
+ }
+ replayAttackMap[messageIndexKey] = eventId
+ }
+ inboundGroupSessionStore.storeInBoundGroupSession(sessionHolder, sessionId, senderKey)
+ val payload = try {
+ val adapter = MoshiProvider.providesMoshi().adapter(JSON_DICT_PARAMETERIZED_TYPE)
+ val payloadString = convertFromUTF8(decryptResult.mDecryptedMessage)
+ adapter.fromJson(payloadString)
+ } catch (e: Exception) {
+ Timber.tag(loggerTag.value).e("## decryptGroupMessage() : fails to parse the payload")
+ throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_DECRYPTED_FORMAT, MXCryptoError.BAD_DECRYPTED_FORMAT_TEXT_REASON)
+ }
+
+ return OlmDecryptionResult(
+ payload,
+ wrapper.keysClaimed,
+ senderKey,
+ wrapper.forwardingCurve25519KeyChain
+ )
}
/**
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..6e2ff5c22b 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")
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 d15b18ec79..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
@@ -78,6 +78,7 @@ internal class MXMegolmDecryption(
encryptedEventContent.ciphertext,
event.roomId,
timeline,
+ eventId = event.eventId.orEmpty(),
encryptedEventContent.sessionId,
encryptedEventContent.senderKey
)
@@ -148,7 +149,8 @@ internal class MXMegolmDecryption(
throw MXCryptoError.Base(
MXCryptoError.ErrorType.KEYS_WITHHELD,
withHeldInfo.code?.value ?: "",
- withHeldInfo.reason)
+ withHeldInfo.reason
+ )
}
if (requestKeysOnFail) {
@@ -248,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 ->
@@ -267,7 +269,8 @@ internal class MXMegolmDecryption(
senderKey = senderKey,
fromIndex = index,
fromDevice = fromDevice,
- event = event)
+ event = event
+ )
cryptoStore.saveIncomingForwardKeyAuditTrail(
roomId = roomKeyContent.roomId,
@@ -276,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..17a44b19ff 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)
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/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..6e317f049b 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
@@ -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 813adf7459..8ecb1d72c6 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
@@ -137,17 +137,11 @@ internal class DefaultKeysBackupService @Inject constructor(
private var keysBackupStateListener: KeysBackupStateListener? = null
- override val isEnabled: Boolean
- get() = keysBackupStateManager.isEnabled
+ override fun isEnabled(): Boolean = keysBackupStateManager.isEnabled
- override val isStucked: Boolean
- get() = keysBackupStateManager.isStucked
+ override fun isStuck(): Boolean = keysBackupStateManager.isStuck
- override val state: KeysBackupState
- get() = keysBackupStateManager.state
-
- override val currentBackupVersion: String?
- get() = keysBackupVersion?.version
+ override fun getState(): KeysBackupState = keysBackupStateManager.state
override fun addListener(listener: KeysBackupStateListener) {
keysBackupStateManager.addListener(listener)
@@ -157,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()
@@ -233,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,
@@ -291,7 +289,7 @@ internal class DefaultKeysBackupService @Inject constructor(
this.callback = object : MatrixCallback {
private fun eventuallyRestartBackup() {
// Do not stay in KeysBackupState.Unknown but check what is available on the homeserver
- if (state == KeysBackupState.Unknown) {
+ if (getState() == KeysBackupState.Unknown) {
checkAndStartKeysBackup()
}
}
@@ -345,9 +343,11 @@ internal class DefaultKeysBackupService @Inject constructor(
return cryptoStore.inboundGroupSessionsCount(true)
}
- override fun backupAllGroupSessions(progressListener: ProgressListener?,
- callback: MatrixCallback?) {
- if (!isEnabled || backupOlmPkEncryption == null || keysBackupVersion == null) {
+ override fun backupAllGroupSessions(
+ progressListener: ProgressListener?,
+ callback: MatrixCallback?
+ ) {
+ if (!isEnabled() || backupOlmPkEncryption == null || keysBackupVersion == null) {
callback?.onFailure(Throwable("Backup not enabled"))
return
}
@@ -383,7 +383,7 @@ internal class DefaultKeysBackupService @Inject constructor(
}
// If backup is finished, notify the main listener
- if (state === KeysBackupState.ReadyToBackUp) {
+ if (getState() === KeysBackupState.ReadyToBackUp) {
backupAllGroupSessionsCallback?.onSuccess(Unit)
resetBackupAllGroupSessionsListeners()
}
@@ -397,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 {
@@ -505,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
@@ -589,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) {
@@ -608,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) {
@@ -628,7 +636,7 @@ internal class DefaultKeysBackupService @Inject constructor(
}
}
- override fun onSecretKeyGossip(secret: String) {
+ fun onSecretKeyGossip(secret: String) {
Timber.i("## CrossSigning - onSecretKeyGossip")
cryptoCoroutineScope.launch(coroutineDispatchers.io) {
@@ -707,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) {
@@ -806,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) {
@@ -859,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))
@@ -915,12 +929,12 @@ internal class DefaultKeysBackupService @Inject constructor(
*/
fun maybeBackupKeys() {
when {
- isStucked -> {
+ 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()
}
- state == KeysBackupState.ReadyToBackUp -> {
+ getState() == KeysBackupState.ReadyToBackUp -> {
keysBackupStateManager.state = KeysBackupState.WillBackUp
// Wait between 0 and 10 seconds, to avoid backup requests from
@@ -933,14 +947,16 @@ internal class DefaultKeysBackupService @Inject constructor(
uiHandler.post { backupKeys() }
}
}
- else -> {
- Timber.v("maybeBackupKeys: Skip it because state: $state")
+ else -> {
+ Timber.v("maybeBackupKeys: Skip it because state: ${getState()}")
}
}
}
- override fun getVersion(version: String,
- callback: MatrixCallback) {
+ override fun getVersion(
+ version: String,
+ callback: MatrixCallback
+ ) {
getKeysBackupVersionTask
.configureWith(version) {
this.callback = object : MatrixCallback {
@@ -1018,9 +1034,9 @@ internal class DefaultKeysBackupService @Inject constructor(
}
override fun checkAndStartKeysBackup() {
- if (!isStucked) {
+ if (!isStuck()) {
// Try to start or restart the backup only if it is in unknown or bad state
- Timber.w("checkAndStartKeysBackup: invalid state: $state")
+ Timber.w("checkAndStartKeysBackup: invalid state: ${getState()}")
return
}
@@ -1179,10 +1195,12 @@ internal class DefaultKeysBackupService @Inject constructor(
}
}
- override fun computePrivateKey(passphrase: String,
- privateKeySalt: String,
- privateKeyIterations: Int,
- progressListener: ProgressListener): ByteArray {
+ override fun computePrivateKey(
+ passphrase: String,
+ privateKeySalt: String,
+ privateKeyIterations: Int,
+ progressListener: ProgressListener
+ ): ByteArray {
return deriveKey(passphrase, privateKeySalt, privateKeyIterations, progressListener)
}
@@ -1259,16 +1277,16 @@ internal class DefaultKeysBackupService @Inject constructor(
Timber.v("backupKeys")
// Sanity check, as this method can be called after a delay, the state may have change during the delay
- if (!isEnabled || backupOlmPkEncryption == null || keysBackupVersion == null) {
+ if (!isEnabled() || backupOlmPkEncryption == null || keysBackupVersion == null) {
Timber.v("backupKeys: Invalid configuration")
backupAllGroupSessionsCallback?.onFailure(IllegalStateException("Invalid configuration"))
resetBackupAllGroupSessionsListeners()
return
}
- if (state === KeysBackupState.BackingUp) {
+ if (getState() === KeysBackupState.BackingUp) {
// Do nothing if we are already backing up
- Timber.v("backupKeys: Invalid state: $state")
+ Timber.v("backupKeys: Invalid state: ${getState()}")
return
}
@@ -1482,8 +1500,10 @@ internal class DefaultKeysBackupService @Inject constructor(
get() = cryptoStore
@VisibleForTesting
- fun createFakeKeysBackupVersion(keysBackupCreationInfo: MegolmBackupCreationInfo,
- callback: MatrixCallback) {
+ fun createFakeKeysBackupVersion(
+ keysBackupCreationInfo: MegolmBackupCreationInfo,
+ callback: MatrixCallback
+ ) {
@Suppress("UNCHECKED_CAST")
val createKeysBackupVersionBody = CreateKeysBackupVersionBody(
algorithm = keysBackupCreationInfo.algorithm,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt
index f821fdcf6d..8560eb5fc1 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt
@@ -49,8 +49,9 @@ internal data class GeneratePrivateKeyResult(
* @return a {privateKey, salt, iterations} tuple.
*/
@WorkerThread
-internal fun generatePrivateKeyWithPassword(password: String,
- progressListener: ProgressListener?
+internal fun generatePrivateKeyWithPassword(
+ password: String,
+ progressListener: ProgressListener?
): GeneratePrivateKeyResult {
val salt = generateSalt()
val iterations = DEFAULT_ITERATION
@@ -70,10 +71,12 @@ internal fun generatePrivateKeyWithPassword(password: String,
* @return a private key.
*/
@WorkerThread
-internal fun retrievePrivateKeyWithPassword(password: String,
- salt: String,
- iterations: Int,
- progressListener: ProgressListener? = null): ByteArray {
+internal fun retrievePrivateKeyWithPassword(
+ password: String,
+ salt: String,
+ iterations: Int,
+ progressListener: ProgressListener? = null
+): ByteArray {
return deriveKey(password, salt, iterations, progressListener)
}
@@ -88,10 +91,12 @@ internal fun retrievePrivateKeyWithPassword(password: String,
* @return a private key.
*/
@WorkerThread
-internal fun deriveKey(password: String,
- salt: String,
- iterations: Int,
- progressListener: ProgressListener?): ByteArray {
+internal fun deriveKey(
+ password: String,
+ salt: String,
+ iterations: Int,
+ progressListener: ProgressListener?
+): ByteArray {
// Note: copied and adapted from MXMegolmExportEncryption
// based on https://en.wikipedia.org/wiki/PBKDF2 algorithm
// it is simpler than the generic algorithm because the expected key length is equal to the mac key length.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupStateManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupStateManager.kt
index 78ef958bbf..0614eceb16 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupStateManager.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupStateManager.kt
@@ -49,7 +49,7 @@ internal class KeysBackupStateManager(private val uiHandler: Handler) {
state == KeysBackupState.BackingUp
// True if unknown or bad state
- val isStucked: Boolean
+ val isStuck: Boolean
get() = state == KeysBackupState.Unknown ||
state == KeysBackupState.Disabled ||
state == KeysBackupState.WrongBackUpVersion ||
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt
index d9c63b46ab..48a735018a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt
@@ -71,8 +71,10 @@ internal interface RoomKeysApi {
* @param updateKeysBackupVersionBody the body
*/
@PUT(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/version/{version}")
- suspend fun updateKeysBackupVersion(@Path("version") version: String,
- @Body updateKeysBackupVersionBody: UpdateKeysBackupVersionBody)
+ suspend fun updateKeysBackupVersion(
+ @Path("version") version: String,
+ @Body updateKeysBackupVersionBody: UpdateKeysBackupVersionBody
+ )
/* ==========================================================================================
* Storing keys
@@ -93,10 +95,12 @@ internal interface RoomKeysApi {
* @param keyBackupData the data to send
*/
@PUT(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}/{sessionId}")
- suspend fun storeRoomSessionData(@Path("roomId") roomId: String,
- @Path("sessionId") sessionId: String,
- @Query("version") version: String,
- @Body keyBackupData: KeyBackupData): BackupKeysResult
+ suspend fun storeRoomSessionData(
+ @Path("roomId") roomId: String,
+ @Path("sessionId") sessionId: String,
+ @Query("version") version: String,
+ @Body keyBackupData: KeyBackupData
+ ): BackupKeysResult
/**
* Store several keys for the given room, using the given backup version.
@@ -106,9 +110,11 @@ internal interface RoomKeysApi {
* @param roomKeysBackupData the data to send
*/
@PUT(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}")
- suspend fun storeRoomSessionsData(@Path("roomId") roomId: String,
- @Query("version") version: String,
- @Body roomKeysBackupData: RoomKeysBackupData): BackupKeysResult
+ suspend fun storeRoomSessionsData(
+ @Path("roomId") roomId: String,
+ @Query("version") version: String,
+ @Body roomKeysBackupData: RoomKeysBackupData
+ ): BackupKeysResult
/**
* Store several keys, using the given backup version.
@@ -117,8 +123,10 @@ internal interface RoomKeysApi {
* @param keysBackupData the data to send
*/
@PUT(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys")
- suspend fun storeSessionsData(@Query("version") version: String,
- @Body keysBackupData: KeysBackupData): BackupKeysResult
+ suspend fun storeSessionsData(
+ @Query("version") version: String,
+ @Body keysBackupData: KeysBackupData
+ ): BackupKeysResult
/* ==========================================================================================
* Retrieving keys
@@ -132,9 +140,11 @@ internal interface RoomKeysApi {
* @param version the version of the backup, or empty String to retrieve the last version
*/
@GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}/{sessionId}")
- suspend fun getRoomSessionData(@Path("roomId") roomId: String,
- @Path("sessionId") sessionId: String,
- @Query("version") version: String): KeyBackupData
+ suspend fun getRoomSessionData(
+ @Path("roomId") roomId: String,
+ @Path("sessionId") sessionId: String,
+ @Query("version") version: String
+ ): KeyBackupData
/**
* Retrieve all the keys for the given room from the backup.
@@ -143,8 +153,10 @@ internal interface RoomKeysApi {
* @param version the version of the backup, or empty String to retrieve the last version
*/
@GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}")
- suspend fun getRoomSessionsData(@Path("roomId") roomId: String,
- @Query("version") version: String): RoomKeysBackupData
+ suspend fun getRoomSessionsData(
+ @Path("roomId") roomId: String,
+ @Query("version") version: String
+ ): RoomKeysBackupData
/**
* Retrieve all the keys from the backup.
@@ -162,16 +174,20 @@ internal interface RoomKeysApi {
* Deletes keys from the backup.
*/
@DELETE(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}/{sessionId}")
- suspend fun deleteRoomSessionData(@Path("roomId") roomId: String,
- @Path("sessionId") sessionId: String,
- @Query("version") version: String)
+ suspend fun deleteRoomSessionData(
+ @Path("roomId") roomId: String,
+ @Path("sessionId") sessionId: String,
+ @Query("version") version: String
+ )
/**
* Deletes keys from the backup.
*/
@DELETE(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}")
- suspend fun deleteRoomSessionsData(@Path("roomId") roomId: String,
- @Query("version") version: String)
+ suspend fun deleteRoomSessionsData(
+ @Path("roomId") roomId: String,
+ @Query("version") version: String
+ )
/**
* Deletes keys from the backup.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt
index 9fdeda01c9..85ba1762d3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt
@@ -69,12 +69,14 @@ internal data class KeyVerificationAccept(
override fun toSendToDeviceObject() = this
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 KeyVerificationAccept(
transactionId = tid,
keyAgreementProtocol = keyAgreementProtocol,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt
index 1ded9c6c7e..0e9590a2d5 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt
@@ -30,6 +30,7 @@ import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent
import org.matrix.android.sdk.api.session.securestorage.IntegrityResult
import org.matrix.android.sdk.api.session.securestorage.KeyInfo
import org.matrix.android.sdk.api.session.securestorage.KeyInfoResult
+import org.matrix.android.sdk.api.session.securestorage.KeyRef
import org.matrix.android.sdk.api.session.securestorage.KeySigner
import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
import org.matrix.android.sdk.api.session.securestorage.SecretStorageKeyContent
@@ -62,10 +63,12 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
private val cryptoCoroutineScope: CoroutineScope
) : SharedSecretStorageService {
- override suspend fun generateKey(keyId: String,
- key: SsssKeySpec?,
- keyName: String,
- keySigner: KeySigner?): SsssKeyCreationInfo {
+ override suspend fun generateKey(
+ keyId: String,
+ key: SsssKeySpec?,
+ keyName: String,
+ keySigner: KeySigner?
+ ): SsssKeyCreationInfo {
return withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.computation) {
val bytes = (key as? RawBytesKeySpec)?.privateKey
?: ByteArray(32).also {
@@ -94,11 +97,13 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
}
}
- override suspend fun generateKeyWithPassphrase(keyId: String,
- keyName: String,
- passphrase: String,
- keySigner: KeySigner,
- progressListener: ProgressListener?): SsssKeyCreationInfo {
+ override suspend fun generateKeyWithPassphrase(
+ keyId: String,
+ keyName: String,
+ passphrase: String,
+ keySigner: KeySigner,
+ progressListener: ProgressListener?
+ ): SsssKeyCreationInfo {
return withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.computation) {
val privatePart = generatePrivateKeyWithPassword(passphrase, progressListener)
@@ -157,7 +162,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
return getKey(keyId)
}
- override suspend fun storeSecret(name: String, secretBase64: String, keys: List) {
+ override suspend fun storeSecret(name: String, secretBase64: String, keys: List) {
withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.computation) {
val encryptedContents = HashMap()
keys.forEach {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt
index 9b1c785059..b18de34329 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt
@@ -192,10 +192,12 @@ internal interface IMXCryptoStore {
*/
fun storeUserDevices(userId: String, devices: Map?)
- fun storeUserCrossSigningKeys(userId: String,
- masterKey: CryptoCrossSigningKey?,
- selfSigningKey: CryptoCrossSigningKey?,
- userSigningKey: CryptoCrossSigningKey?)
+ fun storeUserCrossSigningKeys(
+ userId: String,
+ masterKey: CryptoCrossSigningKey?,
+ selfSigningKey: CryptoCrossSigningKey?,
+ userSigningKey: CryptoCrossSigningKey?
+ )
/**
* Retrieve the known devices for a user.
@@ -392,7 +394,8 @@ internal interface IMXCryptoStore {
algorithm: String,
senderKey: String,
fromDevice: String?,
- event: Event)
+ event: Event
+ )
fun deleteOutgoingRoomKeyRequest(requestId: String)
fun deleteOutgoingRoomKeyRequestInState(state: OutgoingRoomKeyRequestState)
@@ -479,8 +482,14 @@ internal interface IMXCryptoStore {
fun addWithHeldMegolmSession(withHeldContent: RoomKeyWithHeldContent)
fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent?
- fun markedSessionAsShared(roomId: String?, sessionId: String, userId: String, deviceId: String,
- deviceIdentityKey: String, chainIndex: Int)
+ fun markedSessionAsShared(
+ roomId: String?,
+ sessionId: String,
+ userId: String,
+ deviceId: String,
+ deviceIdentityKey: String,
+ chainIndex: Int
+ )
/**
* Query for information on this session sharing history.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt
index 533ab70bba..c56e4d320b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt
@@ -322,10 +322,12 @@ internal class RealmCryptoStore @Inject constructor(
}
}
- override fun storeUserCrossSigningKeys(userId: String,
- masterKey: CryptoCrossSigningKey?,
- selfSigningKey: CryptoCrossSigningKey?,
- userSigningKey: CryptoCrossSigningKey?) {
+ override fun storeUserCrossSigningKeys(
+ userId: String,
+ masterKey: CryptoCrossSigningKey?,
+ selfSigningKey: CryptoCrossSigningKey?,
+ userSigningKey: CryptoCrossSigningKey?
+ ) {
doRealmTransaction(realmConfiguration) { realm ->
UserEntity.getOrCreate(realm, userId)
.let { userEntity ->
@@ -1154,9 +1156,11 @@ internal class RealmCryptoStore @Inject constructor(
}
}
- override fun getOrAddOutgoingRoomKeyRequest(requestBody: RoomKeyRequestBody,
- recipients: Map>,
- fromIndex: Int): OutgoingKeyRequest {
+ override fun getOrAddOutgoingRoomKeyRequest(
+ requestBody: RoomKeyRequestBody,
+ recipients: Map>,
+ fromIndex: Int
+ ): OutgoingKeyRequest {
// Insert the request and return the one passed in parameter
lateinit var request: OutgoingKeyRequest
doRealmTransaction(realmConfiguration) { realm ->
@@ -1220,12 +1224,14 @@ internal class RealmCryptoStore @Inject constructor(
}
}
- override fun updateOutgoingRoomKeyReply(roomId: String,
- sessionId: String,
- algorithm: String,
- senderKey: String,
- fromDevice: String?,
- event: Event) {
+ override fun updateOutgoingRoomKeyReply(
+ roomId: String,
+ sessionId: String,
+ algorithm: String,
+ senderKey: String,
+ fromDevice: String?,
+ event: Event
+ ) {
doRealmTransaction(realmConfiguration) { realm ->
realm.where()
.equalTo(OutgoingKeyRequestEntityFields.ROOM_ID, roomId)
@@ -1266,7 +1272,8 @@ internal class RealmCryptoStore @Inject constructor(
senderKey: String,
algorithm: String,
fromUser: String,
- fromDevice: String) {
+ fromDevice: String
+ ) {
monarchy.writeAsync { realm ->
val now = clock.epochMillis()
realm.createObject().apply {
@@ -1288,13 +1295,15 @@ internal class RealmCryptoStore @Inject constructor(
}
}
- override fun saveWithheldAuditTrail(roomId: String,
- sessionId: String,
- senderKey: String,
- algorithm: String,
- code: WithHeldCode,
- userId: String,
- deviceId: String) {
+ override fun saveWithheldAuditTrail(
+ roomId: String,
+ sessionId: String,
+ senderKey: String,
+ algorithm: String,
+ code: WithHeldCode,
+ userId: String,
+ deviceId: String
+ ) {
monarchy.writeAsync { realm ->
val now = clock.epochMillis()
realm.createObject().apply {
@@ -1316,34 +1325,39 @@ internal class RealmCryptoStore @Inject constructor(
}
}
- override fun saveForwardKeyAuditTrail(roomId: String,
- sessionId: String,
- senderKey: String,
- algorithm: String,
- userId: String,
- deviceId: String,
- chainIndex: Long?) {
+ override fun saveForwardKeyAuditTrail(
+ roomId: String,
+ sessionId: String,
+ senderKey: String,
+ algorithm: String,
+ userId: String,
+ deviceId: String,
+ chainIndex: Long?
+ ) {
saveForwardKeyTrail(roomId, sessionId, senderKey, algorithm, userId, deviceId, chainIndex, false)
}
- override fun saveIncomingForwardKeyAuditTrail(roomId: String,
- sessionId: String,
- senderKey: String,
- algorithm: String,
- userId: String,
- deviceId: String,
- chainIndex: Long?) {
+ override fun saveIncomingForwardKeyAuditTrail(
+ roomId: String,
+ sessionId: String,
+ senderKey: String,
+ algorithm: String,
+ userId: String,
+ deviceId: String,
+ chainIndex: Long?
+ ) {
saveForwardKeyTrail(roomId, sessionId, senderKey, algorithm, userId, deviceId, chainIndex, true)
}
- private fun saveForwardKeyTrail(roomId: String,
- sessionId: String,
- senderKey: String,
- algorithm: String,
- userId: String,
- deviceId: String,
- chainIndex: Long?,
- incoming: Boolean
+ private fun saveForwardKeyTrail(
+ roomId: String,
+ sessionId: String,
+ senderKey: String,
+ algorithm: String,
+ userId: String,
+ deviceId: String,
+ chainIndex: Long?,
+ incoming: Boolean
) {
monarchy.writeAsync { realm ->
val now = clock.epochMillis()
@@ -1617,12 +1631,14 @@ internal class RealmCryptoStore @Inject constructor(
}
}
- override fun markedSessionAsShared(roomId: String?,
- sessionId: String,
- userId: String,
- deviceId: String,
- deviceIdentityKey: String,
- chainIndex: Int) {
+ override fun markedSessionAsShared(
+ roomId: String?,
+ sessionId: String,
+ userId: String,
+ deviceId: String,
+ deviceIdentityKey: String,
+ chainIndex: Int
+ ) {
doRealmTransaction(realmConfiguration) { realm ->
SharedSessionEntity.create(
realm = realm,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmInboundGroupSessionEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmInboundGroupSessionEntity.kt
index 83671b28d9..a4f6c279ac 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmInboundGroupSessionEntity.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmInboundGroupSessionEntity.kt
@@ -33,7 +33,8 @@ internal open class OlmInboundGroupSessionEntity(
// olmInboundGroupSessionData contains Json
var olmInboundGroupSessionData: String? = null,
// Indicate if the key has been backed up to the homeserver
- var backedUp: Boolean = false) :
+ var backedUp: Boolean = false
+) :
RealmObject() {
fun getInboundGroupSession(): OlmInboundGroupSessionWrapper2? {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmSessionEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmSessionEntity.kt
index 1a637d76c4..9f010db288 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmSessionEntity.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmSessionEntity.kt
@@ -25,11 +25,13 @@ import org.matrix.olm.OlmSession
internal fun OlmSessionEntity.Companion.createPrimaryKey(sessionId: String, deviceKey: String) = "$sessionId|$deviceKey"
// olmSessionData is a serialized OlmSession
-internal open class OlmSessionEntity(@PrimaryKey var primaryKey: String = "",
- var sessionId: String? = null,
- var deviceKey: String? = null,
- var olmSessionData: String? = null,
- var lastReceivedMessageTs: Long = 0) :
+internal open class OlmSessionEntity(
+ @PrimaryKey var primaryKey: String = "",
+ var sessionId: String? = null,
+ var deviceKey: String? = null,
+ var olmSessionData: String? = null,
+ var lastReceivedMessageTs: Long = 0
+) :
RealmObject() {
fun getOlmSession(): OlmSession? {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingKeyRequestEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingKeyRequestEntity.kt
index 7a8ba18809..854d148b76 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingKeyRequestEntity.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingKeyRequestEntity.kt
@@ -117,7 +117,7 @@ internal open class OutgoingKeyRequestEntity(
private fun eventToResult(event: Event): RequestResult? {
return when (event.getClearType()) {
- EventType.ROOM_KEY_WITHHELD -> {
+ EventType.ROOM_KEY_WITHHELD -> {
event.content.toModel()?.code?.let {
RequestResult.Failure(it)
}
@@ -125,7 +125,7 @@ internal open class OutgoingKeyRequestEntity(
EventType.FORWARDED_ROOM_KEY -> {
RequestResult.Success((event.content?.get("chain_index") as? Number)?.toInt() ?: 0)
}
- else -> null
+ else -> null
}
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/SharedSessionQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/SharedSessionQueries.kt
index 8bf9794375..85dd50c88e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/SharedSessionQueries.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/SharedSessionQueries.kt
@@ -24,12 +24,14 @@ import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntityFields
-internal fun SharedSessionEntity.Companion.get(realm: Realm,
- roomId: String?,
- sessionId: String,
- userId: String,
- deviceId: String,
- deviceIdentityKey: String?): SharedSessionEntity? {
+internal fun SharedSessionEntity.Companion.get(
+ realm: Realm,
+ roomId: String?,
+ sessionId: String,
+ userId: String,
+ deviceId: String,
+ deviceIdentityKey: String?
+): SharedSessionEntity? {
return realm.where()
.equalTo(SharedSessionEntityFields.ROOM_ID, roomId)
.equalTo(SharedSessionEntityFields.SESSION_ID, sessionId)
@@ -48,12 +50,15 @@ internal fun SharedSessionEntity.Companion.get(realm: Realm, roomId: String?, se
.findAll()
}
-internal fun SharedSessionEntity.Companion.create(realm: Realm, roomId: String?,
- sessionId: String,
- userId: String,
- deviceId: String,
- deviceIdentityKey: String,
- chainIndex: Int): SharedSessionEntity {
+internal fun SharedSessionEntity.Companion.create(
+ realm: Realm,
+ roomId: String?,
+ sessionId: String,
+ userId: String,
+ deviceId: String,
+ deviceIdentityKey: String,
+ chainIndex: Int
+): SharedSessionEntity {
return realm.createObject().apply {
this.roomId = roomId
this.algorithm = MXCRYPTO_ALGORITHM_MEGOLM
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt
index 394c618968..a4b4cd0761 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt
@@ -31,10 +31,11 @@ import org.matrix.android.sdk.internal.task.Task
import javax.inject.Inject
internal interface EncryptEventTask : Task