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.development; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertTrue; 23 24 import android.app.Instrumentation; 25 import android.content.ContentResolver; 26 import android.content.Context; 27 import android.database.ContentObserver; 28 import android.net.Uri; 29 import android.os.Handler; 30 import android.os.Looper; 31 import android.os.UserHandle; 32 import android.provider.Settings; 33 34 import androidx.preference.PreferenceManager; 35 import androidx.preference.PreferenceScreen; 36 import androidx.preference.SwitchPreference; 37 import androidx.test.ext.junit.runners.AndroidJUnit4; 38 import androidx.test.platform.app.InstrumentationRegistry; 39 40 import org.junit.Assert; 41 import org.junit.Before; 42 import org.junit.Test; 43 import org.junit.runner.RunWith; 44 import org.mockito.MockitoAnnotations; 45 46 import java.util.concurrent.CountDownLatch; 47 import java.util.concurrent.TimeUnit; 48 49 @RunWith(AndroidJUnit4.class) 50 public class BackAnimationPreferenceControllerTest { 51 52 private static final int SETTING_VALUE_OFF = 0; 53 private static final int SETTING_VALUE_ON = 1; 54 55 private SwitchPreference mPreference; 56 57 private Context mContext; 58 private BackAnimationPreferenceController mController; 59 private Looper mLooper; 60 61 @Before setUp()62 public void setUp() { 63 MockitoAnnotations.initMocks(this); 64 Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); 65 mContext = instrumentation.getTargetContext(); 66 mController = new BackAnimationPreferenceController(mContext); 67 mPreference = new SwitchPreference(mContext); 68 if (Looper.myLooper() == null) { 69 Looper.prepare(); 70 } 71 mLooper = Looper.myLooper(); 72 73 Settings.Global.putInt(mContext.getContentResolver(), 74 Settings.Global.ENABLE_BACK_ANIMATION, -1); 75 76 final PreferenceManager preferenceManager = new PreferenceManager(mContext); 77 final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext); 78 mPreference.setKey(mController.getPreferenceKey()); 79 screen.addPreference(mPreference); 80 mController.displayPreference(screen); 81 } 82 83 @Test onPreferenceChange_switchEnabled_shouldEnableBackAnimations()84 public void onPreferenceChange_switchEnabled_shouldEnableBackAnimations() { 85 mController.onPreferenceChange(mPreference, true /* new value */); 86 87 final int mode = Settings.Global.getInt(mContext.getContentResolver(), 88 Settings.Global.ENABLE_BACK_ANIMATION, -1 /* default */); 89 assertThat(mode).isEqualTo(SETTING_VALUE_ON); 90 } 91 92 @Test onPreferenceChange_switchDisabled_shouldDisableBackAnimations()93 public void onPreferenceChange_switchDisabled_shouldDisableBackAnimations() { 94 mController.onPreferenceChange(mPreference, false /* new value */); 95 96 final int mode = Settings.Global.getInt(mContext.getContentResolver(), 97 Settings.Global.ENABLE_BACK_ANIMATION, -1 /* default */); 98 assertThat(mode).isEqualTo(SETTING_VALUE_OFF); 99 } 100 101 @Test updateState_settingEnabled_preferenceShouldBeChecked()102 public void updateState_settingEnabled_preferenceShouldBeChecked() { 103 Settings.Global.putInt(mContext.getContentResolver(), 104 Settings.Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_ON); 105 mController.updateState(mPreference); 106 assertTrue(mPreference.isChecked()); 107 } 108 109 @Test updateState_settingDisabled_preferenceShouldNotBeChecked()110 public void updateState_settingDisabled_preferenceShouldNotBeChecked() { 111 Settings.Global.putInt(mContext.getContentResolver(), 112 Settings.Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF); 113 114 mController.updateState(mPreference); 115 assertFalse(mPreference.isChecked()); 116 } 117 118 @Test onDeveloperOptionsSwitchDisabled_shouldDisablePreference()119 public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() 120 throws InterruptedException { 121 ContentResolver contentResolver = mContext.getContentResolver(); 122 int mode = doAndWaitForSettingChange(() -> mController.onDeveloperOptionsSwitchDisabled(), 123 contentResolver); 124 assertThat(mode).isEqualTo(SETTING_VALUE_OFF); 125 assertFalse(mPreference.isEnabled()); 126 assertFalse(mPreference.isChecked()); 127 } 128 doAndWaitForSettingChange(Runnable runnable, ContentResolver contentResolver)129 private int doAndWaitForSettingChange(Runnable runnable, ContentResolver contentResolver) { 130 CountDownLatch countDownLatch = new CountDownLatch(1); 131 ContentObserver settingsObserver = 132 new ContentObserver(new Handler(mLooper)) { 133 @Override 134 public void onChange(boolean selfChange, Uri uri) { 135 countDownLatch.countDown(); 136 } 137 }; 138 contentResolver.registerContentObserver( 139 Settings.Global.getUriFor(Settings.Global.ENABLE_BACK_ANIMATION), 140 false, settingsObserver, UserHandle.USER_SYSTEM 141 ); 142 runnable.run(); 143 try { 144 countDownLatch.await(500, TimeUnit.MILLISECONDS); 145 } catch (InterruptedException e) { 146 Assert.fail(e.getMessage()); 147 } 148 return Settings.Global.getInt(contentResolver, 149 Settings.Global.ENABLE_BACK_ANIMATION, -1 /* default */); 150 } 151 } 152