1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.accessibility; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.never; 22 import static org.mockito.Mockito.spy; 23 import static org.mockito.Mockito.verify; 24 25 import android.content.ContentResolver; 26 import android.content.Context; 27 import android.database.ContentObserver; 28 import android.os.Handler; 29 import android.provider.Settings; 30 31 import androidx.test.core.app.ApplicationProvider; 32 33 import org.junit.After; 34 import org.junit.Test; 35 import org.junit.runner.RunWith; 36 import org.robolectric.RobolectricTestRunner; 37 import org.robolectric.shadow.api.Shadow; 38 import org.robolectric.shadows.ShadowContentResolver; 39 40 import java.util.Collection; 41 import java.util.List; 42 43 /** Test for {@link AccessibilitySettingsContentObserver}. */ 44 @RunWith(RobolectricTestRunner.class) 45 public class AccessibilitySettingsContentObserverTest { 46 47 private static final String SPECIFIC_KEY_A_1 = "SPECIFIC_KEY_A_1"; 48 private static final String SPECIFIC_KEY_A_2 = "SPECIFIC_KEY_A_2"; 49 private static final String SPECIFIC_KEY_B_1 = "SPECIFIC_KEY_B_1"; 50 51 private final Context mContext = ApplicationProvider.getApplicationContext(); 52 private final AccessibilitySettingsContentObserver mObserver = 53 new AccessibilitySettingsContentObserver(new Handler()); 54 private final AccessibilitySettingsContentObserver.ContentObserverCallback mObserverCallbackA = 55 spy(new TestableContentObserverCallback()); 56 private final AccessibilitySettingsContentObserver.ContentObserverCallback mObserverCallbackB = 57 spy(new TestableContentObserverCallback()); 58 private final ContentResolver mContentResolver = mContext.getContentResolver(); 59 60 @Test register_shouldRegisterContentObserverForDefaultKeys()61 public void register_shouldRegisterContentObserverForDefaultKeys() { 62 mObserver.register(mContentResolver); 63 64 ShadowContentResolver shadowContentResolver = Shadow.extract(mContentResolver); 65 assertObserverToUri(shadowContentResolver, 66 Settings.Secure.ACCESSIBILITY_ENABLED, mObserver); 67 assertObserverToUri(shadowContentResolver, 68 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, mObserver); 69 } 70 71 @Test unregister_shouldUnregisterContentObserver()72 public void unregister_shouldUnregisterContentObserver() { 73 mObserver.register(mContentResolver); 74 75 mObserver.unregister(mContentResolver); 76 77 ShadowContentResolver shadowContentResolver = Shadow.extract(mContentResolver); 78 assertNotObserverToUri(shadowContentResolver, Settings.Secure.ACCESSIBILITY_ENABLED); 79 assertNotObserverToUri(shadowContentResolver, 80 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); 81 } 82 83 @Test register_addSpecificKeys_shouldRegisterContentObserverForSpecificAndDefaultKeys()84 public void register_addSpecificKeys_shouldRegisterContentObserverForSpecificAndDefaultKeys() { 85 mObserver.registerKeysToObserverCallback(List.of(SPECIFIC_KEY_A_1), mObserverCallbackA); 86 87 mObserver.register(mContentResolver); 88 89 ShadowContentResolver shadowContentResolver = Shadow.extract(mContentResolver); 90 assertObserverToUri(shadowContentResolver, 91 Settings.Secure.ACCESSIBILITY_ENABLED, mObserver); 92 assertObserverToUri(shadowContentResolver, 93 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, mObserver); 94 assertObserverToUri(shadowContentResolver, SPECIFIC_KEY_A_1, mObserver); 95 } 96 97 @Test onChange_shouldTriggerCallbackOnDefaultKey()98 public void onChange_shouldTriggerCallbackOnDefaultKey() { 99 mObserver.registerObserverCallback(mObserverCallbackA); 100 mObserver.register(mContentResolver); 101 102 mObserver.onChange(/* selfChange= */ false, 103 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_ENABLED)); 104 105 verify(mObserverCallbackA).onChange(Settings.Secure.ACCESSIBILITY_ENABLED); 106 } 107 108 @Test onChange_registerSpecificKeys_shouldTriggerSpecificCallback()109 public void onChange_registerSpecificKeys_shouldTriggerSpecificCallback() { 110 mObserver.registerKeysToObserverCallback( 111 List.of(SPECIFIC_KEY_A_1, SPECIFIC_KEY_A_2), mObserverCallbackA); 112 mObserver.register(mContentResolver); 113 114 mObserver.onChange(/* selfChange= */ false, 115 Settings.Secure.getUriFor(SPECIFIC_KEY_A_2)); 116 117 verify(mObserverCallbackA).onChange(SPECIFIC_KEY_A_2); 118 } 119 120 @Test onChange_registerSpecificKeys_withoutTriggerOtherCallback()121 public void onChange_registerSpecificKeys_withoutTriggerOtherCallback() { 122 mObserver.registerKeysToObserverCallback( 123 List.of(SPECIFIC_KEY_A_1, SPECIFIC_KEY_A_2), mObserverCallbackA); 124 mObserver.registerKeysToObserverCallback( 125 List.of(SPECIFIC_KEY_B_1), mObserverCallbackB); 126 mObserver.register(mContentResolver); 127 128 mObserver.onChange(/* selfChange= */ false, 129 Settings.Secure.getUriFor(SPECIFIC_KEY_B_1)); 130 131 verify(mObserverCallbackA, never()).onChange(SPECIFIC_KEY_A_1); 132 verify(mObserverCallbackA, never()).onChange(SPECIFIC_KEY_A_2); 133 verify(mObserverCallbackA, never()).onChange(SPECIFIC_KEY_B_1); 134 verify(mObserverCallbackB).onChange(SPECIFIC_KEY_B_1); 135 } 136 137 @After tearDown()138 public void tearDown() { 139 mObserver.unregister(mContentResolver); 140 } 141 assertNotObserverToUri(ShadowContentResolver resolver, String key)142 private void assertNotObserverToUri(ShadowContentResolver resolver, String key) { 143 assertThat(resolver.getContentObservers(Settings.Secure.getUriFor(key))).isEmpty(); 144 } 145 assertObserverToUri(ShadowContentResolver resolver, String key, ContentObserver observer)146 private void assertObserverToUri(ShadowContentResolver resolver, 147 String key, ContentObserver observer) { 148 Collection<ContentObserver> observers = 149 resolver.getContentObservers(Settings.Secure.getUriFor(key)); 150 assertThat(observers).contains(observer); 151 } 152 153 private static class TestableContentObserverCallback implements 154 AccessibilitySettingsContentObserver.ContentObserverCallback { 155 @Override onChange(String key)156 public void onChange(String key) { 157 // do nothing 158 } 159 } 160 } 161