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