Merge Android 24Q2 Release (ab/11526283) to aosp-main-future
Bug: 337098550 Merged-In: I96574a79eba581db95d387f0d9c9fde2e004c41c Change-Id: Ib9f2c742f8aa72651ef9eca80a716dd94b9041ea
This commit is contained in:
@@ -4,15 +4,14 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.testutils.XmlTestUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowPowerManager;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -21,9 +20,8 @@ import java.util.List;
|
||||
public class DisplaySettingsTest {
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowPowerManager.class)
|
||||
public void testPreferenceControllers_getPreferenceKeys_existInPreferenceScreen() {
|
||||
final Context context = RuntimeEnvironment.application;
|
||||
final Context context = ApplicationProvider.getApplicationContext();
|
||||
final DisplaySettings fragment = new DisplaySettings();
|
||||
final List<String> preferenceScreenKeys = XmlTestUtils.getKeysFromPreferenceXml(context,
|
||||
fragment.getPreferenceScreenResId());
|
||||
|
||||
@@ -29,10 +29,6 @@ import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
|
||||
import com.android.settings.fuelgauge.batterytip.AnomalyConfigJobService;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -83,22 +79,6 @@ public class SettingsDumpServiceTest {
|
||||
assertThat(mTestService.dumpDefaultBrowser()).isEqualTo(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDumpAnomalyDetection_returnAnomalyInfo() throws JSONException {
|
||||
final SharedPreferences sharedPreferences =
|
||||
RuntimeEnvironment.application.getSharedPreferences(AnomalyConfigJobService.PREF_DB,
|
||||
Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putInt(AnomalyConfigJobService.KEY_ANOMALY_CONFIG_VERSION, ANOMALY_VERSION);
|
||||
editor.commit();
|
||||
doReturn(sharedPreferences).when(mTestService).getSharedPreferences(anyString(), anyInt());
|
||||
|
||||
final JSONObject jsonObject = mTestService.dumpAnomalyDetection();
|
||||
|
||||
assertThat(jsonObject.getInt(AnomalyConfigJobService.KEY_ANOMALY_CONFIG_VERSION)).isEqualTo(
|
||||
ANOMALY_VERSION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDump_printServiceAsKey() {
|
||||
mResolveInfo.activityInfo = new ActivityInfo();
|
||||
|
||||
@@ -31,6 +31,7 @@ import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.search.SearchIndexableRaw;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -42,6 +43,9 @@ import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Tests for {@link AccessibilityButtonPreferenceController}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class AccessibilityButtonPreferenceControllerTest {
|
||||
@@ -88,4 +92,36 @@ public class AccessibilityButtonPreferenceControllerTest {
|
||||
assertThat(mPreference.getTitle()).isEqualTo(
|
||||
mContext.getText(R.string.accessibility_button_title));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateDynamicRawDataToIndex_navigationGestureEnabled_setCorrectIndex() {
|
||||
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
|
||||
.thenReturn(NAV_BAR_MODE_GESTURAL);
|
||||
List<SearchIndexableRaw> rawDataList = new ArrayList<>();
|
||||
|
||||
mController.updateDynamicRawDataToIndex(rawDataList);
|
||||
|
||||
assertThat(rawDataList).hasSize(1);
|
||||
SearchIndexableRaw raw = rawDataList.get(0);
|
||||
assertThat(raw.title).isEqualTo(
|
||||
mResources.getString(R.string.accessibility_button_gesture_title));
|
||||
assertThat(raw.screenTitle).isEqualTo(
|
||||
mResources.getString(R.string.accessibility_shortcuts_settings_title));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateDynamicRawDataToIndex_navigationGestureDisabled_setCorrectIndex() {
|
||||
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
|
||||
.thenReturn(NAV_BAR_MODE_2BUTTON);
|
||||
List<SearchIndexableRaw> rawDataList = new ArrayList<>();
|
||||
|
||||
mController.updateDynamicRawDataToIndex(rawDataList);
|
||||
|
||||
assertThat(rawDataList).hasSize(1);
|
||||
SearchIndexableRaw raw = rawDataList.get(0);
|
||||
assertThat(raw.title).isEqualTo(
|
||||
mResources.getString(R.string.accessibility_button_title));
|
||||
assertThat(raw.screenTitle).isEqualTo(
|
||||
mResources.getString(R.string.accessibility_shortcuts_settings_title));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
|
||||
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@@ -57,7 +58,10 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Tests for {@link AccessibilityDetailsSettingsFragment}. */
|
||||
@Config(shadows = ShadowDevicePolicyManager.class)
|
||||
@Config(shadows = {
|
||||
ShadowDevicePolicyManager.class,
|
||||
ShadowRestrictedLockUtilsInternal.class
|
||||
})
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class AccessibilityDetailsSettingsFragmentTest {
|
||||
private static final String PACKAGE_NAME = "com.foo.bar";
|
||||
|
||||
@@ -52,6 +52,7 @@ import com.android.settings.testutils.XmlTestUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowApplicationPackageManager;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
@@ -87,6 +88,7 @@ import java.util.List;
|
||||
ShadowUserManager.class,
|
||||
ShadowColorDisplayManager.class,
|
||||
ShadowApplicationPackageManager.class,
|
||||
ShadowRestrictedLockUtilsInternal.class,
|
||||
})
|
||||
public class AccessibilitySettingsTest {
|
||||
private static final String PACKAGE_NAME = "com.android.test";
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
*/
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
@@ -50,4 +52,14 @@ public class AccessibilitySetupWizardUtilsTest {
|
||||
verify(layout).setIcon(icon);
|
||||
verify(layout).setHeaderText(title);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setupGlifPreferenceLayout_descriptionIsNull_doesNotCallSetDescriptionText() {
|
||||
GlifPreferenceLayout layout = mock(GlifPreferenceLayout.class);
|
||||
|
||||
AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(mContext, layout, "title",
|
||||
/* description= */ null, /* icon= */ null);
|
||||
|
||||
verify(layout, times(0)).setDescriptionText(any());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ public class AccessibilityShortcutPreferenceFragmentTest {
|
||||
mFragment.updateShortcutPreferenceData();
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
mFragment.getComponentName().flattenToString(), UserShortcutType.SOFTWARE);
|
||||
mFragment.getComponentName().flattenToString());
|
||||
// Compare to default UserShortcutType
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ public class AccessibilityShortcutPreferenceFragmentTest {
|
||||
mFragment.updateShortcutPreferenceData();
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
mFragment.getComponentName().flattenToString(), UserShortcutType.SOFTWARE);
|
||||
mFragment.getComponentName().flattenToString());
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE);
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ public class AccessibilityShortcutPreferenceFragmentTest {
|
||||
mFragment.updateShortcutPreferenceData();
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
mFragment.getComponentName().flattenToString(), UserShortcutType.SOFTWARE);
|
||||
mFragment.getComponentName().flattenToString());
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.HARDWARE);
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ public class AccessibilityShortcutPreferenceFragmentTest {
|
||||
mFragment.saveNonEmptyUserShortcutType(value);
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
mFragment.getComponentName().flattenToString(), UserShortcutType.SOFTWARE);
|
||||
mFragment.getComponentName().flattenToString());
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/** Tests for {@link ArrowPreference} */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ArrowPreferenceTest {
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private ArrowPreference mPreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mPreference = new ArrowPreference(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void construct_withArrow() {
|
||||
assertThat(mPreference.getWidgetLayoutResource()).isEqualTo(
|
||||
R.layout.preference_widget_arrow);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/** Tests for {@link BackgroundPreference} */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class BackgroundPreferenceTest {
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
|
||||
private View mRootView = new View(mContext);
|
||||
@Spy
|
||||
private PreferenceViewHolder mViewHolder = PreferenceViewHolder.createInstanceForTests(
|
||||
mRootView);
|
||||
@Spy
|
||||
private LinearLayout mLinearLayout = new LinearLayout(mContext);
|
||||
private BackgroundPreference mPreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mPreference = new BackgroundPreference(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setBackground_success() {
|
||||
doReturn(mLinearLayout).when(mViewHolder).findViewById(R.id.background);
|
||||
|
||||
mPreference.setBackground(android.R.drawable.screen_background_dark);
|
||||
mPreference.onBindViewHolder(mViewHolder);
|
||||
|
||||
verify(mLinearLayout).setBackground(any());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.UiModeManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.XmlTestUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Tests for {@link ColorContrastFragment}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ColorContrastFragmentTest {
|
||||
|
||||
private ColorContrastFragment mFragment;
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private UiModeManager mUiService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mFragment = spy(new ColorContrastFragment());
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mFragment.getContext()).thenReturn(mContext);
|
||||
when(mContext.getSystemService(UiModeManager.class)).thenReturn(mUiService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMetricsCategory_returnsCorrectCategory() {
|
||||
assertThat(mFragment.getMetricsCategory()).isEqualTo(
|
||||
SettingsEnums.ACCESSIBILITY_COLOR_CONTRAST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPreferenceScreenResId_returnsCorrectXml() {
|
||||
assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(
|
||||
R.xml.accessibility_color_contrast);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLogTag_returnsCorrectTag() {
|
||||
assertThat(mFragment.getLogTag()).isEqualTo("ColorContrastFragment");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNonIndexableKeys_existInXmlLayout() {
|
||||
final List<String> niks =
|
||||
ShortcutsSettingsFragment.SEARCH_INDEX_DATA_PROVIDER
|
||||
.getNonIndexableKeys(mContext);
|
||||
final List<String> keys =
|
||||
XmlTestUtils.getKeysFromPreferenceXml(mContext,
|
||||
R.xml.accessibility_color_contrast);
|
||||
assertThat(keys).containsAtLeastElementsIn(niks);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/** Tests for {@link ContrastPreferenceController}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ContrastPreferenceControllerTest {
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
private static final String PREFERENCE_KEY = "preference_key";
|
||||
|
||||
private Context mContext;
|
||||
private ContrastPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mController = new ContrastPreferenceController(mContext, PREFERENCE_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_flagsEnabled_shouldReturnAvailable() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_COLOR_CONTRAST_CONTROL);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_flagsDisabled_shouldReturnUnsupported() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_COLOR_CONTRAST_CONTROL);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.UiModeManager;
|
||||
import android.content.Context;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.widget.LayoutPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/** Tests for {@link ContrastSelectorPreferenceController}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ContrastSelectorPreferenceControllerTest {
|
||||
|
||||
private static final String PREFERENCE_KEY = "color_contrast_selector";
|
||||
|
||||
@Mock
|
||||
private UiModeManager mUiService;
|
||||
@Mock
|
||||
private Executor mExecutor;
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
@Mock
|
||||
private FrameLayout mFrameLayout;
|
||||
@Mock
|
||||
private LayoutPreference mLayoutPreference;
|
||||
private Context mContext;
|
||||
private ContrastSelectorPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mContext.getMainExecutor()).thenReturn(mExecutor);
|
||||
when(mContext.getSystemService(UiModeManager.class)).thenReturn(mUiService);
|
||||
mController = new ContrastSelectorPreferenceController(mContext, PREFERENCE_KEY);
|
||||
when(mScreen.findPreference(PREFERENCE_KEY)).thenReturn(mLayoutPreference);
|
||||
when(mLayoutPreference.findViewById(anyInt())).thenReturn(mFrameLayout);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_byDefault_shouldReturnAvailable() {
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_shouldAddContrastListener() {
|
||||
mController.displayPreference(mScreen);
|
||||
mController.onStart();
|
||||
|
||||
verify(mUiService).addContrastChangeListener(mExecutor, mController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_shouldRemoveContrastListener() {
|
||||
mController.displayPreference(mScreen);
|
||||
mController.onStart();
|
||||
mController.onStop();
|
||||
|
||||
verify(mUiService).removeContrastChangeListener(mController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_shouldAddClickListener() {
|
||||
mController.displayPreference(mScreen);
|
||||
|
||||
verify(mFrameLayout, times(3)).setOnClickListener(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onContrastChanged_buttonShouldBeSelected() {
|
||||
mController.displayPreference(mScreen);
|
||||
mController.onContrastChanged(1);
|
||||
|
||||
verify(mFrameLayout, times(2)).setSelected(true);
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,7 @@ public class HearingAidPairingDialogFragmentTest {
|
||||
|
||||
final Intent intent = shadowOf(mActivity).getNextStartedActivity();
|
||||
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
|
||||
.isEqualTo(HearingDevicePairingDetail.class.getName());
|
||||
.isEqualTo(HearingDevicePairingFragment.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.bluetooth.BluetoothProgressCategory;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
/** Tests for {@link HearingDevicePairingDetail}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowBluetoothAdapter.class})
|
||||
public class HearingDevicePairingDetailTest {
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedBluetoothDevice;
|
||||
private BluetoothProgressCategory mProgressCategory;
|
||||
private TestHearingDevicePairingDetail mFragment;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
final BluetoothAdapter bluetoothAdapter = spy(BluetoothAdapter.getDefaultAdapter());
|
||||
final ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
|
||||
BluetoothAdapter.getDefaultAdapter());
|
||||
shadowBluetoothAdapter.setEnabled(true);
|
||||
|
||||
mProgressCategory = spy(new BluetoothProgressCategory(mContext));
|
||||
mFragment = spy(new TestHearingDevicePairingDetail());
|
||||
when(mFragment.getContext()).thenReturn(mContext);
|
||||
when(mFragment.findPreference(
|
||||
HearingDevicePairingDetail.KEY_AVAILABLE_HEARING_DEVICES)).thenReturn(
|
||||
mProgressCategory);
|
||||
mFragment.setBluetoothAdapter(bluetoothAdapter);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDeviceListKey_expectedKey() {
|
||||
assertThat(mFragment.getDeviceListKey()).isEqualTo(
|
||||
HearingDevicePairingDetail.KEY_AVAILABLE_HEARING_DEVICES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_bondNone_setProgressFalse() {
|
||||
mFragment.initPreferencesFromPreferenceScreen();
|
||||
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_NONE);
|
||||
|
||||
verify(mProgressCategory).setProgress(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_bonding_setProgressTrue() {
|
||||
mFragment.initPreferencesFromPreferenceScreen();
|
||||
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
|
||||
|
||||
verify(mProgressCategory).setProgress(false);
|
||||
}
|
||||
|
||||
private static class TestHearingDevicePairingDetail extends HearingDevicePairingDetail {
|
||||
TestHearingDevicePairingDetail() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void setBluetoothAdapter(BluetoothAdapter bluetoothAdapter) {
|
||||
this.mBluetoothAdapter = bluetoothAdapter;
|
||||
}
|
||||
|
||||
public void enableScanning() {
|
||||
super.enableScanning();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility;
|
||||
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.bluetooth.BluetoothUuid;
|
||||
import android.bluetooth.le.ScanRecord;
|
||||
import android.bluetooth.le.ScanResult;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.bluetooth.BluetoothDevicePreference;
|
||||
import com.android.settings.bluetooth.BluetoothProgressCategory;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.HearingAidInfo;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Tests for {@link HearingDevicePairingFragment}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowBluetoothAdapter.class})
|
||||
public class HearingDevicePairingFragmentTest {
|
||||
|
||||
private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
|
||||
@Spy
|
||||
private final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
@Spy
|
||||
private final HearingDevicePairingFragment mFragment = new TestHearingDevicePairingFragment();
|
||||
|
||||
@Mock
|
||||
private LocalBluetoothManager mLocalManager;
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedDevice;
|
||||
@Mock
|
||||
private BluetoothProgressCategory mAvailableHearingDeviceGroup;
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private BluetoothDevice mDevice;
|
||||
private BluetoothDevicePreference mDevicePreference;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mFragment.mLocalManager = mLocalManager;
|
||||
mFragment.mCachedDeviceManager = mCachedDeviceManager;
|
||||
mFragment.mBluetoothAdapter = mBluetoothAdapter;
|
||||
doReturn(mContext).when(mFragment).getContext();
|
||||
doReturn(mAvailableHearingDeviceGroup).when(mFragment).findPreference(
|
||||
"available_hearing_devices");
|
||||
mFragment.initPreferencesFromPreferenceScreen();
|
||||
|
||||
|
||||
mDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS);
|
||||
doReturn(mDevice).when(mCachedDevice).getDevice();
|
||||
final Pair<Drawable, String> pair = new Pair<>(mock(Drawable.class), "test_device");
|
||||
doReturn(pair).when(mCachedDevice).getDrawableWithDescription();
|
||||
|
||||
mDevicePreference = new BluetoothDevicePreference(mContext, mCachedDevice, true,
|
||||
BluetoothDevicePreference.SortType.TYPE_DEFAULT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startAndStopScanning_stateIsCorrect() {
|
||||
mFragment.startScanning();
|
||||
|
||||
verify(mFragment).startLeScanning();
|
||||
|
||||
mFragment.stopScanning();
|
||||
|
||||
verify(mFragment).stopLeScanning();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceDeleted_stateIsCorrect() {
|
||||
mFragment.mDevicePreferenceMap.put(mCachedDevice, mDevicePreference);
|
||||
|
||||
assertThat(mFragment.mDevicePreferenceMap).isNotEmpty();
|
||||
|
||||
mFragment.onDeviceDeleted(mCachedDevice);
|
||||
|
||||
assertThat(mFragment.mDevicePreferenceMap).isEmpty();
|
||||
verify(mAvailableHearingDeviceGroup).removePreference(mDevicePreference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addDevice_bluetoothOff_doNothing() {
|
||||
doReturn(BluetoothAdapter.STATE_OFF).when(mBluetoothAdapter).getState();
|
||||
|
||||
assertThat(mFragment.mDevicePreferenceMap.size()).isEqualTo(0);
|
||||
|
||||
mFragment.addDevice(mCachedDevice);
|
||||
|
||||
verify(mAvailableHearingDeviceGroup, never()).addPreference(mDevicePreference);
|
||||
assertThat(mFragment.mDevicePreferenceMap.size()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addDevice_addToAvailableHearingDeviceGroup() {
|
||||
doReturn(BluetoothAdapter.STATE_ON).when(mBluetoothAdapter).getState();
|
||||
|
||||
assertThat(mFragment.mDevicePreferenceMap.size()).isEqualTo(0);
|
||||
|
||||
mFragment.addDevice(mCachedDevice);
|
||||
|
||||
verify(mAvailableHearingDeviceGroup).addPreference(mDevicePreference);
|
||||
assertThat(mFragment.mDevicePreferenceMap.size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleLeScanResult_markDeviceAsHearingAid() {
|
||||
ScanResult scanResult = mock(ScanResult.class);
|
||||
doReturn(mDevice).when(scanResult).getDevice();
|
||||
doReturn(mCachedDevice).when(mCachedDeviceManager).findDevice(mDevice);
|
||||
|
||||
mFragment.handleLeScanResult(scanResult);
|
||||
|
||||
verify(mCachedDevice).setHearingAidInfo(new HearingAidInfo.Builder().build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleLeScanResult_isAndroidCompatible_addDevice() {
|
||||
ScanResult scanResult = mock(ScanResult.class);
|
||||
doReturn(mDevice).when(scanResult).getDevice();
|
||||
doReturn(mCachedDevice).when(mCachedDeviceManager).findDevice(mDevice);
|
||||
doReturn(true).when(mFragment).isAndroidCompatibleHearingAid(scanResult);
|
||||
|
||||
mFragment.handleLeScanResult(scanResult);
|
||||
|
||||
verify(mFragment).addDevice(mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleLeScanResult_isNotAndroidCompatible_() {
|
||||
ScanResult scanResult = mock(ScanResult.class);
|
||||
doReturn(mDevice).when(scanResult).getDevice();
|
||||
doReturn(mCachedDevice).when(mCachedDeviceManager).findDevice(mDevice);
|
||||
doReturn(false).when(mFragment).isAndroidCompatibleHearingAid(scanResult);
|
||||
|
||||
mFragment.handleLeScanResult(scanResult);
|
||||
|
||||
verify(mFragment).discoverServices(mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_deviceConnected_inSelectedList_finish() {
|
||||
doReturn(true).when(mCachedDevice).isConnected();
|
||||
mFragment.mSelectedDeviceList.add(mDevice);
|
||||
|
||||
mFragment.onProfileConnectionStateChanged(mCachedDevice, BluetoothAdapter.STATE_CONNECTED,
|
||||
BluetoothProfile.A2DP);
|
||||
|
||||
verify(mFragment).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_deviceConnected_notInSelectedList_deleteDevice() {
|
||||
doReturn(true).when(mCachedDevice).isConnected();
|
||||
|
||||
mFragment.onProfileConnectionStateChanged(mCachedDevice, BluetoothAdapter.STATE_CONNECTED,
|
||||
BluetoothProfile.A2DP);
|
||||
|
||||
verify(mFragment).removeDevice(mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_deviceNotConnected_doNothing() {
|
||||
doReturn(false).when(mCachedDevice).isConnected();
|
||||
|
||||
mFragment.onProfileConnectionStateChanged(mCachedDevice, BluetoothAdapter.STATE_CONNECTED,
|
||||
BluetoothProfile.A2DP);
|
||||
|
||||
verify(mFragment, never()).finish();
|
||||
verify(mFragment, never()).removeDevice(mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBluetoothStateChanged_stateOn_startScanningAndShowToast() {
|
||||
mFragment.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
|
||||
|
||||
verify(mFragment).startScanning();
|
||||
verify(mFragment).showBluetoothTurnedOnToast();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBluetoothStateChanged_stateOff_finish() {
|
||||
mFragment.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
|
||||
|
||||
verify(mFragment).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_bonded_finish() {
|
||||
mFragment.onDeviceBondStateChanged(mCachedDevice, BluetoothDevice.BOND_BONDED);
|
||||
|
||||
verify(mFragment).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_selectedDeviceNotBonded_startScanning() {
|
||||
mFragment.mSelectedDevice = mDevice;
|
||||
|
||||
mFragment.onDeviceBondStateChanged(mCachedDevice, BluetoothDevice.BOND_NONE);
|
||||
|
||||
verify(mFragment).startScanning();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAndroidCompatibleHearingAid_asha_returnTrue() {
|
||||
ScanResult scanResult = createAshaScanResult();
|
||||
|
||||
boolean isCompatible = mFragment.isAndroidCompatibleHearingAid(scanResult);
|
||||
|
||||
assertThat(isCompatible).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAndroidCompatibleHearingAid_has_returnTrue() {
|
||||
ScanResult scanResult = createHasScanResult();
|
||||
|
||||
boolean isCompatible = mFragment.isAndroidCompatibleHearingAid(scanResult);
|
||||
|
||||
assertThat(isCompatible).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAndroidCompatibleHearingAid_mfiHas_returnFalse() {
|
||||
ScanResult scanResult = createMfiHasScanResult();
|
||||
|
||||
boolean isCompatible = mFragment.isAndroidCompatibleHearingAid(scanResult);
|
||||
|
||||
assertThat(isCompatible).isFalse();
|
||||
}
|
||||
|
||||
private ScanResult createAshaScanResult() {
|
||||
ScanResult scanResult = mock(ScanResult.class);
|
||||
ScanRecord scanRecord = mock(ScanRecord.class);
|
||||
byte[] fakeAshaServiceData = new byte[] {
|
||||
0x09, 0x16, (byte) 0xf0, (byte) 0xfd, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04};
|
||||
doReturn(scanRecord).when(scanResult).getScanRecord();
|
||||
doReturn(fakeAshaServiceData).when(scanRecord).getServiceData(BluetoothUuid.HEARING_AID);
|
||||
return scanResult;
|
||||
}
|
||||
|
||||
private ScanResult createHasScanResult() {
|
||||
ScanResult scanResult = mock(ScanResult.class);
|
||||
ScanRecord scanRecord = mock(ScanRecord.class);
|
||||
doReturn(scanRecord).when(scanResult).getScanRecord();
|
||||
doReturn(List.of(BluetoothUuid.HAS)).when(scanRecord).getServiceUuids();
|
||||
return scanResult;
|
||||
}
|
||||
|
||||
private ScanResult createMfiHasScanResult() {
|
||||
ScanResult scanResult = mock(ScanResult.class);
|
||||
ScanRecord scanRecord = mock(ScanRecord.class);
|
||||
byte[] fakeMfiServiceData = new byte[] {0x00, 0x00, 0x00, 0x00};
|
||||
doReturn(scanRecord).when(scanResult).getScanRecord();
|
||||
doReturn(fakeMfiServiceData).when(scanRecord).getServiceData(BluetoothUuid.MFI_HAS);
|
||||
return scanResult;
|
||||
}
|
||||
|
||||
private class TestHearingDevicePairingFragment extends HearingDevicePairingFragment {
|
||||
@Override
|
||||
protected Preference getCachedPreference(String key) {
|
||||
if (key.equals(TEST_DEVICE_ADDRESS)) {
|
||||
return mDevicePreference;
|
||||
}
|
||||
return super.getCachedPreference(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility;
|
||||
|
||||
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
|
||||
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class KeyboardBounceKeyPreferenceControllerTest {
|
||||
|
||||
private static final String KEY_ACCESSIBILITY_BOUNCE_KEYS =
|
||||
Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS;
|
||||
private static final int UNKNOWN = -1;
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext));
|
||||
private final KeyboardBounceKeyPreferenceController mController =
|
||||
new KeyboardBounceKeyPreferenceController(mContext,
|
||||
KeyboardBounceKeyPreferenceController.PREF_KEY);
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||
mSwitchPreference.setKey(KeyboardBounceKeyPreferenceController.PREF_KEY);
|
||||
screen.addPreference(mSwitchPreference);
|
||||
mController.displayPreference(screen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_byDefault_shouldReturnAvailable() {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||
BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_disableBounceKey_onResumeShouldReturnFalse() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS, OFF);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
assertThat(mSwitchPreference.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_enableBounceKey_onResumeShouldReturnTrue() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS, ON);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
assertThat(mController.isChecked()).isTrue();
|
||||
assertThat(mSwitchPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performClick_enableBounceKey_shouldReturnTrue() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS, OFF);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
verify(mSwitchPreference).setChecked(true);
|
||||
assertThat(mController.isChecked()).isTrue();
|
||||
assertThat(mSwitchPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performClick_disableBounceKey_shouldReturnFalse() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS, ON);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
verify(mSwitchPreference).setChecked(false);
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
assertThat(mSwitchPreference.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_setFalse_shouldDisableBounceKey() {
|
||||
mController.setChecked(false);
|
||||
|
||||
assertThat(Settings.Secure.getInt(
|
||||
mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS, UNKNOWN)).isEqualTo(
|
||||
OFF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_setTrue_shouldEnableBounceKey() {
|
||||
mController.setChecked(true);
|
||||
|
||||
assertThat(Settings.Secure.getInt(
|
||||
mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS,
|
||||
UNKNOWN)).isNotEqualTo(OFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility;
|
||||
|
||||
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
|
||||
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class KeyboardSlowKeyPreferenceControllerTest {
|
||||
|
||||
private static final String KEY_ACCESSIBILITY_SLOW_KEYS =
|
||||
Settings.Secure.ACCESSIBILITY_SLOW_KEYS;
|
||||
private static final int UNKNOWN = -1;
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext));
|
||||
private final KeyboardSlowKeyPreferenceController mController =
|
||||
new KeyboardSlowKeyPreferenceController(mContext,
|
||||
KeyboardSlowKeyPreferenceController.PREF_KEY);
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||
mSwitchPreference.setKey(KeyboardSlowKeyPreferenceController.PREF_KEY);
|
||||
screen.addPreference(mSwitchPreference);
|
||||
mController.displayPreference(screen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_byDefault_shouldReturnAvailable() {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||
BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_disableSlowKey_onResumeShouldReturnFalse() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, OFF);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
assertThat(mSwitchPreference.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_enableSlowKey_onResumeShouldReturnTrue() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, ON);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
assertThat(mController.isChecked()).isTrue();
|
||||
assertThat(mSwitchPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performClick_enableSlowKey_shouldReturnTrue() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, OFF);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
verify(mSwitchPreference).setChecked(true);
|
||||
assertThat(mController.isChecked()).isTrue();
|
||||
assertThat(mSwitchPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performClick_disableSlowKey_shouldReturnFalse() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, ON);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
verify(mSwitchPreference).setChecked(false);
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
assertThat(mSwitchPreference.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_setFalse_shouldDisableSlowKey() {
|
||||
mController.setChecked(false);
|
||||
|
||||
assertThat(Settings.Secure.getInt(
|
||||
mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, UNKNOWN)).isEqualTo(
|
||||
OFF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_setTrue_shouldEnableSlowKey() {
|
||||
mController.setChecked(true);
|
||||
|
||||
assertThat(Settings.Secure.getInt(
|
||||
mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, UNKNOWN)).isNotEqualTo(
|
||||
OFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility;
|
||||
|
||||
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
|
||||
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class KeyboardStickyKeyPreferenceControllerTest {
|
||||
|
||||
private static final String KEY_ACCESSIBILITY_STICKY_KEYS =
|
||||
Settings.Secure.ACCESSIBILITY_STICKY_KEYS;
|
||||
private static final int UNKNOWN = -1;
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext));
|
||||
private final KeyboardStickyKeyPreferenceController mController =
|
||||
new KeyboardStickyKeyPreferenceController(mContext,
|
||||
KeyboardStickyKeyPreferenceController.PREF_KEY);
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||
mSwitchPreference.setKey(KeyboardStickyKeyPreferenceController.PREF_KEY);
|
||||
screen.addPreference(mSwitchPreference);
|
||||
mController.displayPreference(screen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_byDefault_shouldReturnAvailable() {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||
BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_disableStickyKey_onResumeShouldReturnFalse() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, OFF);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
assertThat(mSwitchPreference.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_enableStickyKey_onResumeShouldReturnTrue() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, ON);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
assertThat(mController.isChecked()).isTrue();
|
||||
assertThat(mSwitchPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performClick_enableStickyKey_shouldReturnTrue() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, OFF);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
verify(mSwitchPreference).setChecked(true);
|
||||
assertThat(mController.isChecked()).isTrue();
|
||||
assertThat(mSwitchPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performClick_disableStickyKey_shouldReturnFalse() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, ON);
|
||||
|
||||
mController.updateState(mSwitchPreference);
|
||||
|
||||
mSwitchPreference.performClick();
|
||||
|
||||
verify(mSwitchPreference).setChecked(false);
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
assertThat(mSwitchPreference.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_setFalse_shouldDisableStickyKey() {
|
||||
mController.setChecked(false);
|
||||
|
||||
assertThat(Settings.Secure.getInt(
|
||||
mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, UNKNOWN)).isEqualTo(OFF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_setTrue_shouldEnableStickyKey() {
|
||||
mController.setChecked(true);
|
||||
|
||||
assertThat(Settings.Secure.getInt(
|
||||
mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, UNKNOWN)).isEqualTo(ON);
|
||||
}
|
||||
}
|
||||
@@ -23,9 +23,13 @@ import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.vibrator.Flags;
|
||||
@@ -37,6 +41,7 @@ import androidx.preference.SwitchPreference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -49,7 +54,6 @@ import org.robolectric.RobolectricTestRunner;
|
||||
/** Tests for {@link KeyboardVibrationTogglePreferenceController}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class KeyboardVibrationTogglePreferenceControllerTest {
|
||||
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
@@ -59,8 +63,8 @@ public class KeyboardVibrationTogglePreferenceControllerTest {
|
||||
private Context mContext;
|
||||
private Resources mResources;
|
||||
private KeyboardVibrationTogglePreferenceController mController;
|
||||
|
||||
private SwitchPreference mPreference;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -68,6 +72,7 @@ public class KeyboardVibrationTogglePreferenceControllerTest {
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mResources = spy(mContext.getResources());
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mController = new KeyboardVibrationTogglePreferenceController(mContext, "preferenceKey");
|
||||
mPreference = new SwitchPreference(mContext);
|
||||
when(mPreferenceScreen.findPreference(
|
||||
@@ -148,6 +153,8 @@ public class KeyboardVibrationTogglePreferenceControllerTest {
|
||||
mController.setChecked(true);
|
||||
|
||||
assertThat(readSystemSetting(Settings.System.KEYBOARD_VIBRATION_ENABLED)).isEqualTo(ON);
|
||||
verify(mFeatureFactory.metricsFeatureProvider).action(any(),
|
||||
eq(SettingsEnums.ACTION_KEYBOARD_VIBRATION_CHANGED), eq(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -160,6 +167,8 @@ public class KeyboardVibrationTogglePreferenceControllerTest {
|
||||
mController.setChecked(false);
|
||||
|
||||
assertThat(readSystemSetting(Settings.System.KEYBOARD_VIBRATION_ENABLED)).isEqualTo(OFF);
|
||||
verify(mFeatureFactory.metricsFeatureProvider).action(any(),
|
||||
eq(SettingsEnums.ACTION_KEYBOARD_VIBRATION_CHANGED), eq(false));
|
||||
}
|
||||
|
||||
private void updateSystemSetting(String key, int value) {
|
||||
|
||||
@@ -31,9 +31,14 @@ import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
|
||||
import org.junit.Rule;
|
||||
@@ -45,6 +50,7 @@ import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -53,6 +59,9 @@ import java.util.List;
|
||||
|
||||
/** Test for {@link RestrictedPreferenceHelper}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
ShadowRestrictedLockUtilsInternal.class
|
||||
})
|
||||
public class RestrictedPreferenceHelperTest {
|
||||
|
||||
private static final String PACKAGE_NAME = "com.android.test";
|
||||
@@ -72,6 +81,11 @@ public class RestrictedPreferenceHelperTest {
|
||||
private AccessibilityShortcutInfo mShortcutInfo;
|
||||
private final RestrictedPreferenceHelper mHelper = new RestrictedPreferenceHelper(mContext);
|
||||
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
@Test
|
||||
public void createAccessibilityServicePreferenceList_hasOneInfo_containsSameKey() {
|
||||
final String key = COMPONENT_NAME.flattenToString();
|
||||
@@ -85,6 +99,37 @@ public class RestrictedPreferenceHelperTest {
|
||||
assertThat(preference.getKey()).isEqualTo(key);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
|
||||
android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED})
|
||||
public void createAccessibilityServicePreferenceList_ecmRestricted_prefIsEcmRestricted() {
|
||||
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(
|
||||
mServiceInfo.getResolveInfo().serviceInfo.packageName);
|
||||
final List<AccessibilityServiceInfo> infoList = new ArrayList<>(
|
||||
singletonList(mServiceInfo));
|
||||
|
||||
final List<RestrictedPreference> preferenceList =
|
||||
mHelper.createAccessibilityServicePreferenceList(infoList);
|
||||
final RestrictedPreference preference = preferenceList.get(0);
|
||||
|
||||
assertThat(preference.isDisabledByEcm()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
|
||||
android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED})
|
||||
public void createAccessibilityServicePreferenceList_ecmNotRestricted_prefIsNotEcmRestricted() {
|
||||
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
|
||||
final List<AccessibilityServiceInfo> infoList = new ArrayList<>(
|
||||
singletonList(mServiceInfo));
|
||||
|
||||
final List<RestrictedPreference> preferenceList =
|
||||
mHelper.createAccessibilityServicePreferenceList(infoList);
|
||||
final RestrictedPreference preference = preferenceList.get(0);
|
||||
|
||||
assertThat(preference.isDisabledByEcm()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAccessibilityActivityPreferenceList_hasOneInfo_containsSameKey() {
|
||||
final String key = COMPONENT_NAME.flattenToString();
|
||||
|
||||
@@ -19,12 +19,13 @@ package com.android.settings.accessibility;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.annotation.NonNull;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -33,6 +34,7 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.os.Bundle;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
@@ -40,12 +42,15 @@ import android.service.quicksettings.TileService;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.Flags;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
|
||||
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
|
||||
import com.android.settings.widget.SettingsMainSwitchPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -53,6 +58,7 @@ import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
@@ -298,7 +304,9 @@ public class ToggleAccessibilityServicePreferenceFragmentTest {
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG)
|
||||
public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning()
|
||||
@RequiresFlagsDisabled(
|
||||
com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN)
|
||||
public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning_showDialog()
|
||||
throws Throwable {
|
||||
setupServiceWarningRequired(false);
|
||||
mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null);
|
||||
@@ -309,6 +317,23 @@ public class ToggleAccessibilityServicePreferenceFragmentTest {
|
||||
AccessibilityDialogUtils.DialogEnums.EDIT_SHORTCUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG,
|
||||
com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN})
|
||||
public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning_launchActivity()
|
||||
throws Throwable {
|
||||
setupServiceWarningRequired(false);
|
||||
mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null);
|
||||
doNothing().when(mContext).startActivity(any());
|
||||
|
||||
mFragment.onSettingsClicked(mFragment.mShortcutPreference);
|
||||
|
||||
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mContext).startActivity(captor.capture());
|
||||
assertThat(captor.getValue().getExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
|
||||
.isEqualTo(EditShortcutsPreferenceFragment.class.getName());
|
||||
}
|
||||
|
||||
private void setupTileService(String packageName, String name, String tileName) {
|
||||
final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE);
|
||||
final ResolveInfo info = new ResolveInfo();
|
||||
|
||||
@@ -169,7 +169,7 @@ public class ToggleFeaturePreferenceFragmentTest {
|
||||
mFragment.updateShortcutPreferenceData();
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
mFragment.mComponentName.flattenToString(), UserShortcutType.SOFTWARE);
|
||||
mFragment.mComponentName.flattenToString());
|
||||
// Compare to default UserShortcutType
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE);
|
||||
}
|
||||
@@ -185,7 +185,7 @@ public class ToggleFeaturePreferenceFragmentTest {
|
||||
mFragment.updateShortcutPreferenceData();
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
mFragment.mComponentName.flattenToString(), UserShortcutType.SOFTWARE);
|
||||
mFragment.mComponentName.flattenToString());
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE);
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ public class ToggleFeaturePreferenceFragmentTest {
|
||||
mFragment.updateShortcutPreferenceData();
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
mFragment.mComponentName.flattenToString(), UserShortcutType.SOFTWARE);
|
||||
mFragment.mComponentName.flattenToString());
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.HARDWARE);
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ public class ToggleFeaturePreferenceFragmentTest {
|
||||
mFragment.saveNonEmptyUserShortcutType(value);
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
mFragment.mComponentName.flattenToString(), UserShortcutType.SOFTWARE);
|
||||
mFragment.mComponentName.flattenToString());
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE);
|
||||
}
|
||||
|
||||
|
||||
@@ -374,7 +374,7 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
mFragController.get().updateShortcutPreferenceData();
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
MAGNIFICATION_CONTROLLER_NAME, UserShortcutType.SOFTWARE);
|
||||
MAGNIFICATION_CONTROLLER_NAME);
|
||||
// Compare to default UserShortcutType
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE);
|
||||
}
|
||||
@@ -388,7 +388,7 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
mFragController.get().updateShortcutPreferenceData();
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
MAGNIFICATION_CONTROLLER_NAME, UserShortcutType.SOFTWARE);
|
||||
MAGNIFICATION_CONTROLLER_NAME);
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE | UserShortcutType.TRIPLETAP);
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
mFragController.get().updateShortcutPreferenceData();
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
MAGNIFICATION_CONTROLLER_NAME, UserShortcutType.SOFTWARE);
|
||||
MAGNIFICATION_CONTROLLER_NAME);
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.TRIPLETAP);
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
mFragController.get().updateShortcutPreferenceData();
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
MAGNIFICATION_CONTROLLER_NAME, UserShortcutType.SOFTWARE);
|
||||
MAGNIFICATION_CONTROLLER_NAME);
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.TWOFINGERTRIPLETAP);
|
||||
}
|
||||
|
||||
@@ -431,7 +431,7 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
mFragController.get().updateShortcutPreferenceData();
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
MAGNIFICATION_CONTROLLER_NAME, UserShortcutType.SOFTWARE);
|
||||
MAGNIFICATION_CONTROLLER_NAME);
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.TWOFINGERTRIPLETAP);
|
||||
}
|
||||
|
||||
@@ -507,7 +507,7 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
fragment.saveNonEmptyUserShortcutType(value);
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
MAGNIFICATION_CONTROLLER_NAME, UserShortcutType.SOFTWARE);
|
||||
MAGNIFICATION_CONTROLLER_NAME);
|
||||
assertThat(value).isEqualTo(6);
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.HARDWARE | UserShortcutType.TRIPLETAP);
|
||||
}
|
||||
@@ -529,7 +529,7 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
fragment.saveNonEmptyUserShortcutType(value);
|
||||
|
||||
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
|
||||
MAGNIFICATION_CONTROLLER_NAME, UserShortcutType.SOFTWARE);
|
||||
MAGNIFICATION_CONTROLLER_NAME);
|
||||
assertThat(value).isEqualTo(UserShortcutType.TWOFINGERTRIPLETAP);
|
||||
assertThat(expectedType).isEqualTo(UserShortcutType.TWOFINGERTRIPLETAP);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class ViewAllBluetoothDevicesPreferenceControllerTest {
|
||||
private final String TEST_KEY = "test_key";
|
||||
|
||||
@Spy
|
||||
private HearingDevicePairingDetail mFragment = new HearingDevicePairingDetail();
|
||||
private HearingDevicePairingFragment mFragment = new HearingDevicePairingFragment();
|
||||
private FragmentActivity mActivity;
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
@@ -74,13 +74,13 @@ public class ViewAllBluetoothDevicesPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlePreferenceTreeClick_expectedPreference_launchBluetoothPairingDetail() {
|
||||
doNothing().when(mController).launchBluetoothPairingDetail();
|
||||
public void handlePreferenceTreeClick_expectedPreference_launchConnectedDevicePage() {
|
||||
doNothing().when(mController).launchConnectedDevicePage();
|
||||
mPreference.setKey(TEST_KEY);
|
||||
|
||||
boolean status = mController.handlePreferenceTreeClick(mPreference);
|
||||
|
||||
verify(mController).launchBluetoothPairingDetail();
|
||||
verify(mController).launchConnectedDevicePage();
|
||||
assertThat(status).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link AdvancedShortcutsPreferenceController}
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class AdvancedShortcutsPreferenceControllerTest {
|
||||
private static final String PREF_KEY = "prefKey";
|
||||
private static final String TARGET_MAGNIFICATION =
|
||||
"com.android.server.accessibility.MagnificationController";
|
||||
private static final String TARGET_FAKE =
|
||||
new ComponentName("FakePackage", "FakeClass").flattenToString();
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private AdvancedShortcutsPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mController = new AdvancedShortcutsPreferenceController(mContext, PREF_KEY);
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
Preference preference = new Preference(mContext);
|
||||
preference.setKey(PREF_KEY);
|
||||
PreferenceScreen preferenceScreen =
|
||||
new PreferenceManager(mContext).createPreferenceScreen(mContext);
|
||||
preferenceScreen.addPreference(preference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_targetIsMagnificationAndIsExpanded_returnsConditionallyUnavailable() {
|
||||
mController.setExpanded(true);
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_targetIsMagnificationAndIsNotExpanded_returnsAvailableUnsearchable() {
|
||||
mController.setExpanded(false);
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_targetIsNotMagnificationAndIsNotExpanded_returnsConditionallyUnavailable() {
|
||||
mController.setExpanded(false);
|
||||
mController.setShortcutTargets(Set.of(TARGET_FAKE));
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_targetIsNotMagnificationAndIsExpanded_returnsConditionallyUnavailable() {
|
||||
mController.setExpanded(true);
|
||||
mController.setShortcutTargets(Set.of(TARGET_FAKE));
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setExpanded_expand_updateExpandedValue() {
|
||||
mController.setExpanded(true);
|
||||
|
||||
assertThat(mController.isExpanded()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setExpanded_collapse_updateExpandedValue() {
|
||||
mController.setExpanded(false);
|
||||
|
||||
assertThat(mController.isExpanded()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_multipleTargets_returnFalse() {
|
||||
mController.setShortcutTargets(Set.of(TARGET_FAKE, TARGET_MAGNIFICATION));
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_magnificationTargetOnly_returnTrue() {
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_nonMagnificationTarget_returnFalse() {
|
||||
mController.setShortcutTargets(Set.of(TARGET_FAKE));
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_returnFalse() {
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,556 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
|
||||
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
|
||||
import static com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment.SHORTCUT_SETTINGS;
|
||||
|
||||
import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_DEFERRED_SETUP;
|
||||
import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_FIRST_RUN;
|
||||
import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_PRE_DEFERRED_SETUP;
|
||||
import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_SETUP_FLOW;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.provider.Settings;
|
||||
import android.util.Pair;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.testing.FragmentScenario;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.TwoStatePreference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.internal.accessibility.common.ShortcutConstants;
|
||||
import com.android.internal.accessibility.dialog.AccessibilityTarget;
|
||||
import com.android.internal.accessibility.util.ShortcutUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.accessibility.AccessibilityUtil;
|
||||
import com.android.settings.accessibility.PreferredShortcuts;
|
||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import com.google.android.setupcompat.util.WizardManagerHelper;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowAccessibilityManager;
|
||||
import org.robolectric.shadows.ShadowContentResolver;
|
||||
import org.robolectric.shadows.ShadowLooper;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link EditShortcutsPreferenceFragment}
|
||||
*/
|
||||
@Config(shadows = SettingsShadowResources.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class EditShortcutsPreferenceFragmentTest {
|
||||
private static final int METRICS_CATEGORY = 123;
|
||||
private static final CharSequence SCREEN_TITLE = "Fake shortcut title";
|
||||
private static final ComponentName TARGET_FAKE_COMPONENT =
|
||||
new ComponentName("FakePackage", "FakeClass");
|
||||
private static final String TARGET = MAGNIFICATION_CONTROLLER_NAME;
|
||||
private static final Set<String> TARGETS = Set.of(TARGET);
|
||||
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private FragmentActivity mActivity;
|
||||
private FragmentScenario<EditShortcutsPreferenceFragment> mFragmentScenario;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
SettingsShadowResources.overrideResource(
|
||||
com.android.internal.R.integer.config_navBarInteractionMode,
|
||||
NAV_BAR_MODE_GESTURAL);
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
|
||||
Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE);
|
||||
|
||||
mActivity = Robolectric.buildActivity(FragmentActivity.class).get();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
if (mFragmentScenario != null) {
|
||||
mFragmentScenario.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showEditShortcutScreen_targetIsMagnification_launchSubSetting() {
|
||||
EditShortcutsPreferenceFragment.showEditShortcutScreen(
|
||||
mActivity, METRICS_CATEGORY, SCREEN_TITLE,
|
||||
MAGNIFICATION_COMPONENT_NAME, /* fromIntent= */ null);
|
||||
|
||||
assertLaunchSubSettingWithCurrentTargetComponents(
|
||||
MAGNIFICATION_CONTROLLER_NAME, /* isInSuw= */ false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showEditShortcutScreen_launchSubSetting() {
|
||||
EditShortcutsPreferenceFragment.showEditShortcutScreen(
|
||||
mActivity, METRICS_CATEGORY, SCREEN_TITLE,
|
||||
TARGET_FAKE_COMPONENT, /* fromIntent= */ null);
|
||||
|
||||
assertLaunchSubSettingWithCurrentTargetComponents(
|
||||
TARGET_FAKE_COMPONENT.flattenToString(), /* isInSuw= */ false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showEditShortcutScreen_inSuw_launchSubSettingWithSuw() {
|
||||
EditShortcutsPreferenceFragment.showEditShortcutScreen(
|
||||
mActivity, METRICS_CATEGORY, SCREEN_TITLE,
|
||||
TARGET_FAKE_COMPONENT, createSuwIntent(new Intent(), /* isInSuw= */ true));
|
||||
|
||||
assertLaunchSubSettingWithCurrentTargetComponents(
|
||||
TARGET_FAKE_COMPONENT.flattenToString(), /* isInSuw= */ true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fragmentCreated_inSuw_controllersTargetsSet() {
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ true);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.CREATED);
|
||||
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
List<ShortcutOptionPreferenceController> controllers =
|
||||
getShortcutOptionPreferenceControllers(fragment);
|
||||
|
||||
for (ShortcutOptionPreferenceController controller : controllers) {
|
||||
assertThat(controller.getShortcutTargets()).containsExactlyElementsIn(TARGETS);
|
||||
assertThat(controller.isInSetupWizard()).isTrue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fragmentCreated_notInSuw_controllersTargetsSet() {
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.CREATED);
|
||||
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
List<ShortcutOptionPreferenceController> controllers =
|
||||
getShortcutOptionPreferenceControllers(fragment);
|
||||
|
||||
for (ShortcutOptionPreferenceController controller : controllers) {
|
||||
assertThat(controller.getShortcutTargets()).containsExactlyElementsIn(TARGETS);
|
||||
assertThat(controller.isInSetupWizard()).isFalse();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fragmentCreated_settingsObserversAreRegistered() {
|
||||
ShadowContentResolver contentResolver = shadowOf(mContext.getContentResolver());
|
||||
for (Uri uri : SHORTCUT_SETTINGS) {
|
||||
assertThat(contentResolver.getContentObservers(uri)).isEmpty();
|
||||
}
|
||||
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.CREATED);
|
||||
|
||||
for (Uri uri : SHORTCUT_SETTINGS) {
|
||||
assertThat(contentResolver.getContentObservers(uri)).isNotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fragmentDestroyed_unregisterSettingsObserver() {
|
||||
ShadowContentResolver contentResolver = shadowOf(mContext.getContentResolver());
|
||||
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false)
|
||||
.moveToState(Lifecycle.State.CREATED);
|
||||
mFragmentScenario.onFragment(EditShortcutsPreferenceFragment::onDestroy);
|
||||
|
||||
for (Uri uri : SHORTCUT_SETTINGS) {
|
||||
assertThat(contentResolver.getContentObservers(uri)).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onVolumeKeysShortcutSettingChanged_volumeKeyControllerUpdated() {
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.CREATED);
|
||||
|
||||
ShortcutUtils.optInValueToSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.HARDWARE, TARGET);
|
||||
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
TwoStatePreference preference = fragment.findPreference(
|
||||
mContext.getString(R.string.accessibility_shortcut_volume_keys_pref));
|
||||
assertThat(preference.isChecked()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onSoftwareShortcutSettingChanged_softwareControllersUpdated() {
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.CREATED);
|
||||
|
||||
ShortcutUtils.optInValueToSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.SOFTWARE, TARGET);
|
||||
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
|
||||
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
TwoStatePreference preference = fragment.findPreference(
|
||||
mContext.getString(R.string.accessibility_shortcut_gesture_pref));
|
||||
assertThat(preference.isChecked()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onSoftwareShortcutModeChanged_softwareControllersUpdated() {
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.CREATED);
|
||||
|
||||
ShortcutUtils.optInValueToSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.SOFTWARE, TARGET);
|
||||
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
|
||||
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
TwoStatePreference preference = fragment.findPreference(
|
||||
mContext.getString(R.string.accessibility_shortcut_gesture_pref));
|
||||
assertThat(preference.isChecked()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onTripleTapShortcutSettingChanged_tripleTapShortcutControllerUpdated() {
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.CREATED);
|
||||
|
||||
Settings.Secure.putInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
|
||||
AccessibilityUtil.State.ON);
|
||||
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
|
||||
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
TwoStatePreference preference = fragment.findPreference(
|
||||
mContext.getString(R.string.accessibility_shortcut_triple_tap_pref));
|
||||
assertThat(preference.isChecked()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onTwoFingersShortcutSettingChanged_twoFingersDoubleTapShortcutControllerUpdated() {
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.CREATED);
|
||||
|
||||
Settings.Secure.putInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED,
|
||||
AccessibilityUtil.State.ON);
|
||||
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
|
||||
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
TwoStatePreference preference = fragment.findPreference(
|
||||
mContext.getString(
|
||||
R.string.accessibility_shortcut_two_fingers_double_tap_pref));
|
||||
assertThat(preference.isChecked()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fragmentResumed_enableTouchExploration_gestureShortcutOptionSummaryUpdated() {
|
||||
String expectedSummary = mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_gesture_talkback)
|
||||
+ "\n\n"
|
||||
+ mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_floating);
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.RESUMED);
|
||||
|
||||
ShadowAccessibilityManager am = shadowOf(
|
||||
mContext.getSystemService(AccessibilityManager.class));
|
||||
am.setTouchExplorationEnabled(true);
|
||||
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
Preference preference = fragment.findPreference(
|
||||
mContext.getString(R.string.accessibility_shortcut_gesture_pref));
|
||||
assertThat(preference.getSummary().toString()).isEqualTo(expectedSummary);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fragmentPaused_enableTouchExploration_gestureShortcutOptionSummaryNotUpdated() {
|
||||
String expectedSummary = mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_gesture)
|
||||
+ "\n\n"
|
||||
+ mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_floating);
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.RESUMED).moveToState(Lifecycle.State.STARTED);
|
||||
|
||||
ShadowAccessibilityManager am = shadowOf(
|
||||
mContext.getSystemService(AccessibilityManager.class));
|
||||
am.setTouchExplorationEnabled(true);
|
||||
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
Preference preference = fragment.findPreference(
|
||||
mContext.getString(R.string.accessibility_shortcut_gesture_pref));
|
||||
assertThat(preference.getSummary().toString()).isEqualTo(expectedSummary);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAdvancedPreferenceClicked_advancedShouldBecomeInvisible() {
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.RESUMED);
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
Preference advanced = fragment.findPreference(
|
||||
mContext.getString(R.string.accessibility_shortcuts_advanced_collapsed));
|
||||
assertThat(advanced.isVisible()).isTrue();
|
||||
|
||||
fragment.onPreferenceTreeClick(advanced);
|
||||
|
||||
assertThat(advanced.isVisible()).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fragmentRecreated_expanded_advancedRemainInvisible() {
|
||||
onAdvancedPreferenceClicked_advancedShouldBecomeInvisible();
|
||||
|
||||
mFragmentScenario.recreate();
|
||||
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
Preference advanced = fragment.findPreference(
|
||||
mContext.getString(R.string.accessibility_shortcuts_advanced_collapsed));
|
||||
assertThat(advanced.isVisible()).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fragmentRecreated_collapsed_advancedRemainVisible() {
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.RESUMED);
|
||||
|
||||
mFragmentScenario.recreate();
|
||||
|
||||
mFragmentScenario.onFragment(fragment -> {
|
||||
Preference advanced = fragment.findPreference(
|
||||
mContext.getString(R.string.accessibility_shortcuts_advanced_collapsed));
|
||||
assertThat(advanced.isVisible()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fragmentResumed_preferredShortcutsUpdated() {
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.RESUMED);
|
||||
// Move the fragment to the background
|
||||
mFragmentScenario.moveToState(Lifecycle.State.CREATED);
|
||||
assertThat(
|
||||
PreferredShortcuts.retrieveUserShortcutType(
|
||||
mContext, TARGET)
|
||||
).isEqualTo(ShortcutConstants.UserShortcutType.SOFTWARE);
|
||||
// Update the chosen shortcut type to Volume keys while the fragment is in the background
|
||||
ShortcutUtils.optInValueToSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.HARDWARE, TARGET);
|
||||
|
||||
mFragmentScenario.moveToState(Lifecycle.State.RESUMED);
|
||||
|
||||
assertThat(
|
||||
PreferredShortcuts.retrieveUserShortcutType(
|
||||
mContext, TARGET)
|
||||
).isEqualTo(ShortcutConstants.UserShortcutType.HARDWARE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onVolumeKeysShortcutSettingChanged_preferredShortcutsUpdated() {
|
||||
mFragmentScenario = createFragScenario(/* isInSuw= */ false);
|
||||
mFragmentScenario.moveToState(Lifecycle.State.CREATED);
|
||||
assertThat(
|
||||
PreferredShortcuts.retrieveUserShortcutType(
|
||||
mContext, TARGET)
|
||||
).isEqualTo(ShortcutConstants.UserShortcutType.SOFTWARE);
|
||||
|
||||
ShortcutUtils.optInValueToSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.HARDWARE, TARGET);
|
||||
|
||||
// Calls onFragment so that the change to Setting is notified to its observer
|
||||
mFragmentScenario.onFragment(fragment ->
|
||||
assertThat(
|
||||
PreferredShortcuts.retrieveUserShortcutType(
|
||||
mContext, TARGET)
|
||||
).isEqualTo(ShortcutConstants.UserShortcutType.HARDWARE)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findTitles_withSingleTarget_hasNullSubtitle() {
|
||||
final String fake_label = "FAKE";
|
||||
List<AccessibilityTarget> accessibilityTargets = List.of(
|
||||
generateAccessibilityTargetMock(TARGET_FAKE_COMPONENT, fake_label));
|
||||
|
||||
Pair<String, String> titles = EditShortcutsPreferenceFragment
|
||||
.getTitlesFromAccessibilityTargetList(
|
||||
Set.of(TARGET_FAKE_COMPONENT.flattenToString()),
|
||||
accessibilityTargets, mActivity.getResources()
|
||||
);
|
||||
|
||||
assertThat(titles.first).isNotNull();
|
||||
assertThat(titles.first).contains(fake_label);
|
||||
assertThat(titles.second).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findTitles_withMoreTargets_hasSubtitle() {
|
||||
final String fake_label = "FAKE";
|
||||
final String magnification_label = "MAGNIFICATION";
|
||||
List<AccessibilityTarget> accessibilityTargets = List.of(
|
||||
generateAccessibilityTargetMock(TARGET_FAKE_COMPONENT, fake_label),
|
||||
generateAccessibilityTargetMock(MAGNIFICATION_COMPONENT_NAME, magnification_label));
|
||||
|
||||
Pair<String, String> titles = EditShortcutsPreferenceFragment
|
||||
.getTitlesFromAccessibilityTargetList(
|
||||
Set.of(TARGET_FAKE_COMPONENT.flattenToString(),
|
||||
MAGNIFICATION_COMPONENT_NAME.flattenToString()),
|
||||
accessibilityTargets, mActivity.getResources()
|
||||
);
|
||||
|
||||
assertThat(titles.first).isNotNull();
|
||||
assertThat(titles.second).isNotNull();
|
||||
assertThat(titles.second).contains(fake_label);
|
||||
assertThat(titles.second).contains(magnification_label);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findTitles_targetMissing_labelNotInTitles() {
|
||||
final String fake_label = "FAKE";
|
||||
List<AccessibilityTarget> accessibilityTargets = List.of(
|
||||
generateAccessibilityTargetMock(TARGET_FAKE_COMPONENT, fake_label));
|
||||
|
||||
assertThrows(IllegalStateException.class,
|
||||
() -> EditShortcutsPreferenceFragment
|
||||
.getTitlesFromAccessibilityTargetList(
|
||||
Set.of(MAGNIFICATION_COMPONENT_NAME.flattenToString()),
|
||||
accessibilityTargets, mActivity.getResources()
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void assertLaunchSubSettingWithCurrentTargetComponents(
|
||||
String componentName, boolean isInSuw) {
|
||||
Intent intent = shadowOf(mActivity.getApplication()).getNextStartedActivity();
|
||||
|
||||
assertThat(intent).isNotNull();
|
||||
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
|
||||
assertThat(intent.getComponent()).isEqualTo(
|
||||
new ComponentName(mActivity, SubSettings.class));
|
||||
assertThat(intent.getExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
|
||||
.isEqualTo(EditShortcutsPreferenceFragment.class.getName());
|
||||
assertThat(intent.getExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE))
|
||||
.isEqualTo(SCREEN_TITLE.toString());
|
||||
assertThat(intent.getExtra(
|
||||
MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY)).isEqualTo(METRICS_CATEGORY);
|
||||
Bundle args = (Bundle) intent.getExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS);
|
||||
assertThat(args).isNotNull();
|
||||
assertThat(Arrays.stream(args.getStringArray(
|
||||
EditShortcutsPreferenceFragment.ARG_KEY_SHORTCUT_TARGETS)).toList())
|
||||
.containsExactly(componentName);
|
||||
assertThat(WizardManagerHelper.isAnySetupWizard(intent)).isEqualTo(isInSuw);
|
||||
}
|
||||
|
||||
private List<ShortcutOptionPreferenceController> getShortcutOptionPreferenceControllers(
|
||||
EditShortcutsPreferenceFragment fragment) {
|
||||
|
||||
Collection<List<AbstractPreferenceController>> controllers =
|
||||
ReflectionHelpers.callInstanceMethod(fragment, "getPreferenceControllers");
|
||||
List<ShortcutOptionPreferenceController> retControllers = new ArrayList<>();
|
||||
controllers.stream().flatMap(Collection::stream)
|
||||
.filter(controller -> controller instanceof ShortcutOptionPreferenceController)
|
||||
.forEach(controller ->
|
||||
retControllers.add((ShortcutOptionPreferenceController) controller));
|
||||
|
||||
return retControllers;
|
||||
}
|
||||
|
||||
private FragmentScenario<EditShortcutsPreferenceFragment> createFragScenario(boolean isInSuw) {
|
||||
Bundle args = new Bundle();
|
||||
args.putStringArray(
|
||||
EditShortcutsPreferenceFragment.ARG_KEY_SHORTCUT_TARGETS, new String[]{TARGET});
|
||||
FragmentScenario<EditShortcutsPreferenceFragment> scenario =
|
||||
FragmentScenario.launch(
|
||||
EditShortcutsPreferenceFragment.class, args,
|
||||
/* themeResId= */ 0, Lifecycle.State.INITIALIZED);
|
||||
scenario.onFragment(fragment -> {
|
||||
Intent intent = fragment.requireActivity().getIntent();
|
||||
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE, SCREEN_TITLE);
|
||||
fragment.requireActivity().setIntent(createSuwIntent(intent, isInSuw));
|
||||
// Since the fragment is attached before we have a chance
|
||||
// to modify the activity's intent; initialize controllers again
|
||||
fragment.initializePreferenceControllerArguments();
|
||||
});
|
||||
return scenario;
|
||||
}
|
||||
|
||||
private Intent createSuwIntent(Intent intent, boolean isInSuw) {
|
||||
|
||||
if (intent == null) {
|
||||
intent = new Intent();
|
||||
}
|
||||
intent.putExtra(EXTRA_IS_SETUP_FLOW, isInSuw);
|
||||
intent.putExtra(EXTRA_IS_FIRST_RUN, isInSuw);
|
||||
intent.putExtra(EXTRA_IS_PRE_DEFERRED_SETUP, isInSuw);
|
||||
intent.putExtra(EXTRA_IS_DEFERRED_SETUP, isInSuw);
|
||||
return intent;
|
||||
}
|
||||
|
||||
private AccessibilityTarget generateAccessibilityTargetMock(
|
||||
ComponentName componentName, String label) {
|
||||
AccessibilityTarget target = mock(AccessibilityTarget.class);
|
||||
when(target.getComponentName()).thenReturn(componentName);
|
||||
when(target.getId()).thenReturn(componentName.flattenToString());
|
||||
when(target.getLabel()).thenReturn(label);
|
||||
return target;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link FloatingButtonShortcutOptionController}
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class FloatingButtonShortcutOptionControllerTest {
|
||||
private static final String PREF_KEY = "prefKey";
|
||||
private static final String TARGET =
|
||||
new ComponentName("FakePackage", "FakeClass").flattenToString();
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private FloatingButtonShortcutOptionController mController;
|
||||
private ShortcutOptionPreference mShortcutOptionPreference;
|
||||
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mController = new FloatingButtonShortcutOptionController(
|
||||
mContext, PREF_KEY);
|
||||
mController.setShortcutTargets(Set.of(TARGET));
|
||||
mShortcutOptionPreference = new ShortcutOptionPreference(mContext);
|
||||
mShortcutOptionPreference.setKey(PREF_KEY);
|
||||
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
|
||||
mPreferenceScreen.addPreference(mShortcutOptionPreference);
|
||||
setFloatingButtonEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_verifyTitle() {
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
|
||||
assertThat(mShortcutOptionPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.accessibility_shortcut_edit_dialog_title_software));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_inSuw_verifySummaryEmpty() {
|
||||
mController.setInSetupWizard(true);
|
||||
|
||||
assertThat(TextUtils.isEmpty(mController.getSummary())).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_notInSuw_verifySummary() {
|
||||
mController.setInSetupWizard(false);
|
||||
|
||||
assertThat(mController.getSummary().toString()).isEqualTo(
|
||||
mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_floating));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_floatingMenuEnabled_returnTrue() {
|
||||
setFloatingButtonEnabled(true);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_floatingMenuDisabled_returnFalse() {
|
||||
setFloatingButtonEnabled(false);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
private void setFloatingButtonEnabled(boolean enable) {
|
||||
int mode = enable
|
||||
? ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU : ACCESSIBILITY_BUTTON_MODE_GESTURE;
|
||||
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, mode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.AccessibilityTestUtils;
|
||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link GestureShortcutOptionController}
|
||||
*/
|
||||
@Config(shadows = SettingsShadowResources.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class GestureShortcutOptionControllerTest {
|
||||
private static final String PREF_KEY = "prefKey";
|
||||
private static final String TARGET =
|
||||
new ComponentName("FakePackage", "FakeClass").flattenToString();
|
||||
private final Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
private GestureShortcutOptionController mController;
|
||||
private ShortcutOptionPreference mShortcutOptionPreference;
|
||||
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mController = new GestureShortcutOptionController(
|
||||
mContext, PREF_KEY);
|
||||
mController.setShortcutTargets(Set.of(TARGET));
|
||||
mShortcutOptionPreference = new ShortcutOptionPreference(mContext);
|
||||
mShortcutOptionPreference.setKey(PREF_KEY);
|
||||
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
|
||||
mPreferenceScreen.addPreference(mShortcutOptionPreference);
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false);
|
||||
enableTouchExploration(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_verifyTitle() {
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
|
||||
assertThat(mShortcutOptionPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_title_software_by_gesture));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_touchExplorationDisabled_verifySummary() {
|
||||
enableTouchExploration(false);
|
||||
String expected = mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_gesture)
|
||||
+ "\n\n"
|
||||
+ mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_floating);
|
||||
|
||||
assertThat(mController.getSummary().toString()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_touchExplorationEnabled_verifySummary() {
|
||||
enableTouchExploration(true);
|
||||
String expected = mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_gesture_talkback)
|
||||
+ "\n\n"
|
||||
+ mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_floating);
|
||||
|
||||
assertThat(mController.getSummary().toString()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_inSuw_returnFalse() {
|
||||
mController.setInSetupWizard(true);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_notInSuwUseGestureNavSystemUseFab_returnFalse() {
|
||||
mController.setInSetupWizard(false);
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ true);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_notInSuwUseGestureNavSystemNotUseFab_returnTrue() {
|
||||
mController.setInSetupWizard(false);
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_notInSuwUseButtonNavSystemUseFab_returnFalse() {
|
||||
mController.setInSetupWizard(false);
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ true);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_notInSuwUseButtonNavSystemNotUseFab_returnFalse() {
|
||||
mController.setInSetupWizard(false);
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ false);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
private void enableTouchExploration(boolean enable) {
|
||||
AccessibilityManager am = mock(AccessibilityManager.class);
|
||||
when(mContext.getSystemService(AccessibilityManager.class)).thenReturn(am);
|
||||
when(am.isTouchExplorationEnabled()).thenReturn(enable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.AccessibilityTestUtils;
|
||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link NavButtonShortcutOptionController}
|
||||
*/
|
||||
@Config(shadows = SettingsShadowResources.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class NavButtonShortcutOptionControllerTest {
|
||||
private static final String PREF_KEY = "prefKey";
|
||||
private static final String TARGET =
|
||||
new ComponentName("FakePackage", "FakeClass").flattenToString();
|
||||
private final Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
private NavButtonShortcutOptionController mController;
|
||||
private ShortcutOptionPreference mShortcutOptionPreference;
|
||||
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mController = new NavButtonShortcutOptionController(
|
||||
mContext, PREF_KEY);
|
||||
mController.setShortcutTargets(Set.of(TARGET));
|
||||
mShortcutOptionPreference = new ShortcutOptionPreference(mContext);
|
||||
mShortcutOptionPreference.setKey(PREF_KEY);
|
||||
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
|
||||
mPreferenceScreen.addPreference(mShortcutOptionPreference);
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_verifyTitle() {
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
|
||||
assertThat(mShortcutOptionPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_title_software));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_inSuw_verifySummary() {
|
||||
mController.setInSetupWizard(true);
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
|
||||
assertThat(mShortcutOptionPreference.getSummary().toString()).isEqualTo(
|
||||
mContext.getString(R.string.accessibility_shortcut_edit_dialog_summary_software));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_notInSuw_verifySummary() {
|
||||
mController.setInSetupWizard(false);
|
||||
String expected = mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software)
|
||||
+ "\n\n"
|
||||
+ mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_floating);
|
||||
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
|
||||
assertThat(mShortcutOptionPreference.getSummary().toString()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_useGestureNavSystemUseFab_returnFalse() {
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ true);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_useGestureNavSystemNotUseFab_returnFalse() {
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_useButtonNavSystemUseFab_returnFalse() {
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ true);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_useButtonNavSystemNotUseFab_returnTrue() {
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ false);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mockito;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link ShortcutOptionPreferenceController}
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ShortcutOptionPreferenceControllerTest {
|
||||
|
||||
private static final String PREF_KEY = "prefKey";
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private ShortcutOptionPreference mShortcutOptionPreference;
|
||||
private ShortcutOptionPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mShortcutOptionPreference = spy(new ShortcutOptionPreference(mContext));
|
||||
mShortcutOptionPreference.setKey(PREF_KEY);
|
||||
mController = spy(new ShortcutOptionPreferenceController(mContext, PREF_KEY) {
|
||||
@Override
|
||||
protected boolean isShortcutAvailable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isChecked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void enableShortcutForTargets(boolean enable) {
|
||||
// do nothing
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_shortcutControllerIsChecked_shouldSetPreferenceChecked() {
|
||||
when(mController.isChecked()).thenReturn(true);
|
||||
|
||||
mController.updateState(mShortcutOptionPreference);
|
||||
|
||||
assertThat(mShortcutOptionPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_shortcutControllerIsNotChecked_shouldSetPreferenceUnchecked() {
|
||||
when(mController.isChecked()).thenReturn(false);
|
||||
|
||||
mController.updateState(mShortcutOptionPreference);
|
||||
|
||||
assertThat(mShortcutOptionPreference.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_shortcutAvailable_returnAvailableUnsearchable() {
|
||||
when(mController.isShortcutAvailable()).thenReturn(true);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_shortcutUnavailable_returnConditionallyUnavailable() {
|
||||
when(mController.isShortcutAvailable()).thenReturn(false);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChanged_callEnableShortcutForTargets() {
|
||||
mController.onPreferenceChange(mShortcutOptionPreference, true);
|
||||
mController.onPreferenceChange(mShortcutOptionPreference, false);
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(mController);
|
||||
inOrder.verify(mController).enableShortcutForTargets(true);
|
||||
inOrder.verify(mController).enableShortcutForTargets(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getShortcutTargets() {
|
||||
Set<String> targets = Set.of("target1", "target2");
|
||||
mController.setShortcutTargets(targets);
|
||||
|
||||
assertThat(mController.getShortcutTargets())
|
||||
.containsExactlyElementsIn(targets);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isInSetupWizard() {
|
||||
mController.setInSetupWizard(true);
|
||||
|
||||
assertThat(mController.isInSetupWizard()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/**
|
||||
* Test for {@link ShortcutOptionPreferenceTest}
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ShortcutOptionPreferenceTest {
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private ShortcutOptionPreference mShortcutOptionPreference;
|
||||
private PreferenceViewHolder mViewHolder;
|
||||
private ImageView mImageView;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mShortcutOptionPreference = new ShortcutOptionPreference(mContext);
|
||||
int layoutId = mShortcutOptionPreference.getLayoutResource();
|
||||
View itemView = LayoutInflater.from(mContext).inflate(layoutId, /* root= */null);
|
||||
mViewHolder = PreferenceViewHolder.createInstanceForTests(itemView);
|
||||
mImageView = (ImageView) mViewHolder.findViewById(R.id.image);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindViewHolder_imageResNotSet_shouldHideImageView() {
|
||||
mShortcutOptionPreference.onBindViewHolder(mViewHolder);
|
||||
|
||||
assertThat(mImageView.getVisibility()).isEqualTo(View.GONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindViewHolder_imageResIdSet_shouldShowImageView() {
|
||||
mShortcutOptionPreference.setIntroImageResId(R.drawable.a11y_shortcut_type_hardware);
|
||||
|
||||
mShortcutOptionPreference.onBindViewHolder(mViewHolder);
|
||||
|
||||
assertThat(mImageView.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindViewHolder_imageRawResIdSet_shouldShowImageView() {
|
||||
mShortcutOptionPreference.setIntroImageRawResId(
|
||||
com.android.settings.R.raw.accessibility_color_inversion_banner);
|
||||
|
||||
mShortcutOptionPreference.onBindViewHolder(mViewHolder);
|
||||
|
||||
assertThat(mImageView.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindViewHolder_shouldUpdateSummaryTextLineHeight() {
|
||||
assertThat(mShortcutOptionPreference.getSummaryTextLineHeight()).isEqualTo(0);
|
||||
|
||||
mShortcutOptionPreference.onBindViewHolder(mViewHolder);
|
||||
|
||||
assertThat(mShortcutOptionPreference.getSummaryTextLineHeight()).isNotEqualTo(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.android.internal.accessibility.common.ShortcutConstants.SERVICES_SEPARATOR;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.app.Application;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.internal.accessibility.common.ShortcutConstants;
|
||||
import com.android.internal.accessibility.util.ShortcutUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.accessibility.AccessibilityButtonFragment;
|
||||
import com.android.settings.accessibility.FloatingMenuSizePreferenceController;
|
||||
import com.android.settings.utils.AnnotationSpan;
|
||||
import com.android.settingslib.accessibility.AccessibilityUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.Shadows;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link SoftwareShortcutOptionPreferenceController}
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class SoftwareShortcutOptionPreferenceControllerTest {
|
||||
private static final String PREF_KEY = "prefKey";
|
||||
private static final String TARGET_MAGNIFICATION =
|
||||
"com.android.server.accessibility.MagnificationController";
|
||||
private static final ComponentName TARGET_ALWAYS_ON_A11Y_SERVICE =
|
||||
new ComponentName("FakePackage", "AlwaysOnA11yService");
|
||||
private static final ComponentName TARGET_STANDARD_A11Y_SERVICE =
|
||||
new ComponentName("FakePackage", "StandardA11yService");
|
||||
private static final String SOFTWARE_SHORTCUT_SETTING_NAME =
|
||||
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
|
||||
|
||||
private Context mContext;
|
||||
private TestSoftwareShortcutOptionPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = spy(Robolectric.buildActivity(FragmentActivity.class).get());
|
||||
|
||||
AccessibilityServiceInfo mAlwaysOnServiceInfo = createAccessibilityServiceInfo(
|
||||
TARGET_ALWAYS_ON_A11Y_SERVICE, /* isAlwaysOnService= */ true);
|
||||
AccessibilityServiceInfo mStandardServiceInfo = createAccessibilityServiceInfo(
|
||||
TARGET_STANDARD_A11Y_SERVICE, /* isAlwaysOnService= */ false);
|
||||
AccessibilityManager am = mock(AccessibilityManager.class);
|
||||
when(mContext.getSystemService(Context.ACCESSIBILITY_SERVICE)).thenReturn(am);
|
||||
when(am.getInstalledAccessibilityServiceList()).thenReturn(
|
||||
List.of(mAlwaysOnServiceInfo, mStandardServiceInfo));
|
||||
|
||||
mController = new TestSoftwareShortcutOptionPreferenceController(mContext, PREF_KEY);
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_allTargetsHasShortcutConfigured_returnTrue() {
|
||||
Settings.Secure.putString(
|
||||
mContext.getContentResolver(), SOFTWARE_SHORTCUT_SETTING_NAME,
|
||||
String.join(String.valueOf(SERVICES_SEPARATOR),
|
||||
TARGET_MAGNIFICATION,
|
||||
TARGET_STANDARD_A11Y_SERVICE.flattenToString(),
|
||||
TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString())
|
||||
);
|
||||
mController.setShortcutTargets(
|
||||
Set.of(TARGET_MAGNIFICATION,
|
||||
TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString(),
|
||||
TARGET_STANDARD_A11Y_SERVICE.flattenToString()));
|
||||
|
||||
assertThat(mController.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_someTargetsHasShortcutConfigured_returnFalse() {
|
||||
Settings.Secure.putString(
|
||||
mContext.getContentResolver(), SOFTWARE_SHORTCUT_SETTING_NAME,
|
||||
String.join(String.valueOf(SERVICES_SEPARATOR),
|
||||
TARGET_MAGNIFICATION,
|
||||
TARGET_STANDARD_A11Y_SERVICE.flattenToString())
|
||||
);
|
||||
mController.setShortcutTargets(
|
||||
Set.of(TARGET_MAGNIFICATION,
|
||||
TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString(),
|
||||
TARGET_STANDARD_A11Y_SERVICE.flattenToString()));
|
||||
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_noTargetsHasShortcutConfigured_returnFalse() {
|
||||
Settings.Secure.putString(
|
||||
mContext.getContentResolver(), SOFTWARE_SHORTCUT_SETTING_NAME, "");
|
||||
mController.setShortcutTargets(
|
||||
Set.of(TARGET_MAGNIFICATION,
|
||||
TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString(),
|
||||
TARGET_STANDARD_A11Y_SERVICE.flattenToString()));
|
||||
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCustomizedAccessibilityButtonLink_verifyText() {
|
||||
String expected =
|
||||
mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_floating);
|
||||
|
||||
CharSequence spannable = mController.getCustomizeAccessibilityButtonLink();
|
||||
|
||||
assertThat(spannable.toString()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCustomizedAccessibilityButtonLink_verifyClickAction() {
|
||||
String expected =
|
||||
mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_floating);
|
||||
|
||||
CharSequence spannable = mController.getCustomizeAccessibilityButtonLink();
|
||||
|
||||
assertThat(spannable).isInstanceOf(SpannableStringBuilder.class);
|
||||
AnnotationSpan[] spans = ((SpannableStringBuilder) spannable).getSpans(
|
||||
0, expected.length(), AnnotationSpan.class);
|
||||
spans[0].onClick(new View(mContext));
|
||||
assertLaunchSettingsPage(AccessibilityButtonFragment.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_enableShortcut_shortcutTurnedOn() {
|
||||
String target = TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString();
|
||||
mController.setShortcutTargets(Set.of(target));
|
||||
assertThat(ShortcutUtils.isComponentIdExistingInSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.SOFTWARE, target
|
||||
)).isFalse();
|
||||
|
||||
mController.enableShortcutForTargets(true);
|
||||
|
||||
assertThat(ShortcutUtils.isComponentIdExistingInSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.SOFTWARE, target
|
||||
)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_disableShortcut_shortcutTurnedOff() {
|
||||
String target = TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString();
|
||||
ShortcutUtils.optInValueToSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.SOFTWARE, target);
|
||||
assertThat(ShortcutUtils.isComponentIdExistingInSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.SOFTWARE, target
|
||||
)).isTrue();
|
||||
mController.setShortcutTargets(Set.of(target));
|
||||
|
||||
mController.enableShortcutForTargets(false);
|
||||
|
||||
assertThat(ShortcutUtils.isComponentIdExistingInSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.SOFTWARE, target
|
||||
)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_enableShortcutWithMagnification_menuSizeIncreased() {
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
|
||||
mController.enableShortcutForTargets(true);
|
||||
|
||||
assertThat(
|
||||
Settings.Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
|
||||
FloatingMenuSizePreferenceController.Size.UNKNOWN))
|
||||
.isEqualTo(FloatingMenuSizePreferenceController.Size.LARGE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_enableShortcutWithMagnification_userConfigureSmallMenuSize_menuSizeNotChanged() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
|
||||
FloatingMenuSizePreferenceController.Size.SMALL);
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
|
||||
mController.enableShortcutForTargets(true);
|
||||
|
||||
assertThat(
|
||||
Settings.Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
|
||||
FloatingMenuSizePreferenceController.Size.UNKNOWN))
|
||||
.isEqualTo(FloatingMenuSizePreferenceController.Size.SMALL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_enableAlwaysOnServiceShortcut_turnsOnAlwaysOnService() {
|
||||
mController.setShortcutTargets(
|
||||
Set.of(TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString()));
|
||||
|
||||
mController.enableShortcutForTargets(true);
|
||||
|
||||
assertThat(AccessibilityUtils.getEnabledServicesFromSettings(mContext))
|
||||
.contains(TARGET_ALWAYS_ON_A11Y_SERVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_disableAlwaysOnServiceShortcut_turnsOffAlwaysOnService() {
|
||||
mController.setShortcutTargets(
|
||||
Set.of(TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString()));
|
||||
|
||||
mController.enableShortcutForTargets(false);
|
||||
|
||||
assertThat(AccessibilityUtils.getEnabledServicesFromSettings(mContext))
|
||||
.doesNotContain(TARGET_ALWAYS_ON_A11Y_SERVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_enableStandardServiceShortcut_wontTurnOnService() {
|
||||
mController.setShortcutTargets(
|
||||
Set.of(TARGET_STANDARD_A11Y_SERVICE.flattenToString()));
|
||||
|
||||
mController.enableShortcutForTargets(true);
|
||||
|
||||
assertThat(AccessibilityUtils.getEnabledServicesFromSettings(mContext))
|
||||
.doesNotContain(TARGET_STANDARD_A11Y_SERVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_disableStandardServiceShortcutWithServiceOn_wontTurnOffService() {
|
||||
mController.setShortcutTargets(
|
||||
Set.of(TARGET_STANDARD_A11Y_SERVICE.flattenToString()));
|
||||
AccessibilityUtils.setAccessibilityServiceState(
|
||||
mContext, TARGET_STANDARD_A11Y_SERVICE, /* enabled= */ true);
|
||||
|
||||
mController.enableShortcutForTargets(false);
|
||||
|
||||
assertThat(AccessibilityUtils.getEnabledServicesFromSettings(mContext))
|
||||
.contains(TARGET_STANDARD_A11Y_SERVICE);
|
||||
}
|
||||
|
||||
private void assertLaunchSettingsPage(String page) {
|
||||
ContextWrapper applicationContext = (Application) mContext.getApplicationContext();
|
||||
final Intent intent = Shadows.shadowOf(applicationContext).getNextStartedActivity();
|
||||
assertThat(intent).isNotNull();
|
||||
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
|
||||
assertThat(intent.getComponent()).isEqualTo(
|
||||
new ComponentName(applicationContext, SubSettings.class));
|
||||
assertThat(intent.getExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo(page);
|
||||
}
|
||||
|
||||
private AccessibilityServiceInfo createAccessibilityServiceInfo(
|
||||
ComponentName componentName, boolean isAlwaysOnService) {
|
||||
final ApplicationInfo applicationInfo = new ApplicationInfo();
|
||||
applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
|
||||
final ServiceInfo serviceInfo = new ServiceInfo();
|
||||
applicationInfo.packageName = componentName.getPackageName();
|
||||
serviceInfo.packageName = componentName.getPackageName();
|
||||
serviceInfo.name = componentName.getClassName();
|
||||
serviceInfo.applicationInfo = applicationInfo;
|
||||
|
||||
final ResolveInfo resolveInfo = new ResolveInfo();
|
||||
resolveInfo.serviceInfo = serviceInfo;
|
||||
try {
|
||||
final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo,
|
||||
mContext);
|
||||
info.setComponentName(componentName);
|
||||
if (isAlwaysOnService) {
|
||||
info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
|
||||
}
|
||||
return info;
|
||||
} catch (XmlPullParserException | IOException e) {
|
||||
// Do nothing
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class TestSoftwareShortcutOptionPreferenceController
|
||||
extends SoftwareShortcutOptionPreferenceController {
|
||||
|
||||
TestSoftwareShortcutOptionPreferenceController(
|
||||
Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShortcutAvailable() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.icu.text.MessageFormat;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityUtil;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link TripleTapShortcutOptionController}
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class TripleTapShortcutOptionControllerTest {
|
||||
private static final String PREF_KEY = "prefKey";
|
||||
private static final String TARGET_MAGNIFICATION =
|
||||
"com.android.server.accessibility.MagnificationController";
|
||||
private static final String TARGET_FAKE =
|
||||
new ComponentName("FakePackage", "FakeClass").flattenToString();
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private TripleTapShortcutOptionController mController;
|
||||
private ShortcutOptionPreference mShortcutOptionPreference;
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mController = new TripleTapShortcutOptionController(mContext, PREF_KEY);
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
mShortcutOptionPreference = new ShortcutOptionPreference(mContext);
|
||||
mShortcutOptionPreference.setKey(PREF_KEY);
|
||||
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
|
||||
mPreferenceScreen.addPreference(mShortcutOptionPreference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_verifyScreenTestSet() {
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
|
||||
assertThat(mShortcutOptionPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.accessibility_shortcut_edit_dialog_title_triple_tap));
|
||||
assertThat(mShortcutOptionPreference.getSummary().toString()).isEqualTo(
|
||||
MessageFormat.format(
|
||||
mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_triple_tap),
|
||||
3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_targetIsMagnificationAndIsExpanded_returnsAvailableUnsearchable() {
|
||||
mController.setExpanded(true);
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_targetIsMagnificationAndIsNotExpanded_returnsConditionallyUnavailable() {
|
||||
mController.setExpanded(false);
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_targetIsNotMagnificationAndIsNotExpanded_returnsConditionallyUnavailable() {
|
||||
mController.setExpanded(false);
|
||||
mController.setShortcutTargets(Set.of(TARGET_FAKE));
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_targetIsNotMagnificationAndIsExpanded_returnsConditionallyUnavailable() {
|
||||
mController.setExpanded(true);
|
||||
mController.setShortcutTargets(Set.of(TARGET_FAKE));
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setExpanded_expand_updateExpandedValue() {
|
||||
mController.setExpanded(true);
|
||||
|
||||
assertThat(mController.isExpanded()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setExpanded_collapse_updateExpandedValue() {
|
||||
mController.setExpanded(false);
|
||||
|
||||
assertThat(mController.isExpanded()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_multipleTargets_returnFalse() {
|
||||
mController.setShortcutTargets(Set.of(TARGET_FAKE, TARGET_MAGNIFICATION));
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_magnificationTargetOnly_returnTrue() {
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_nonMagnificationTarget_returnFalse() {
|
||||
mController.setShortcutTargets(Set.of(TARGET_FAKE));
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_tripleTapConfigured_returnTrue() {
|
||||
mController.enableShortcutForTargets(true);
|
||||
|
||||
assertThat(mController.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_tripleTapNotConfigured_returnFalse() {
|
||||
mController.enableShortcutForTargets(false);
|
||||
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_enableShortcut_settingUpdated() {
|
||||
mController.enableShortcutForTargets(true);
|
||||
|
||||
assertThat(
|
||||
Settings.Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
|
||||
AccessibilityUtil.State.OFF)
|
||||
).isEqualTo(AccessibilityUtil.State.ON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_disableShortcut_settingUpdated() {
|
||||
mController.enableShortcutForTargets(false);
|
||||
|
||||
assertThat(
|
||||
Settings.Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
|
||||
AccessibilityUtil.State.OFF)
|
||||
).isEqualTo(AccessibilityUtil.State.OFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.icu.text.MessageFormat;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.server.accessibility.Flags;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityUtil;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link TwoFingersDoubleTapShortcutOptionController}
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class TwoFingersDoubleTapShortcutOptionControllerTest {
|
||||
private static final String PREF_KEY = "prefKey";
|
||||
private static final String TARGET_MAGNIFICATION =
|
||||
"com.android.server.accessibility.MagnificationController";
|
||||
private static final String TARGET_FAKE =
|
||||
new ComponentName("FakePackage", "FakeClass").flattenToString();
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private TwoFingersDoubleTapShortcutOptionController mController;
|
||||
private ShortcutOptionPreference mShortcutOptionPreference;
|
||||
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mController = new TwoFingersDoubleTapShortcutOptionController(mContext, PREF_KEY);
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
mShortcutOptionPreference = new ShortcutOptionPreference(mContext);
|
||||
mShortcutOptionPreference.setKey(PREF_KEY);
|
||||
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
|
||||
mPreferenceScreen.addPreference(mShortcutOptionPreference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_verifyScreenTextSet() {
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
|
||||
assertThat(mShortcutOptionPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_title_two_finger_double_tap));
|
||||
assertThat(mShortcutOptionPreference.getSummary().toString()).isEqualTo(
|
||||
MessageFormat.format(mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_two_finger_double_tap),
|
||||
2));
|
||||
}
|
||||
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
|
||||
@Test
|
||||
public void isShortcutAvailable_featureFlagTurnedOff_returnFalse() {
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
|
||||
@Test
|
||||
public void isShortcutAvailable_multipleTargets_returnFalse() {
|
||||
mController.setShortcutTargets(Set.of(TARGET_FAKE, TARGET_MAGNIFICATION));
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
|
||||
@Test
|
||||
public void isShortcutAvailable_magnificationTargetOnly_returnTrue() {
|
||||
mController.setShortcutTargets(Set.of(TARGET_MAGNIFICATION));
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
|
||||
@Test
|
||||
public void isShortcutAvailable_nonMagnificationTarget_returnFalse() {
|
||||
mController.setShortcutTargets(Set.of(TARGET_FAKE));
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_twoFingersDoubleTapConfigured_returnTrue() {
|
||||
mController.enableShortcutForTargets(true);
|
||||
|
||||
assertThat(mController.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_twoFingersDoubleTapNotConfigured_returnFalse() {
|
||||
mController.enableShortcutForTargets(false);
|
||||
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_enableShortcut_settingUpdated() {
|
||||
mController.enableShortcutForTargets(true);
|
||||
|
||||
assertThat(
|
||||
Settings.Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED,
|
||||
AccessibilityUtil.State.OFF)
|
||||
).isEqualTo(AccessibilityUtil.State.ON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_disableShortcut_settingUpdated() {
|
||||
mController.enableShortcutForTargets(false);
|
||||
|
||||
assertThat(
|
||||
Settings.Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED,
|
||||
AccessibilityUtil.State.OFF)
|
||||
).isEqualTo(AccessibilityUtil.State.OFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.internal.accessibility.common.ShortcutConstants;
|
||||
import com.android.internal.accessibility.util.ShortcutUtils;
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link VolumeKeysShortcutOptionController}
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class VolumeKeysShortcutOptionControllerTest {
|
||||
|
||||
private static final String PREF_KEY = "prefKey";
|
||||
private static final String TARGET =
|
||||
new ComponentName("FakePackage", "FakeClass").flattenToString();
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private VolumeKeysShortcutOptionController mController;
|
||||
private ShortcutOptionPreference mShortcutOptionPreference;
|
||||
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mController = new VolumeKeysShortcutOptionController(
|
||||
mContext, PREF_KEY);
|
||||
mController.setShortcutTargets(Set.of(TARGET));
|
||||
mShortcutOptionPreference = new ShortcutOptionPreference(mContext);
|
||||
mShortcutOptionPreference.setKey(PREF_KEY);
|
||||
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
|
||||
mPreferenceScreen.addPreference(mShortcutOptionPreference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_verifyScreenTextSet() {
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
|
||||
assertThat(mShortcutOptionPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.accessibility_shortcut_edit_dialog_title_hardware));
|
||||
assertThat(mShortcutOptionPreference.getSummary().toString()).isEqualTo(
|
||||
mContext.getString(R.string.accessibility_shortcut_edit_dialog_summary_hardware));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_returnsTrue() {
|
||||
assertThat(mController.isShortcutAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_targetUseVolumeKeyShortcut_returnTrue() {
|
||||
ShortcutUtils.optInValueToSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.HARDWARE, TARGET);
|
||||
|
||||
assertThat(mController.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_targetNotUseVolumeKeyShortcut_returnFalse() {
|
||||
ShortcutUtils.optOutValueFromSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.HARDWARE, TARGET);
|
||||
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_enableVolumeKeysShortcut_shortcutSet() {
|
||||
mController.enableShortcutForTargets(true);
|
||||
|
||||
assertThat(
|
||||
ShortcutUtils.isComponentIdExistingInSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.HARDWARE, TARGET)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableShortcutForTargets_disableVolumeKeysShortcut_shortcutNotSet() {
|
||||
mController.enableShortcutForTargets(false);
|
||||
|
||||
assertThat(
|
||||
ShortcutUtils.isComponentIdExistingInSettings(
|
||||
mContext, ShortcutConstants.UserShortcutType.HARDWARE, TARGET)).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -254,25 +254,26 @@ public class AccountPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateRawDataToIndex_ManagedProfile_shouldNotUpdate() {
|
||||
public void updateRawDataToIndex_noManagedProfile_shouldContainAddAccount() {
|
||||
final List<SearchIndexableRaw> data = new ArrayList<>();
|
||||
when(mUserManager.isManagedProfile()).thenReturn(false);
|
||||
|
||||
mController.updateRawDataToIndex(data);
|
||||
|
||||
assertThat(data).hasSize(1);
|
||||
assertThat(data.get(0).key).isEqualTo("add_account");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void updateRawDataToIndex_ManagedProfile_shouldContainAddAccount() {
|
||||
final List<SearchIndexableRaw> data = new ArrayList<>();
|
||||
when(mUserManager.isManagedProfile()).thenReturn(true);
|
||||
|
||||
mController.updateRawDataToIndex(data);
|
||||
|
||||
assertThat(data).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateRawDataToIndex_DisabledUser_shouldNotUpdate() {
|
||||
final List<SearchIndexableRaw> data = new ArrayList<>();
|
||||
final List<UserInfo> infos = new ArrayList<>();
|
||||
infos.add(new UserInfo(1, "user 1", UserInfo.FLAG_DISABLED));
|
||||
when(mUserManager.isManagedProfile()).thenReturn(false);
|
||||
when(mUserManager.getProfiles(anyInt())).thenReturn(infos);
|
||||
mController.updateRawDataToIndex(data);
|
||||
|
||||
assertThat(data).isEmpty();
|
||||
assertThat(data).hasSize(1);
|
||||
assertThat(data.get(0).key).isEqualTo("add_account");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AuthenticatorDescription;
|
||||
import android.app.Activity;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
@@ -35,6 +36,7 @@ import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
@@ -44,33 +46,38 @@ import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class,
|
||||
ShadowRestrictedLockUtilsInternal.class})
|
||||
public class ChooseAccountPreferenceControllerTest {
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
private Context mContext;
|
||||
private ChooseAccountPreferenceController mController;
|
||||
private Activity mActivity;
|
||||
private PreferenceManager mPreferenceManager;
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
private ShadowAccountManager mAccountManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mController = spy(new ChooseAccountPreferenceController(mContext, "controller_key"));
|
||||
mActivity = Robolectric.setupActivity(FragmentActivity.class);
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
|
||||
mAccountManager = (ShadowAccountManager) Shadows.shadowOf(AccountManager.get(mContext));
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -108,7 +115,7 @@ public class ChooseAccountPreferenceControllerTest {
|
||||
final AuthenticatorDescription authDesc = new AuthenticatorDescription("com.acct1",
|
||||
"com.android.settings",
|
||||
R.string.header_add_an_account, 0, 0, 0, false);
|
||||
ShadowAccountManager.addAuthenticator(authDesc);
|
||||
mAccountManager.addAuthenticator(authDesc);
|
||||
|
||||
final SyncAdapterType[] syncAdapters = {new SyncAdapterType("authority" /* authority */,
|
||||
"com.acct1" /* accountType */, false /* userVisible */,
|
||||
@@ -133,7 +140,7 @@ public class ChooseAccountPreferenceControllerTest {
|
||||
final AuthenticatorDescription authDesc = new AuthenticatorDescription("com.acct1",
|
||||
"com.android.settings",
|
||||
R.string.header_add_an_account, 0, 0, 0, false);
|
||||
ShadowAccountManager.addAuthenticator(authDesc);
|
||||
mAccountManager.addAuthenticator(authDesc);
|
||||
|
||||
final SyncAdapterType[] syncAdapters = {new SyncAdapterType("authority" /* authority */,
|
||||
"com.acct1" /* accountType */, false /* userVisible */,
|
||||
@@ -158,7 +165,7 @@ public class ChooseAccountPreferenceControllerTest {
|
||||
final AuthenticatorDescription authDesc = new AuthenticatorDescription("com.acct1",
|
||||
"com.android.settings",
|
||||
R.string.header_add_an_account, 0, 0, 0, false);
|
||||
ShadowAccountManager.addAuthenticator(authDesc);
|
||||
mAccountManager.addAuthenticator(authDesc);
|
||||
|
||||
final SyncAdapterType[] syncAdapters = {new SyncAdapterType("authority" /* authority */,
|
||||
"com.acct1" /* accountType */, false /* userVisible */,
|
||||
@@ -184,8 +191,8 @@ public class ChooseAccountPreferenceControllerTest {
|
||||
final AuthenticatorDescription authDesc2 = new AuthenticatorDescription("com.acct2",
|
||||
"com.android.settings",
|
||||
R.string.header_add_an_account, 0, 0, 0, false);
|
||||
ShadowAccountManager.addAuthenticator(authDesc);
|
||||
ShadowAccountManager.addAuthenticator(authDesc2);
|
||||
mAccountManager.addAuthenticator(authDesc);
|
||||
mAccountManager.addAuthenticator(authDesc2);
|
||||
|
||||
final SyncAdapterType[] syncAdapters = {new SyncAdapterType("authority" /* authority */,
|
||||
"com.acct1" /* accountType */, false /* userVisible */,
|
||||
|
||||
@@ -41,13 +41,12 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.ParameterizedRobolectricTestRunner;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@RunWith(ParameterizedRobolectricTestRunner.class)
|
||||
public class WorkModePreferenceControllerTest {
|
||||
|
||||
private static final String PREF_KEY = "work_mode";
|
||||
|
||||
@@ -38,13 +38,20 @@ import android.os.Build;
|
||||
import android.os.SystemConfigManager;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.webkit.Flags;
|
||||
|
||||
import com.android.settings.testutils.ApplicationTestUtils;
|
||||
import com.android.settings.webview.WebViewUpdateServiceWrapper;
|
||||
import com.android.settingslib.testutils.shadow.ShadowDefaultDialerManager;
|
||||
import com.android.settingslib.testutils.shadow.ShadowSmsApplication;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -68,6 +75,9 @@ import java.util.Set;
|
||||
@LooperMode(LooperMode.Mode.LEGACY)
|
||||
public final class ApplicationFeatureProviderImplTest {
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
private final int MAIN_USER_ID = 0;
|
||||
private final int MANAGED_PROFILE_ID = 10;
|
||||
|
||||
@@ -96,6 +106,8 @@ public final class ApplicationFeatureProviderImplTest {
|
||||
@Mock
|
||||
private LocationManager mLocationManager;
|
||||
@Mock
|
||||
private WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper;
|
||||
@Mock
|
||||
private SystemConfigManager mSystemConfigManager;
|
||||
|
||||
private ApplicationFeatureProvider mProvider;
|
||||
@@ -113,7 +125,7 @@ public final class ApplicationFeatureProviderImplTest {
|
||||
when(mContext.getSystemService(SystemConfigManager.class)).thenReturn(mSystemConfigManager);
|
||||
|
||||
mProvider = new ApplicationFeatureProviderImpl(mContext, mPackageManager,
|
||||
mPackageManagerService, mDevicePolicyManager);
|
||||
mPackageManagerService, mDevicePolicyManager, mWebViewUpdateServiceWrapper);
|
||||
}
|
||||
|
||||
private void verifyCalculateNumberOfPolicyInstalledApps(boolean async) {
|
||||
@@ -348,6 +360,26 @@ public final class ApplicationFeatureProviderImplTest {
|
||||
assertThat(allowlist).contains("com.android.settings.intelligence");
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_UPDATE_SERVICE_V2)
|
||||
public void getKeepEnabledPackages_shouldContainWebViewPackage() {
|
||||
final String testWebViewPackageName = "com.android.webview";
|
||||
when(mWebViewUpdateServiceWrapper.getDefaultWebViewPackageName())
|
||||
.thenReturn(testWebViewPackageName);
|
||||
final Set<String> allowlist = mProvider.getKeepEnabledPackages();
|
||||
assertThat(allowlist).contains(testWebViewPackageName);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_UPDATE_SERVICE_V2)
|
||||
public void getKeepEnabledPackages_shouldNotContainWebViewPackageIfFlagDisabled() {
|
||||
final String testWebViewPackageName = "com.android.webview";
|
||||
when(mWebViewUpdateServiceWrapper.getDefaultWebViewPackageName())
|
||||
.thenReturn(testWebViewPackageName);
|
||||
final Set<String> allowlist = mProvider.getKeepEnabledPackages();
|
||||
assertThat(allowlist).doesNotContain(testWebViewPackageName);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class})
|
||||
public void getKeepEnabledPackages_shouldContainPackageInstaller() {
|
||||
|
||||
@@ -41,8 +41,11 @@ import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
@@ -84,6 +87,9 @@ public final class InstalledAppCounterTest {
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
private int mInstalledAppCount = -1;
|
||||
private ApplicationInfo mApp1;
|
||||
private ApplicationInfo mApp2;
|
||||
@@ -189,11 +195,13 @@ public final class InstalledAppCounterTest {
|
||||
mPackageManager, mApp6)).isFalse();
|
||||
}
|
||||
|
||||
@Ignore("b/313578776")
|
||||
@Test
|
||||
public void testCountInstalledAppsAcrossAllUsersSync() {
|
||||
testCountInstalledAppsAcrossAllUsers(false /* async */);
|
||||
}
|
||||
|
||||
@Ignore("b/313578776")
|
||||
@Test
|
||||
public void testCountInstalledAppsAcrossAllUsersAsync() {
|
||||
testCountInstalledAppsAcrossAllUsers(true /* async */);
|
||||
@@ -215,6 +223,7 @@ public final class InstalledAppCounterTest {
|
||||
eq(MAIN_USER_ID))).thenReturn(Arrays.asList(mApp2));
|
||||
|
||||
mFakeFeatureFlags.setFlag(Flags.FLAG_ARCHIVING, false);
|
||||
mSetFlagsRule.disableFlags(com.android.settings.flags.Flags.FLAG_APP_ARCHIVING);
|
||||
// Count the number of all apps installed, irrespective of install reason.
|
||||
count(InstalledAppCounter.IGNORE_INSTALL_REASON, mFakeFeatureFlags);
|
||||
assertThat(mInstalledAppCount).isEqualTo(1);
|
||||
|
||||
@@ -16,12 +16,21 @@
|
||||
|
||||
package com.android.settings.applications.appcompat;
|
||||
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET;
|
||||
|
||||
import static com.android.settings.applications.AppInfoBase.ARG_PACKAGE_NAME;
|
||||
import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_3_2;
|
||||
import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_DEFAULT;
|
||||
import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_FULLSCREEN;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -30,15 +39,20 @@ import static org.mockito.Mockito.when;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import androidx.fragment.app.testing.EmptyFragmentActivity;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowActivityManager;
|
||||
import com.android.settings.testutils.shadow.ShadowFragment;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InOrder;
|
||||
@@ -51,9 +65,13 @@ import org.robolectric.annotation.Config;
|
||||
* To run test: atest SettingsRoboTests:UserAspectRatioDetailsTest
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowActivityManager.class})
|
||||
@Config(shadows = {ShadowActivityManager.class, ShadowFragment.class})
|
||||
public class UserAspectRatioDetailsTest {
|
||||
|
||||
@Rule
|
||||
public ActivityScenarioRule<EmptyFragmentActivity> rule =
|
||||
new ActivityScenarioRule<>(EmptyFragmentActivity.class);
|
||||
|
||||
@Mock
|
||||
private UserAspectRatioManager mUserAspectRatioManager;
|
||||
@Mock
|
||||
@@ -72,6 +90,8 @@ public class UserAspectRatioDetailsTest {
|
||||
mFragment = spy(new UserAspectRatioDetails());
|
||||
when(mFragment.getContext()).thenReturn(mContext);
|
||||
when(mFragment.getAspectRatioManager()).thenReturn(mUserAspectRatioManager);
|
||||
when(mUserAspectRatioManager.isOverrideToFullscreenEnabled(anyString(), anyInt()))
|
||||
.thenReturn(false);
|
||||
ShadowActivityManager.setService(mAm);
|
||||
mRadioButtonPref = new RadioWithImagePreference(mContext);
|
||||
final FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
|
||||
@@ -80,6 +100,8 @@ public class UserAspectRatioDetailsTest {
|
||||
|
||||
@Test
|
||||
public void onRadioButtonClicked_prefChange_shouldStopActivity() throws RemoteException {
|
||||
doReturn(USER_MIN_ASPECT_RATIO_UNSET).when(mFragment)
|
||||
.getSelectedUserMinAspectRatio(anyString());
|
||||
// Default was already selected
|
||||
mRadioButtonPref.setKey(KEY_PREF_DEFAULT);
|
||||
mFragment.onRadioButtonClicked(mRadioButtonPref);
|
||||
@@ -92,6 +114,8 @@ public class UserAspectRatioDetailsTest {
|
||||
|
||||
@Test
|
||||
public void onRadioButtonClicked_prefChange_shouldSetAspectRatio() throws RemoteException {
|
||||
doReturn(USER_MIN_ASPECT_RATIO_UNSET).when(mFragment)
|
||||
.getSelectedUserMinAspectRatio(anyString());
|
||||
// Default was already selected
|
||||
mRadioButtonPref.setKey(KEY_PREF_DEFAULT);
|
||||
mFragment.onRadioButtonClicked(mRadioButtonPref);
|
||||
@@ -105,6 +129,8 @@ public class UserAspectRatioDetailsTest {
|
||||
|
||||
@Test
|
||||
public void onRadioButtonClicked_prefChange_logMetrics() throws NullPointerException {
|
||||
doReturn(USER_MIN_ASPECT_RATIO_UNSET).when(mFragment)
|
||||
.getSelectedUserMinAspectRatio(anyString());
|
||||
// Default was already selected
|
||||
mRadioButtonPref.setKey(KEY_PREF_DEFAULT);
|
||||
mFragment.onRadioButtonClicked(mRadioButtonPref);
|
||||
@@ -129,4 +155,47 @@ public class UserAspectRatioDetailsTest {
|
||||
any(),
|
||||
anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onButtonClicked_overrideEnabled_fullscreenPreselected()
|
||||
throws RemoteException {
|
||||
doReturn(true).when(mUserAspectRatioManager)
|
||||
.isOverrideToFullscreenEnabled(anyString(), anyInt());
|
||||
doReturn(USER_MIN_ASPECT_RATIO_UNSET).when(mUserAspectRatioManager)
|
||||
.getUserMinAspectRatioValue(anyString(), anyInt());
|
||||
doReturn(mRadioButtonPref).when(mFragment).findPreference(KEY_PREF_DEFAULT);
|
||||
doReturn(mRadioButtonPref).when(mFragment).findPreference(KEY_PREF_FULLSCREEN);
|
||||
doReturn(true).when(mUserAspectRatioManager)
|
||||
.hasAspectRatioOption(anyInt(), anyString());
|
||||
|
||||
rule.getScenario().onActivity(a -> doReturn(a).when(mFragment).getActivity());
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(ARG_PACKAGE_NAME, anyString());
|
||||
mFragment.setArguments(args);
|
||||
mFragment.onCreate(Bundle.EMPTY);
|
||||
|
||||
// Fullscreen should be pre-selected
|
||||
assertEquals(KEY_PREF_FULLSCREEN, mFragment.mSelectedKey);
|
||||
assertEquals(USER_MIN_ASPECT_RATIO_FULLSCREEN,
|
||||
mFragment.getSelectedUserMinAspectRatio(mFragment.mSelectedKey));
|
||||
|
||||
// Revert to app default, should be set to app default from unset
|
||||
mRadioButtonPref.setKey(KEY_PREF_DEFAULT);
|
||||
mFragment.onRadioButtonClicked(mRadioButtonPref);
|
||||
verify(mUserAspectRatioManager).setUserMinAspectRatio(
|
||||
any(), anyInt(), anyInt());
|
||||
assertEquals(USER_MIN_ASPECT_RATIO_APP_DEFAULT,
|
||||
mFragment.getSelectedUserMinAspectRatio(mFragment.mSelectedKey));
|
||||
assertEquals(KEY_PREF_DEFAULT, mFragment.mSelectedKey);
|
||||
|
||||
// Fullscreen override disabled, should be changed to unset from app default
|
||||
when(mUserAspectRatioManager.isOverrideToFullscreenEnabled(anyString(), anyInt()))
|
||||
.thenReturn(false);
|
||||
mFragment.mKeyToAspectRatioMap.clear();
|
||||
mFragment.onCreate(Bundle.EMPTY);
|
||||
|
||||
assertEquals(KEY_PREF_DEFAULT, mFragment.mSelectedKey);
|
||||
assertEquals(USER_MIN_ASPECT_RATIO_UNSET,
|
||||
mFragment.getSelectedUserMinAspectRatio(mFragment.mSelectedKey));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
@@ -38,15 +39,18 @@ import static org.mockito.Mockito.when;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.om.OverlayInfo;
|
||||
import android.content.om.OverlayManager;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.Flags;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.util.ArraySet;
|
||||
import android.view.View;
|
||||
|
||||
@@ -107,7 +111,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
@Mock
|
||||
private OverlayManager mOverlayManager;
|
||||
@Mock
|
||||
private PackageManager mPackageManger;
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private DevicePolicyManager mDpm;
|
||||
@Mock
|
||||
@@ -132,7 +136,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
doReturn(mDpm).when(mSettingsActivity).getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
doReturn(mUserManager).when(mSettingsActivity).getSystemService(Context.USER_SERVICE);
|
||||
doReturn(mPackageManger).when(mSettingsActivity).getPackageManager();
|
||||
doReturn(mPackageManager).when(mSettingsActivity).getPackageManager();
|
||||
doReturn(mAm).when(mSettingsActivity).getSystemService(Context.ACTIVITY_SERVICE);
|
||||
doReturn(mOverlayManager).when(mSettingsActivity).
|
||||
getSystemService(OverlayManager.class);
|
||||
@@ -184,7 +188,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
@Test
|
||||
public void retrieveAppEntry_hasAppEntry_notNull()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt());
|
||||
doReturn(mPackageInfo).when(mPackageManager).getPackageInfo(anyString(), anyInt());
|
||||
|
||||
mController.retrieveAppEntry();
|
||||
|
||||
@@ -195,7 +199,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
@Test
|
||||
public void retrieveAppEntry_noAppEntry_null() throws PackageManager.NameNotFoundException {
|
||||
doReturn(null).when(mState).getEntry(eq(PACKAGE_NAME), anyInt());
|
||||
doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt());
|
||||
doReturn(mPackageInfo).when(mPackageManager).getPackageInfo(anyString(), anyInt());
|
||||
|
||||
mController.retrieveAppEntry();
|
||||
|
||||
@@ -207,7 +211,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
public void retrieveAppEntry_throwException_null() throws
|
||||
PackageManager.NameNotFoundException {
|
||||
doReturn(mAppEntry).when(mState).getEntry(anyString(), anyInt());
|
||||
doThrow(new PackageManager.NameNotFoundException()).when(mPackageManger).getPackageInfo(
|
||||
doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getPackageInfo(
|
||||
anyString(), anyInt());
|
||||
|
||||
mController.retrieveAppEntry();
|
||||
@@ -225,7 +229,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void updateOpenButton_haveLaunchIntent_buttonShouldBeEnable() {
|
||||
doReturn(new Intent()).when(mPackageManger).getLaunchIntentForPackage(anyString());
|
||||
doReturn(new Intent()).when(mPackageManager).getLaunchIntentForPackage(anyString());
|
||||
|
||||
mController.updateOpenButton();
|
||||
|
||||
@@ -346,6 +350,35 @@ public class AppButtonsPreferenceControllerTest {
|
||||
verify(mButtonPrefs).setButton2Enabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_IMPROVE_HOME_APP_BEHAVIOR)
|
||||
public void updateUninstallButton_isNotSystemAndIsCurrentHomeAndHasOneHome_setButtonDisable() {
|
||||
doReturn(false).when(mController).isSystemPackage(any(), any(), any());
|
||||
doReturn(new ComponentName(PACKAGE_NAME, "cls")).when(mPackageManager).getHomeActivities(
|
||||
anyList());
|
||||
|
||||
mController.mHomePackages.add(PACKAGE_NAME);
|
||||
|
||||
mController.updateUninstallButton();
|
||||
|
||||
verify(mButtonPrefs).setButton2Enabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_IMPROVE_HOME_APP_BEHAVIOR)
|
||||
public void updateUninstallButton_isNotSystemAndIsCurrentHomeAndHasOtherHome_setButtonEnable() {
|
||||
doReturn(false).when(mController).isSystemPackage(any(), any(), any());
|
||||
doReturn(new ComponentName(PACKAGE_NAME, "cls")).when(mPackageManager).getHomeActivities(
|
||||
anyList());
|
||||
|
||||
mController.mHomePackages.add(PACKAGE_NAME);
|
||||
mController.mHomePackages.add("com.android.home.fake");
|
||||
|
||||
mController.updateUninstallButton();
|
||||
|
||||
verify(mButtonPrefs).setButton2Enabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateUninstallButton_isSystemRro_setButtonDisable() {
|
||||
mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
|
||||
@@ -477,7 +510,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
throws PackageManager.NameNotFoundException {
|
||||
doReturn(AppButtonsPreferenceController.AVAILABLE)
|
||||
.when(mController).getAvailabilityStatus();
|
||||
doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt());
|
||||
doReturn(mPackageInfo).when(mPackageManager).getPackageInfo(anyString(), anyInt());
|
||||
doReturn(mButtonPrefs).when(mScreen).findPreference(anyString());
|
||||
mController.displayPreference(mScreen);
|
||||
mController.mButtonsPref = null;
|
||||
|
||||
@@ -35,6 +35,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.ecm.EnhancedConfirmationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@@ -90,7 +91,8 @@ public final class AppInfoDashboardFragmentTest {
|
||||
private DevicePolicyManager mDevicePolicyManager;
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
|
||||
@Mock
|
||||
private EnhancedConfirmationManager mEcManager;
|
||||
private AppInfoDashboardFragment mFragment;
|
||||
private Context mShadowContext;
|
||||
|
||||
@@ -102,6 +104,7 @@ public final class AppInfoDashboardFragmentTest {
|
||||
doReturn(mActivity).when(mFragment).getActivity();
|
||||
doReturn(mShadowContext).when(mFragment).getContext();
|
||||
doReturn(mPackageManager).when(mActivity).getPackageManager();
|
||||
doReturn(mEcManager).when(mActivity).getSystemService(EnhancedConfirmationManager.class);
|
||||
when(mUserManager.isAdminUser()).thenReturn(true);
|
||||
|
||||
ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.settings.applications.appinfo;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -25,10 +26,12 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.applications.ProcStatsData;
|
||||
@@ -37,14 +40,14 @@ import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
@@ -54,6 +57,8 @@ import org.robolectric.util.ReflectionHelpers;
|
||||
com.android.settings.testutils.shadow.ShadowFragment.class,
|
||||
})
|
||||
public class AppMemoryPreferenceControllerTest {
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
@Mock
|
||||
private SettingsActivity mActivity;
|
||||
@@ -69,9 +74,11 @@ public class AppMemoryPreferenceControllerTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
ShadowUserManager.getShadow().setIsAdminUser(true);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
UserManager userManager = mock(UserManager.class);
|
||||
when(userManager.isAdminUser()).thenReturn(true);
|
||||
doReturn(userManager).when(mContext).getSystemService(Context.USER_SERVICE);
|
||||
|
||||
mController =
|
||||
spy(new AppMemoryPreferenceController(mContext, mFragment, null /* lifecycle */));
|
||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
|
||||
@@ -80,7 +87,6 @@ public class AppMemoryPreferenceControllerTest {
|
||||
when(mFragment.getActivity()).thenReturn(mActivity);
|
||||
}
|
||||
|
||||
@Ignore("b/313582035")
|
||||
@Test
|
||||
@Config(qualifiers = "mcc999")
|
||||
public void getAvailabilityStatus_developmentSettingsEnabled_shouldReturnAvailable() {
|
||||
|
||||
@@ -19,16 +19,28 @@ package com.android.settings.applications.specialaccess;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.role.RoleManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.nfc.cardemulation.CardEmulation;
|
||||
import android.os.UserManager;
|
||||
import android.permission.flags.Flags;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
@@ -37,6 +49,10 @@ import org.robolectric.util.ReflectionHelpers;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class DefaultPaymentSettingsPreferenceControllerTest {
|
||||
|
||||
private static final String PREF_KEY = "key";
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
@Mock
|
||||
private NfcAdapter mNfcAdapter;
|
||||
@Mock
|
||||
@@ -45,6 +61,10 @@ public class DefaultPaymentSettingsPreferenceControllerTest {
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private RoleManager mRoleManager;
|
||||
@Mock
|
||||
private Preference mPreference;
|
||||
|
||||
private DefaultPaymentSettingsPreferenceController mController;
|
||||
|
||||
@@ -55,7 +75,8 @@ public class DefaultPaymentSettingsPreferenceControllerTest {
|
||||
when(mContext.getApplicationContext()).thenReturn(mContext);
|
||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
mController = new DefaultPaymentSettingsPreferenceController(mContext, "key");
|
||||
when(mContext.getSystemService(RoleManager.class)).thenReturn(mRoleManager);
|
||||
mController = new DefaultPaymentSettingsPreferenceController(mContext, PREF_KEY);
|
||||
ReflectionHelpers.setField(mController, "mNfcAdapter", mNfcAdapter);
|
||||
}
|
||||
|
||||
@@ -86,4 +107,20 @@ public class DefaultPaymentSettingsPreferenceControllerTest {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||
DefaultPaymentSettingsPreferenceController.DISABLED_DEPENDENT_SETTING);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_WALLET_ROLE_ENABLED)
|
||||
public void handlePreferenceTreeClick_walletRoleEnabled_shouldReturnTrue() {
|
||||
when(mRoleManager.isRoleAvailable(anyString())).thenReturn(true);
|
||||
when(mPreference.getKey()).thenReturn(PREF_KEY);
|
||||
ArgumentCaptor<String> roleTypeCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
|
||||
assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
|
||||
verify(mRoleManager).isRoleAvailable(roleTypeCaptor.capture());
|
||||
verify(mContext).startActivity(intentArgumentCaptor.capture());
|
||||
assertThat(roleTypeCaptor.getValue()).isEqualTo(RoleManager.ROLE_WALLET);
|
||||
assertThat(intentArgumentCaptor.getValue().getAction())
|
||||
.isEqualTo(CardEmulation.ACTION_CHANGE_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,35 @@
|
||||
|
||||
package com.android.settings.applications.specialaccess.premiumsms;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Process;
|
||||
import android.telephony.SmsManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.preference.R;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.datausage.AppStateDataUsageBridge;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
|
||||
import com.android.settingslib.RestrictedDropDownPreference;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -30,19 +52,28 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
ShadowRestrictedLockUtilsInternal.class
|
||||
})
|
||||
public class PremiumSmsAccessTest {
|
||||
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private PremiumSmsAccess mFragment;
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mFragment = new PremiumSmsAccess();
|
||||
mFragment.onAttach(RuntimeEnvironment.application);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mFragment.onAttach(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -74,4 +105,89 @@ public class PremiumSmsAccessTest {
|
||||
"app",
|
||||
SmsManager.PREMIUM_SMS_CONSENT_ALWAYS_ALLOW);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebuildComplete_ecmRestricted_shouldBeDisabled() {
|
||||
mFragment = spy(mFragment);
|
||||
mContext = spy(mContext);
|
||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
View view = inflater.inflate(R.layout.preference_dropdown, null);
|
||||
PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
|
||||
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
PreferenceScreen preferenceScreen = spy(preferenceManager.createPreferenceScreen(mContext));
|
||||
doReturn(preferenceManager).when(mFragment).getPreferenceManager();
|
||||
doReturn(preferenceScreen).when(mFragment).getPreferenceScreen();
|
||||
final String testPkg = "com.example.disabled";
|
||||
doNothing().when(mContext).startActivity(any());
|
||||
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(testPkg);
|
||||
|
||||
doAnswer((invocation) -> {
|
||||
final RestrictedDropDownPreference preference = invocation.getArgument(0);
|
||||
// Verify preference is disabled by ecm and the summary is changed accordingly.
|
||||
assertThat(preference.isDisabledByEcm()).isTrue();
|
||||
assertThat(preference.getSummary().toString()).isEqualTo(
|
||||
mContext.getString(
|
||||
com.android.settingslib.R.string.disabled_by_app_ops_text));
|
||||
preference.onBindViewHolder(holder);
|
||||
preference.performClick();
|
||||
// Verify that when the preference is clicked, ecm details intent is launched
|
||||
verify(mContext).startActivity(any());
|
||||
|
||||
return null;
|
||||
}).when(preferenceScreen).addPreference(any(RestrictedDropDownPreference.class));
|
||||
|
||||
mFragment.onRebuildComplete(createAppEntries(testPkg));
|
||||
verify(preferenceScreen).addPreference(any(RestrictedDropDownPreference.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebuildComplete_ecmNotRestricted_notDisabled() {
|
||||
mFragment = spy(mFragment);
|
||||
mContext = spy(mContext);
|
||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
View view = inflater.inflate(R.layout.preference_dropdown, null);
|
||||
PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
|
||||
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
PreferenceScreen preferenceScreen = spy(preferenceManager.createPreferenceScreen(mContext));
|
||||
doReturn(preferenceManager).when(mFragment).getPreferenceManager();
|
||||
doReturn(preferenceScreen).when(mFragment).getPreferenceScreen();
|
||||
final String testPkg = "com.example.enabled";
|
||||
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
|
||||
|
||||
|
||||
doAnswer((invocation) -> {
|
||||
final RestrictedDropDownPreference preference = invocation.getArgument(0);
|
||||
assertThat(preference.isDisabledByEcm()).isFalse();
|
||||
assertThat(preference.getSummary().toString()).isEqualTo("");
|
||||
preference.onBindViewHolder(holder);
|
||||
preference.performClick();
|
||||
// Verify that when the preference is clicked, ecm details intent is not launched
|
||||
verify(mContext, never()).startActivity(any());
|
||||
|
||||
return null;
|
||||
}).when(preferenceScreen).addPreference(any(RestrictedDropDownPreference.class));
|
||||
|
||||
mFragment.onRebuildComplete(createAppEntries(testPkg));
|
||||
verify(preferenceScreen).addPreference(any(RestrictedDropDownPreference.class));
|
||||
}
|
||||
|
||||
private ArrayList<ApplicationsState.AppEntry> createAppEntries(String... packageNames) {
|
||||
final ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
||||
for (int i = 0; i < packageNames.length; ++i) {
|
||||
final ApplicationInfo info = new ApplicationInfo();
|
||||
info.packageName = packageNames[i];
|
||||
info.uid = Process.FIRST_APPLICATION_UID + i;
|
||||
info.sourceDir = info.packageName;
|
||||
final ApplicationsState.AppEntry appEntry =
|
||||
spy(new ApplicationsState.AppEntry(mContext, info, i));
|
||||
appEntry.extraInfo = new AppStateDataUsageBridge
|
||||
.DataUsageState(false, false);
|
||||
doNothing().when(appEntry).ensureLabel(any(Context.class));
|
||||
ReflectionHelpers.setField(appEntry, "info", info);
|
||||
appEntries.add(appEntry);
|
||||
}
|
||||
return appEntries;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,15 +23,15 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.testutils.shadow.ShadowActivityManager;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.shadows.ShadowActivityManager;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
@@ -45,7 +45,7 @@ public class VrListenerScreenPreferenceControllerTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mController = new VrListenerScreenPreferenceController(mContext, "key");
|
||||
mActivityManager = Shadow.extract(mContext.getSystemService(Context.ACTIVITY_SERVICE));
|
||||
}
|
||||
|
||||
@@ -25,23 +25,20 @@ import static org.mockito.Mockito.verify;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowActivityManager;
|
||||
import com.android.settings.testutils.shadow.ShadowNotificationManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
ShadowActivityManager.class,
|
||||
})
|
||||
public class ZenAccessControllerTest {
|
||||
|
||||
private static final String TEST_PKG = "com.test.package";
|
||||
@@ -49,15 +46,12 @@ public class ZenAccessControllerTest {
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private Context mContext;
|
||||
private ZenAccessController mController;
|
||||
private ShadowActivityManager mActivityManager;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mController = new ZenAccessController(mContext, "key");
|
||||
mActivityManager = Shadow.extract(mContext.getSystemService(Context.ACTIVITY_SERVICE));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.biometrics;
|
||||
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.os.Looper;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = ShadowAlertDialogCompat.class)
|
||||
public class BiometricsSplitScreenDialogTest {
|
||||
@Rule
|
||||
public final MockitoRule mocks = MockitoJUnit.rule();
|
||||
private FragmentActivity mActivity;
|
||||
private BiometricsSplitScreenDialog mFragment;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ShadowAlertDialogCompat.reset();
|
||||
mActivity = Robolectric.buildActivity(FragmentActivity.class).setup().get();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowAlertDialogCompat.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTexts_face() {
|
||||
final AlertDialog dialog = setUpFragment(TYPE_FACE, false /*destroyActivity*/);
|
||||
|
||||
final ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
assertThat(shadowAlertDialog.getTitle().toString()).isEqualTo(
|
||||
mActivity.getString(R.string.biometric_settings_add_face_in_split_mode_title));
|
||||
assertThat(shadowAlertDialog.getMessage().toString()).isEqualTo(
|
||||
mActivity.getString(R.string.biometric_settings_add_face_in_split_mode_message));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTexts_fingerprint() {
|
||||
final AlertDialog dialog = setUpFragment(TYPE_FINGERPRINT, false /*destroyActivity*/);
|
||||
|
||||
final ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
assertThat(shadowAlertDialog.getTitle().toString()).isEqualTo(
|
||||
mActivity.getString(
|
||||
R.string.biometric_settings_add_fingerprint_in_split_mode_title));
|
||||
assertThat(shadowAlertDialog.getMessage().toString()).isEqualTo(
|
||||
mActivity.getString(
|
||||
R.string.biometric_settings_add_fingerprint_in_split_mode_message));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testButton_destroyActivity() {
|
||||
final AlertDialog dialog = setUpFragment(TYPE_FACE, true /*destroyActivity*/);
|
||||
final Button button = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
|
||||
assertThat(button).isNotNull();
|
||||
button.performClick();
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
assertThat(mActivity.isFinishing()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testButton_notDestroyActivity() {
|
||||
final AlertDialog dialog = setUpFragment(TYPE_FACE, false /*destroyActivity*/);
|
||||
final Button button = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
|
||||
assertThat(button).isNotNull();
|
||||
button.performClick();
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
assertThat(mActivity.isFinishing()).isFalse();
|
||||
}
|
||||
|
||||
private AlertDialog setUpFragment(
|
||||
@BiometricAuthenticator.Modality int biometricsModality, boolean destroyActivity) {
|
||||
mFragment = BiometricsSplitScreenDialog.newInstance(biometricsModality, destroyActivity);
|
||||
mFragment.show(mActivity.getSupportFragmentManager(), null);
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog).isNotNull();
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.settings.biometrics.combination;
|
||||
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
||||
|
||||
import static com.android.settings.biometrics.combination.BiometricsSettingsBase.CONFIRM_REQUEST;
|
||||
import static com.android.settings.password.ChooseLockPattern.RESULT_FINISHED;
|
||||
|
||||
@@ -26,7 +24,6 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
@@ -37,11 +34,8 @@ import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.hardware.biometrics.ComponentInfoInternal;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.os.Bundle;
|
||||
import android.util.AndroidRuntimeException;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -52,15 +46,12 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.XmlRes;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.biometrics.BiometricStatusPreferenceController;
|
||||
import com.android.settings.biometrics.BiometricsSplitScreenDialog;
|
||||
import com.android.settings.biometrics.face.FaceStatusPreferenceController;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
@@ -72,7 +63,6 @@ import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -112,8 +102,6 @@ public class CombinedBiometricProfileSettingsTest {
|
||||
private FaceStatusPreferenceController mFaceStatusPreferenceController;
|
||||
@Mock
|
||||
private FaceManager mFaceManager;
|
||||
@Mock
|
||||
private FragmentTransaction mFragmentTransaction;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -350,133 +338,6 @@ public class CombinedBiometricProfileSettingsTest {
|
||||
assertThat(capturedPreferences.get(0).getKey()).isEqualTo(mFragment.getFacePreferenceKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClickFingerprintUnlock_inMultiWindow_withoutEnrolledFp_showsDialog() {
|
||||
testClickFingerprintUnlock(true /* isInMultiWindow */, false /* hasEnrolledFingerprint */);
|
||||
verifyShowsDialogAfterClickingUnlock(mFragment.getFingerprintPreferenceKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClickFingerprintUnlock_inMultiWindow_withEnrolledFp_noDialog() {
|
||||
testClickFingerprintUnlock(true /* isInMultiWindow */, true /* hasEnrolledFingerprint */);
|
||||
verifyNoDialogAfterClickingUnlock(mFragment.getFingerprintPreferenceKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClickFingerprintUnlock_inFullScreen_withoutEnrolledFp_noDialog() {
|
||||
testClickFingerprintUnlock(false /* isInMultiWindow */, false /* hasEnrolledFingerprint */);
|
||||
verifyNoDialogAfterClickingUnlock(mFragment.getFingerprintPreferenceKey());
|
||||
}
|
||||
|
||||
private void testClickFingerprintUnlock(boolean isInMultiWindow,
|
||||
boolean hasEnrolledFingerprint) {
|
||||
final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
|
||||
props.add(new FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
1 /* maxEnrollmentsPerUser */,
|
||||
new ArrayList<ComponentInfoInternal>(),
|
||||
TYPE_UDFPS_OPTICAL,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */));
|
||||
doReturn(props).when(mFingerprintManager).getSensorPropertiesInternal();
|
||||
|
||||
doAnswer(invocation -> {
|
||||
final FingerprintManager.GenerateChallengeCallback callback =
|
||||
invocation.getArgument(1);
|
||||
callback.onChallengeGenerated(0, 0, 1L);
|
||||
return null;
|
||||
}).when(mFingerprintManager).generateChallenge(anyInt(), any());
|
||||
doReturn(new byte[]{1}).when(mFragment).requestGatekeeperHat(any(), anyLong(), anyInt(),
|
||||
anyLong());
|
||||
FragmentManager fragmentManager = mock(FragmentManager.class);
|
||||
doReturn(fragmentManager).when(mActivity).getSupportFragmentManager();
|
||||
doReturn(mFragmentTransaction).when(fragmentManager).beginTransaction();
|
||||
doReturn(isInMultiWindow).when(mActivity).isInMultiWindowMode();
|
||||
doReturn(hasEnrolledFingerprint).when(mFingerprintManager).hasEnrolledFingerprints(
|
||||
anyInt());
|
||||
|
||||
// Start fragment
|
||||
mFragment.onAttach(mContext);
|
||||
mFragment.onCreate(null);
|
||||
mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
|
||||
mFragment.onResume();
|
||||
|
||||
// User clicks on "Fingerprint Unlock"
|
||||
final Preference preference = new Preference(mContext);
|
||||
preference.setKey(mFragment.getFingerprintPreferenceKey());
|
||||
mFragment.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/295325503")
|
||||
public void testClickFaceUnlock_inMultiWindow_withoutEnrolledFp_showsDialog() {
|
||||
testClickFaceUnlock(true /* isInMultiWindow */, false /*hasEnrolledFace*/);
|
||||
verifyShowsDialogAfterClickingUnlock(mFragment.getFacePreferenceKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClickFaceUnlock_inMultiWindow_withEnrolledFp_noDialog() {
|
||||
testClickFaceUnlock(true /* isInMultiWindow */, true /* hasEnrolledFace */);
|
||||
verifyNoDialogAfterClickingUnlock(mFragment.getFacePreferenceKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClickFaceUnlock_inFullScreen_withoutEnrolledFp_noDialog() {
|
||||
testClickFaceUnlock(false /* isInMultiWindow */ , false /* hasEnrolledFace */);
|
||||
verifyNoDialogAfterClickingUnlock(mFragment.getFacePreferenceKey());
|
||||
}
|
||||
|
||||
private void testClickFaceUnlock(boolean isInMultiWindow, boolean hasEnrolledFace) {
|
||||
doAnswer(invocation -> {
|
||||
final FaceManager.GenerateChallengeCallback callback =
|
||||
invocation.getArgument(1);
|
||||
callback.onGenerateChallengeResult(0, 0, 1L);
|
||||
return null;
|
||||
}).when(mFaceManager).generateChallenge(anyInt(), any());
|
||||
doReturn(new byte[] { 1 }).when(mFragment).requestGatekeeperHat(any(), anyLong(), anyInt(),
|
||||
anyLong());
|
||||
FragmentManager fragmentManager = mock(FragmentManager.class);
|
||||
doReturn(fragmentManager).when(mActivity).getSupportFragmentManager();
|
||||
doReturn(mFragmentTransaction).when(fragmentManager).beginTransaction();
|
||||
doReturn(isInMultiWindow).when(mActivity).isInMultiWindowMode();
|
||||
doReturn(hasEnrolledFace).when(mFaceManager).hasEnrolledTemplates(
|
||||
anyInt());
|
||||
|
||||
// Start fragment
|
||||
mFragment.onAttach(mContext);
|
||||
mFragment.onCreate(null);
|
||||
mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
|
||||
mFragment.onResume();
|
||||
|
||||
// User clicks on "Face Unlock"
|
||||
final Preference preference = new Preference(mContext);
|
||||
preference.setKey(mFragment.getFacePreferenceKey());
|
||||
mFragment.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
private void verifyNoDialogAfterClickingUnlock(String preferenceKey) {
|
||||
final BiometricStatusPreferenceController controller =
|
||||
preferenceKey.equals(mFragment.getFacePreferenceKey())
|
||||
? mFaceStatusPreferenceController
|
||||
: mFingerprintStatusPreferenceController;
|
||||
verify(controller).handlePreferenceTreeClick(mPreferenceCaptor.capture());
|
||||
List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues();
|
||||
assertThat(capturedPreferences).hasSize(1);
|
||||
assertThat(capturedPreferences.get(0).getKey()).isEqualTo(preferenceKey);
|
||||
verify(mFragmentTransaction, never()).add(any(),
|
||||
eq(BiometricsSplitScreenDialog.class.getName()));
|
||||
}
|
||||
|
||||
private void verifyShowsDialogAfterClickingUnlock(String preferenceKey) {
|
||||
final BiometricStatusPreferenceController controller =
|
||||
preferenceKey.equals(mFragment.getFacePreferenceKey())
|
||||
? mFaceStatusPreferenceController
|
||||
: mFingerprintStatusPreferenceController;
|
||||
verify(controller, never()).handlePreferenceTreeClick(any());
|
||||
verify(mFragmentTransaction).add(any(),
|
||||
eq(BiometricsSplitScreenDialog.class.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoCrashIfDetachActivityDuringGeneratingChallengeThroughFaceManager() {
|
||||
doAnswer(invocation -> {
|
||||
|
||||
@@ -38,20 +38,25 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.face.Face;
|
||||
import android.hardware.face.FaceEnrollOptions;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.hardware.face.FaceSensorProperties;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
|
||||
import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
@@ -62,6 +67,7 @@ import com.android.settings.biometrics.BiometricUtils;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
||||
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
|
||||
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager;
|
||||
@@ -101,7 +107,8 @@ import java.util.List;
|
||||
ShadowUtils.class,
|
||||
ShadowDevicePolicyManager.class,
|
||||
ShadowSensorPrivacyManager.class,
|
||||
SettingsShadowResources.class
|
||||
SettingsShadowResources.class,
|
||||
ShadowAlertDialogCompat.class
|
||||
})
|
||||
public class FaceEnrollIntroductionTest {
|
||||
|
||||
@@ -123,8 +130,8 @@ public class FaceEnrollIntroductionTest {
|
||||
enum GateKeeperAction {CALL_SUPER, RETURN_BYTE_ARRAY, THROW_CREDENTIAL_NOT_MATCH}
|
||||
|
||||
public static class TestFaceEnrollIntroduction extends FaceEnrollIntroduction {
|
||||
|
||||
private int mRecreateCount = 0;
|
||||
public boolean mIsMultiWindowMode;
|
||||
|
||||
public int getRecreateCount() {
|
||||
return mRecreateCount;
|
||||
@@ -161,6 +168,11 @@ public class FaceEnrollIntroductionTest {
|
||||
protected boolean launchPostureGuidance() {
|
||||
return super.launchPostureGuidance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInMultiWindowMode() {
|
||||
return mIsMultiWindowMode;
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
@@ -178,12 +190,15 @@ public class FaceEnrollIntroductionTest {
|
||||
public void tearDown() {
|
||||
ShadowUtils.reset();
|
||||
ShadowLockPatternUtils.reset();
|
||||
ShadowAlertDialogCompat.reset();
|
||||
}
|
||||
|
||||
private void setupActivity() {
|
||||
final Intent testIntent = new Intent();
|
||||
// Set the challenge token so the confirm screen will not be shown
|
||||
testIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
|
||||
testIntent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
|
||||
FaceEnrollOptions.ENROLL_REASON_SETTINGS);
|
||||
|
||||
when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any())).thenReturn(
|
||||
null /* Simulate no posture intent */);
|
||||
@@ -208,6 +223,8 @@ public class FaceEnrollIntroductionTest {
|
||||
testIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
|
||||
testIntent.putExtra(EXTRA_KEY_NEXT_LAUNCHED, false);
|
||||
testIntent.putExtra(EXTRA_LAUNCHED_POSTURE_GUIDANCE, false);
|
||||
testIntent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
|
||||
FaceEnrollOptions.ENROLL_REASON_SETTINGS);
|
||||
|
||||
when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any())).thenReturn(
|
||||
testIntent);
|
||||
@@ -596,4 +613,47 @@ public class FaceEnrollIntroductionTest {
|
||||
assertThat(result).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiWindow_showsDialog() {
|
||||
mController = Robolectric.buildActivity(TestFaceEnrollIntroduction.class);
|
||||
mActivity = (TestFaceEnrollIntroduction) mController.get();
|
||||
mActivity.mIsMultiWindowMode = true;
|
||||
mController.setup().get();
|
||||
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
||||
final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog).isNotNull();
|
||||
|
||||
final ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
assertThat(shadowAlertDialog.getTitle().toString()).isEqualTo(
|
||||
mActivity.getString(R.string.biometric_settings_add_face_in_split_mode_title));
|
||||
assertThat(shadowAlertDialog.getMessage().toString()).isEqualTo(
|
||||
mActivity.getString(R.string.biometric_settings_add_face_in_split_mode_message));
|
||||
|
||||
final Button button = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
assertThat(button).isNotNull();
|
||||
button.performClick();
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
assertThat(mActivity.isFinishing()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleWindow_noDialog() {
|
||||
Robolectric.buildActivity(TestFaceEnrollIntroduction.class).setup().get();
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFaceEnrollIntroduction_forwardsEnrollOptions() {
|
||||
setupActivity();
|
||||
final Intent intent = mActivity.getEnrollingIntent();
|
||||
|
||||
assertThat(intent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1))
|
||||
.isEqualTo(FaceEnrollOptions.ENROLL_REASON_SETTINGS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -669,7 +669,8 @@ public class FingerprintEnrollEnrollingTest {
|
||||
any(CancellationSignal.class),
|
||||
anyInt(),
|
||||
callbackCaptor.capture(),
|
||||
eq(FingerprintManager.ENROLL_ENROLL));
|
||||
eq(FingerprintManager.ENROLL_ENROLL),
|
||||
any());
|
||||
|
||||
return callbackCaptor.getValue();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.robolectric.RuntimeEnvironment.application;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
@@ -52,6 +51,7 @@ import android.os.CancellationSignal;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -227,7 +227,8 @@ public class FingerprintEnrollFindSensorTest {
|
||||
any(CancellationSignal.class),
|
||||
anyInt(),
|
||||
callbackCaptor.capture(),
|
||||
eq(FingerprintManager.ENROLL_FIND_SENSOR));
|
||||
eq(FingerprintManager.ENROLL_FIND_SENSOR),
|
||||
any());
|
||||
|
||||
return callbackCaptor.getValue();
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.content.res.Resources;
|
||||
import android.hardware.biometrics.ComponentInfoInternal;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.fingerprint.Fingerprint;
|
||||
import android.hardware.fingerprint.FingerprintEnrollOptions;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
@@ -52,6 +53,7 @@ import androidx.annotation.Nullable;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.biometrics.BiometricUtils;
|
||||
import com.android.settings.biometrics.GatekeeperPasswordProvider;
|
||||
|
||||
import com.google.android.setupcompat.util.WizardManagerHelper;
|
||||
@@ -289,6 +291,18 @@ public class FingerprintEnrollIntroductionTest {
|
||||
assertThat(mFingerprintEnrollIntroduction.shouldFinishWhenBackgrounded()).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFingerprintEnrollIntroduction_forwardsEnrollOptions() {
|
||||
final Intent intent = newTokenOnlyIntent();
|
||||
intent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
|
||||
FingerprintEnrollOptions.ENROLL_REASON_SETTINGS);
|
||||
setupFingerprintEnrollIntroWith(intent);
|
||||
|
||||
final Intent enrollingIntent = mFingerprintEnrollIntroduction.getEnrollingIntent();
|
||||
assertThat(enrollingIntent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1))
|
||||
.isEqualTo(FingerprintEnrollOptions.ENROLL_REASON_SETTINGS);
|
||||
}
|
||||
|
||||
private Intent newTokenOnlyIntent() {
|
||||
return new Intent()
|
||||
.putExtra(EXTRA_KEY_CHALLENGE_TOKEN, new byte[] { 1 });
|
||||
|
||||
@@ -20,9 +20,7 @@ import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWE
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
||||
|
||||
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment;
|
||||
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.ADD_FINGERPRINT_REQUEST;
|
||||
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.CHOOSE_LOCK_GENERIC_REQUEST;
|
||||
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.KEY_FINGERPRINT_ADD;
|
||||
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.KEY_REQUIRE_SCREEN_ON_TO_AUTH;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@@ -34,9 +32,7 @@ import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
@@ -57,10 +53,8 @@ import android.view.ViewGroup;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.biometrics.BiometricsSplitScreenDialog;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowFragment;
|
||||
@@ -132,35 +126,6 @@ public class FingerprintSettingsFragmentTest {
|
||||
ShadowUtils.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddFingerprint_inFullScreen_noDialog() {
|
||||
setUpFragment(false);
|
||||
// Click "Add Fingerprint"
|
||||
final Preference preference = new Preference(mContext);
|
||||
preference.setKey(KEY_FINGERPRINT_ADD);
|
||||
mFragment.onPreferenceTreeClick(preference);
|
||||
|
||||
verify(mFragment).startActivityForResult(any(), eq(ADD_FINGERPRINT_REQUEST));
|
||||
verify(mFragmentTransaction, never()).add(any(),
|
||||
eq(BiometricsSplitScreenDialog.class.getName()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddFingerprint_inMultiWindow_showsDialog() {
|
||||
setUpFragment(false);
|
||||
|
||||
doReturn(true).when(mActivity).isInMultiWindowMode();
|
||||
|
||||
// Click "Add Fingerprint"
|
||||
final Preference preference = new Preference(mContext);
|
||||
preference.setKey(KEY_FINGERPRINT_ADD);
|
||||
mFragment.onPreferenceTreeClick(preference);
|
||||
|
||||
verify(mFragment, times(0)).startActivityForResult(any(), eq(ADD_FINGERPRINT_REQUEST));
|
||||
verify(mFragmentTransaction).add(any(), eq(BiometricsSplitScreenDialog.class.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChooseLockKeyForFingerprint() {
|
||||
setUpFragment(true);
|
||||
@@ -262,6 +227,7 @@ public class FingerprintSettingsFragmentTest {
|
||||
mFragment.onResume();
|
||||
}
|
||||
|
||||
@Ignore("b/315519360")
|
||||
@Test
|
||||
public void testFragmentVisibleWhenNoHardwareDetected() {
|
||||
doReturn(false).when(mFingerprintManager).isHardwareDetected();
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import static org.robolectric.RuntimeEnvironment.application;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -28,14 +29,18 @@ import android.hardware.biometrics.ComponentInfoInternal;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.biometrics.BiometricEnrollBase;
|
||||
import com.android.settings.biometrics.BiometricEnrollIntroduction;
|
||||
import com.android.settings.password.SetupSkipDialog;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
||||
import com.android.settings.testutils.shadow.ShadowFingerprintManager;
|
||||
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowStorageManager;
|
||||
@@ -66,12 +71,23 @@ import java.util.List;
|
||||
ShadowFingerprintManager.class,
|
||||
ShadowLockPatternUtils.class,
|
||||
ShadowStorageManager.class,
|
||||
ShadowUserManager.class
|
||||
ShadowUserManager.class,
|
||||
ShadowAlertDialogCompat.class
|
||||
})
|
||||
public class SetupFingerprintEnrollIntroductionTest {
|
||||
|
||||
private ActivityController<SetupFingerprintEnrollIntroduction> mController;
|
||||
|
||||
public static class TestSetupFingerprintEnrollIntroductionInMultiWindowMode
|
||||
extends SetupFingerprintEnrollIntroduction {
|
||||
public boolean mIsMultiWindowMode = true;
|
||||
|
||||
@Override
|
||||
public boolean isInMultiWindowMode() {
|
||||
return mIsMultiWindowMode;
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
Shadows.shadowOf(application.getPackageManager())
|
||||
@@ -105,6 +121,36 @@ public class SetupFingerprintEnrollIntroductionTest {
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowStorageManager.reset();
|
||||
ShadowAlertDialogCompat.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiWindow_showsDialog() {
|
||||
Activity activity = Robolectric.buildActivity(
|
||||
TestSetupFingerprintEnrollIntroductionInMultiWindowMode.class).setup().get();
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
||||
final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog).isNotNull();
|
||||
|
||||
final ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
assertThat(shadowAlertDialog.getTitle().toString()).isEqualTo(
|
||||
activity.getString(
|
||||
R.string.biometric_settings_add_fingerprint_in_split_mode_title));
|
||||
assertThat(shadowAlertDialog.getMessage().toString()).isEqualTo(
|
||||
activity.getString(
|
||||
R.string.biometric_settings_add_fingerprint_in_split_mode_message));
|
||||
|
||||
// TODO(b/299573056): Make WizardManagerHelper.isAnySetupWizard(getIntent()) correct and
|
||||
// test button click not finishing the activity.
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleWindow_noDialog() {
|
||||
Robolectric.buildActivity(SetupFingerprintEnrollIntroduction.class).setup().get();
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -33,16 +33,20 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.runner.AndroidJUnit4
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Introduction
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.NavigationState
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollIntroV2Fragment
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollIntroViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Intro
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.NavState
|
||||
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.android.systemui.biometrics.shared.model.SensorStrength
|
||||
import com.google.android.setupdesign.GlifLayout
|
||||
import com.google.android.setupdesign.template.RequireScrollMixin
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
@@ -62,18 +66,27 @@ class FingerprintEnrollIntroFragmentTest {
|
||||
)
|
||||
private val backgroundDispatcher = StandardTestDispatcher()
|
||||
private lateinit var fragmentScenario: FragmentScenario<FingerprintEnrollIntroV2Fragment>
|
||||
private val fingerprintSensor =
|
||||
FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.POWER_BUTTON)
|
||||
|
||||
var enrollFlow = Default
|
||||
val flowViewModel = FingerprintFlowViewModel(enrollFlow)
|
||||
|
||||
private val navigationViewModel =
|
||||
FingerprintEnrollNavigationViewModel(
|
||||
backgroundDispatcher,
|
||||
interactor,
|
||||
gatekeeperViewModel,
|
||||
Intro,
|
||||
NavState(true),
|
||||
Default,
|
||||
FingerprintNavigationViewModel(
|
||||
Introduction,
|
||||
false,
|
||||
flowViewModel,
|
||||
interactor
|
||||
)
|
||||
|
||||
private var fingerprintViewModel =
|
||||
FingerprintEnrollViewModel(interactor, gatekeeperViewModel, navigationViewModel)
|
||||
FingerprintEnrollIntroViewModel(
|
||||
navigationViewModel,
|
||||
flowViewModel,
|
||||
interactor,
|
||||
)
|
||||
|
||||
private var fingerprintScrollViewModel = FingerprintScrollViewModel()
|
||||
|
||||
@Before
|
||||
@@ -85,9 +98,9 @@ class FingerprintEnrollIntroFragmentTest {
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
return when (modelClass) {
|
||||
FingerprintEnrollViewModel::class.java -> fingerprintViewModel
|
||||
FingerprintEnrollIntroViewModel::class.java -> fingerprintViewModel
|
||||
FingerprintScrollViewModel::class.java -> fingerprintScrollViewModel
|
||||
FingerprintEnrollNavigationViewModel::class.java -> navigationViewModel
|
||||
FingerprintNavigationViewModel::class.java -> navigationViewModel
|
||||
FingerprintGatekeeperViewModel::class.java -> gatekeeperViewModel
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include /src/com/android/settings/biometrics/fingerprint2/OWNERS
|
||||
@@ -59,7 +59,6 @@ import org.robolectric.annotation.Config;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Ignore("b/313014781")
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowEntityHeaderController.class, ShadowDeviceConfig.class})
|
||||
public class AdvancedBluetoothDetailsHeaderControllerTest {
|
||||
@@ -386,6 +385,9 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
|
||||
.thenReturn("true".getBytes());
|
||||
Set<CachedBluetoothDevice> cacheBluetoothDevices = new HashSet<>();
|
||||
when(mCachedDevice.getMemberDevice()).thenReturn(cacheBluetoothDevices);
|
||||
when(mBluetoothAdapter.addOnMetadataChangedListener(
|
||||
mBluetoothDevice, mContext.getMainExecutor(), mController.mMetadataListener))
|
||||
.thenReturn(true);
|
||||
|
||||
mController.onStart();
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -25,36 +24,26 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.AudioManager;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.settings.connecteddevice.DevicePreferenceCallback;
|
||||
import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowAudioManager;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -75,9 +64,6 @@ import java.util.Collection;
|
||||
ShadowBluetoothUtils.class
|
||||
})
|
||||
public class AvailableMediaBluetoothDeviceUpdaterTest {
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
|
||||
|
||||
@Mock private DashboardFragment mDashboardFragment;
|
||||
@@ -86,11 +72,7 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
|
||||
@Mock private BluetoothDevice mBluetoothDevice;
|
||||
@Mock private Drawable mDrawable;
|
||||
@Mock private LocalBluetoothManager mLocalBtManager;
|
||||
@Mock private LocalBluetoothProfileManager mLocalBtProfileManager;
|
||||
@Mock private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
@Mock private LocalBluetoothLeBroadcast mBroadcast;
|
||||
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
|
||||
@Mock private BluetoothLeBroadcastReceiveState mBroadcastReceiveState;
|
||||
|
||||
private Context mContext;
|
||||
private AvailableMediaBluetoothDeviceUpdater mBluetoothDeviceUpdater;
|
||||
@@ -98,12 +80,14 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
|
||||
private AudioManager mAudioManager;
|
||||
private BluetoothDevicePreference mPreference;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
private AudioSharingFeatureProvider mFeatureProvider;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mFeatureProvider = FakeFeatureFactory.setupForTest().getAudioSharingFeatureProvider();
|
||||
mAudioManager = mContext.getSystemService(AudioManager.class);
|
||||
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
|
||||
mLocalBtManager = Utils.getLocalBtManager(mContext);
|
||||
@@ -267,13 +251,15 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onProfileConnectionStateChanged_leAudioDeviceConnected_notInCall_addsPreference() {
|
||||
setUpBroadcast(/* isSupported= */ false, /* isBroadcasting= */ false);
|
||||
public void
|
||||
onProfileConnectionStateChanged_leaDeviceConnected_notInCallNoSharing_addsPreference() {
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
|
||||
.thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
|
||||
when(mFeatureProvider.isAudioSharingFilterMatched(
|
||||
any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class)))
|
||||
.thenReturn(false);
|
||||
|
||||
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
@@ -284,13 +270,15 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onProfileConnectionStateChanged_leAudioDeviceConnected_inCall_addsPreference() {
|
||||
setUpBroadcast(/* isSupported= */ false, /* isBroadcasting= */ false);
|
||||
public void
|
||||
onProfileConnectionStateChanged_leaDeviceConnected_inCallNoSharing_addsPreference() {
|
||||
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
|
||||
when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
|
||||
.thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
|
||||
when(mFeatureProvider.isAudioSharingFilterMatched(
|
||||
any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class)))
|
||||
.thenReturn(false);
|
||||
|
||||
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
@@ -301,50 +289,16 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void
|
||||
onProfileConnectionStateChanged_leaDeviceConnected_notInCall_notInBroadcast_addsPref() {
|
||||
setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ false);
|
||||
onProfileConnectionStateChanged_leaDeviceConnected_notInCallInSharing_removesPref() {
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
|
||||
.thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
|
||||
|
||||
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void
|
||||
onProfileConnectionStateChanged_leaDeviceConnected_inCall_notInBroadcast_addsPref() {
|
||||
setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ false);
|
||||
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
|
||||
when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
|
||||
when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
|
||||
when(mFeatureProvider.isAudioSharingFilterMatched(
|
||||
any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class)))
|
||||
.thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
|
||||
|
||||
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void
|
||||
onProfileConnectionStateChanged_leaDeviceConnected_notInCall_inBroadcast_removesPref() {
|
||||
setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ true);
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
|
||||
.thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
|
||||
|
||||
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
@@ -355,14 +309,15 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void
|
||||
onProfileConnectionStateChanged_leaDeviceConnected_inCall_inBroadcast_removesPref() {
|
||||
setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ true);
|
||||
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
|
||||
public void onProfileConnectionStateChanged_leaDeviceConnected_inCallInSharing_removesPref() {
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
|
||||
.thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
|
||||
when(mFeatureProvider.isAudioSharingFilterMatched(
|
||||
any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class)))
|
||||
.thenReturn(true);
|
||||
|
||||
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
@@ -414,56 +369,9 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onClick_Preference_setActive() {
|
||||
setUpBroadcast(/* isSupported= */ false, /* isBroadcasting= */ false);
|
||||
mBluetoothDeviceUpdater.onPreferenceClick(mPreference);
|
||||
|
||||
verify(mCachedBluetoothDevice).setActive();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onClick_Preference_isNotBroadcasting_setActive() {
|
||||
setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ false);
|
||||
mBluetoothDeviceUpdater.onPreferenceClick(mPreference);
|
||||
|
||||
verify(mCachedBluetoothDevice).setActive();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onClick_Preference_isBroadcasting_stopBroadcastingAndSetActive() {
|
||||
setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ true);
|
||||
doNothing().when(mBroadcast).stopBroadcast(anyInt());
|
||||
mBluetoothDeviceUpdater.onPreferenceClick(mPreference);
|
||||
|
||||
verify(mBroadcast).stopBroadcast(anyInt());
|
||||
verify(mCachedBluetoothDevice).setActive();
|
||||
}
|
||||
|
||||
private void setUpBroadcast(boolean isSupported, boolean isBroadcasting) {
|
||||
if (isSupported) {
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
when(mLocalBtManager.getProfileManager()).thenReturn(mLocalBtProfileManager);
|
||||
when(mLocalBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(isBroadcasting);
|
||||
when(mLocalBtProfileManager.getLeAudioBroadcastAssistantProfile())
|
||||
.thenReturn(mAssistant);
|
||||
if (isBroadcasting) {
|
||||
when(mAssistant.getAllSources(any()))
|
||||
.thenReturn(ImmutableList.of(mBroadcastReceiveState));
|
||||
} else {
|
||||
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
|
||||
}
|
||||
} else {
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_NOT_SUPPORTED);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.bluetooth;
|
||||
|
||||
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.DISABLED;
|
||||
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.ENABLED;
|
||||
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.PREF_KEY;
|
||||
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.SETTING_NAME;
|
||||
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.UNSET;
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
|
||||
import static com.android.settingslib.flags.Flags.FLAG_BLUETOOTH_QS_TILE_DIALOG_AUTO_ON_TOGGLE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class BluetoothAutoOnPreferenceControllerTest {
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
private Context mContext;
|
||||
private ContentResolver mContentResolver;
|
||||
private BluetoothAutoOnPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mSetFlagsRule.enableFlags(FLAG_BLUETOOTH_QS_TILE_DIALOG_AUTO_ON_TOGGLE);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mContentResolver = mContext.getContentResolver();
|
||||
mController = new BluetoothAutoOnPreferenceController(mContext, PREF_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailability_valueUnset_returnUnsupported() {
|
||||
Settings.Secure.putInt(mContentResolver, SETTING_NAME, UNSET);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailability_valueSet_returnAvailable() {
|
||||
Settings.Secure.putInt(mContentResolver, SETTING_NAME, DISABLED);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_valueEnabled_returnTrue() {
|
||||
Settings.Secure.putInt(mContentResolver, SETTING_NAME, ENABLED);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
assertThat(mController.isChecked()).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_returnTrue() {
|
||||
Settings.Secure.putInt(mContentResolver, SETTING_NAME, DISABLED);
|
||||
|
||||
mController.setChecked(true);
|
||||
assertThat(mController.isChecked()).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_returnFalse() {
|
||||
Settings.Secure.putInt(mContentResolver, SETTING_NAME, ENABLED);
|
||||
|
||||
mController.setChecked(false);
|
||||
assertThat(mController.isChecked()).isEqualTo(false);
|
||||
}
|
||||
}
|
||||
@@ -112,6 +112,7 @@ public class BluetoothDetailsCompanionAppsControllerTest extends
|
||||
/* selfManaged */ false,
|
||||
/* notifyOnDeviceNearby */ true,
|
||||
/* revoked */ false,
|
||||
/* pending */ false,
|
||||
/* timeApprovedMs */ System.currentTimeMillis(),
|
||||
/* lastTimeConnected */ Long.MAX_VALUE,
|
||||
/* systemDataSyncFlags */ -1);
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.robolectric.annotation.Config;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
com.android.settings.testutils.shadow.ShadowFragment.class,
|
||||
com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal.class,
|
||||
})
|
||||
public abstract class BluetoothDetailsControllerTestBase {
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.bluetooth;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreferenceCompat;
|
||||
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.shadows.ShadowLooper;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class BluetoothDetailsExtraOptionsControllerTest extends BluetoothDetailsControllerTestBase {
|
||||
|
||||
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
|
||||
@Mock private BluetoothDevice mBluetoothDevice;
|
||||
@Mock private Lifecycle mExtraOptionsLifecycle;
|
||||
@Mock private PreferenceCategory mOptionsContainer;
|
||||
@Mock private PreferenceScreen mPreferenceScreen;
|
||||
|
||||
private BluetoothDetailsExtraOptionsController mController;
|
||||
private BluetoothFeatureProvider mFeatureProvider;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
when(mCachedDevice.getAddress()).thenReturn(MAC_ADDRESS);
|
||||
when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
when(mBluetoothDevice.getAnonymizedAddress()).thenReturn(MAC_ADDRESS);
|
||||
|
||||
final FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mFeatureProvider = fakeFeatureFactory.getBluetoothFeatureProvider();
|
||||
|
||||
mController =
|
||||
new BluetoothDetailsExtraOptionsController(
|
||||
mContext, mFragment, mCachedDevice, mExtraOptionsLifecycle);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_removeAndAddPreferences() {
|
||||
Preference preference1 = new SwitchPreferenceCompat(mContext);
|
||||
Preference preference2 = new SwitchPreferenceCompat(mContext);
|
||||
when(mFeatureProvider.getBluetoothExtraOptions(mContext, mCachedDevice))
|
||||
.thenReturn(ImmutableList.of(preference1, preference2));
|
||||
when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
|
||||
.thenReturn(mOptionsContainer);
|
||||
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
ShadowLooper.idleMainLooper();
|
||||
|
||||
verify(mOptionsContainer).removeAll();
|
||||
verify(mOptionsContainer).addPreference(preference1);
|
||||
verify(mOptionsContainer).addPreference(preference2);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package com.android.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -28,23 +29,33 @@ import android.bluetooth.BluetoothClass;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.sysprop.BluetoothProperties;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.preference.SwitchPreferenceCompat;
|
||||
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothDevice;
|
||||
import com.android.settingslib.R;
|
||||
import com.android.settingslib.bluetooth.A2dpProfile;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LeAudioProfile;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
import com.android.settingslib.bluetooth.MapProfile;
|
||||
import com.android.settingslib.bluetooth.PbapServerProfile;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -59,30 +70,41 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Ignore
|
||||
@Config(shadows = ShadowBluetoothDevice.class)
|
||||
public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsControllerTestBase {
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
private static final String LE_DEVICE_MODEL = "le_audio_headset";
|
||||
private static final String NON_LE_DEVICE_MODEL = "non_le_audio_headset";
|
||||
private BluetoothDetailsProfilesController mController;
|
||||
private List<LocalBluetoothProfile> mConnectableProfiles;
|
||||
private PreferenceCategory mProfiles;
|
||||
private BluetoothFeatureProvider mFeatureProvider;
|
||||
|
||||
@Mock
|
||||
private LocalBluetoothManager mLocalManager;
|
||||
@Mock
|
||||
private LocalBluetoothProfileManager mProfileManager;
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager;
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mFeatureProvider = fakeFeatureFactory.getBluetoothFeatureProvider();
|
||||
|
||||
mProfiles = spy(new PreferenceCategory(mContext));
|
||||
when(mProfiles.getPreferenceManager()).thenReturn(mPreferenceManager);
|
||||
|
||||
mConnectableProfiles = new ArrayList<>();
|
||||
when(mLocalManager.getProfileManager()).thenReturn(mProfileManager);
|
||||
when(mLocalManager.getCachedDeviceManager()).thenReturn(mCachedBluetoothDeviceManager);
|
||||
when(mCachedBluetoothDeviceManager.getCachedDevicesCopy())
|
||||
.thenReturn(ImmutableList.of(mCachedDevice));
|
||||
when(mCachedDevice.getConnectableProfiles()).thenAnswer(invocation ->
|
||||
new ArrayList<>(mConnectableProfiles)
|
||||
);
|
||||
@@ -196,25 +218,26 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
return profile;
|
||||
}
|
||||
|
||||
/** Returns the list of SwitchPreference objects added to the screen - there should be one per
|
||||
* Bluetooth profile.
|
||||
/**
|
||||
* Returns the list of SwitchPreferenceCompat objects added to the screen - there should be one
|
||||
* per Bluetooth profile.
|
||||
*/
|
||||
private List<SwitchPreference> getProfileSwitches(boolean expectOnlyMConnectable) {
|
||||
private List<SwitchPreferenceCompat> getProfileSwitches(boolean expectOnlyMConnectable) {
|
||||
if (expectOnlyMConnectable) {
|
||||
assertThat(mConnectableProfiles).isNotEmpty();
|
||||
assertThat(mProfiles.getPreferenceCount() - 1).isEqualTo(mConnectableProfiles.size());
|
||||
}
|
||||
List<SwitchPreference> result = new ArrayList<>();
|
||||
List<SwitchPreferenceCompat> result = new ArrayList<>();
|
||||
for (int i = 0; i < mProfiles.getPreferenceCount(); i++) {
|
||||
final Preference preference = mProfiles.getPreference(i);
|
||||
if (preference instanceof SwitchPreference) {
|
||||
result.add((SwitchPreference) preference);
|
||||
if (preference instanceof SwitchPreferenceCompat) {
|
||||
result.add((SwitchPreferenceCompat) preference);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void verifyProfileSwitchTitles(List<SwitchPreference> switches) {
|
||||
private void verifyProfileSwitchTitles(List<SwitchPreferenceCompat> switches) {
|
||||
for (int i = 0; i < switches.size(); i++) {
|
||||
String expectedTitle =
|
||||
mContext.getString(mConnectableProfiles.get(i).getNameResource(mDevice));
|
||||
@@ -234,7 +257,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
addFakeProfile(com.android.settingslib.R.string.bluetooth_profile_a2dp, true);
|
||||
addFakeProfile(com.android.settingslib.R.string.bluetooth_profile_headset, false);
|
||||
showScreen(mController);
|
||||
List<SwitchPreference> switches = getProfileSwitches(true);
|
||||
List<SwitchPreferenceCompat> switches = getProfileSwitches(true);
|
||||
verifyProfileSwitchTitles(switches);
|
||||
assertThat(switches.get(0).isChecked()).isTrue();
|
||||
assertThat(switches.get(1).isChecked()).isFalse();
|
||||
@@ -260,8 +283,8 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
addFakeProfile(com.android.settingslib.R.string.bluetooth_profile_a2dp, true);
|
||||
addFakeProfile(com.android.settingslib.R.string.bluetooth_profile_headset, true);
|
||||
showScreen(mController);
|
||||
List<SwitchPreference> switches = getProfileSwitches(true);
|
||||
SwitchPreference pref = switches.get(0);
|
||||
List<SwitchPreferenceCompat> switches = getProfileSwitches(true);
|
||||
SwitchPreferenceCompat pref = switches.get(0);
|
||||
|
||||
// Clicking the pref should cause the profile to become not-preferred.
|
||||
assertThat(pref.isChecked()).isTrue();
|
||||
@@ -296,14 +319,16 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
PbapServerProfile psp = mock(PbapServerProfile.class);
|
||||
when(psp.getNameResource(mDevice))
|
||||
.thenReturn(com.android.settingslib.R.string.bluetooth_profile_pbap);
|
||||
when(psp.getSummaryResourceForDevice(mDevice))
|
||||
.thenReturn(R.string.bluetooth_profile_pbap_summary);
|
||||
when(psp.toString()).thenReturn(PbapServerProfile.NAME);
|
||||
when(psp.isProfileReady()).thenReturn(true);
|
||||
when(mProfileManager.getPbapProfile()).thenReturn(psp);
|
||||
|
||||
showScreen(mController);
|
||||
List<SwitchPreference> switches = getProfileSwitches(false);
|
||||
List<SwitchPreferenceCompat> switches = getProfileSwitches(false);
|
||||
assertThat(switches.size()).isEqualTo(1);
|
||||
SwitchPreference pref = switches.get(0);
|
||||
SwitchPreferenceCompat pref = switches.get(0);
|
||||
assertThat(pref.getTitle()).isEqualTo(
|
||||
mContext.getString(com.android.settingslib.R.string.bluetooth_profile_pbap));
|
||||
assertThat(pref.isChecked()).isTrue();
|
||||
@@ -321,14 +346,16 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
PbapServerProfile psp = mock(PbapServerProfile.class);
|
||||
when(psp.getNameResource(mDevice))
|
||||
.thenReturn(com.android.settingslib.R.string.bluetooth_profile_pbap);
|
||||
when(psp.getSummaryResourceForDevice(mDevice))
|
||||
.thenReturn(R.string.bluetooth_profile_pbap_summary);
|
||||
when(psp.toString()).thenReturn(PbapServerProfile.NAME);
|
||||
when(psp.isProfileReady()).thenReturn(true);
|
||||
when(mProfileManager.getPbapProfile()).thenReturn(psp);
|
||||
|
||||
showScreen(mController);
|
||||
List<SwitchPreference> switches = getProfileSwitches(false);
|
||||
List<SwitchPreferenceCompat> switches = getProfileSwitches(false);
|
||||
assertThat(switches.size()).isEqualTo(1);
|
||||
SwitchPreference pref = switches.get(0);
|
||||
SwitchPreferenceCompat pref = switches.get(0);
|
||||
assertThat(pref.getTitle()).isEqualTo(
|
||||
mContext.getString(com.android.settingslib.R.string.bluetooth_profile_pbap));
|
||||
assertThat(pref.isChecked()).isFalse();
|
||||
@@ -350,9 +377,9 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
when(mProfileManager.getProfileByName(eq(mapProfile.toString()))).thenReturn(mapProfile);
|
||||
mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_REJECTED);
|
||||
showScreen(mController);
|
||||
List<SwitchPreference> switches = getProfileSwitches(false);
|
||||
List<SwitchPreferenceCompat> switches = getProfileSwitches(false);
|
||||
assertThat(switches.size()).isEqualTo(1);
|
||||
SwitchPreference pref = switches.get(0);
|
||||
SwitchPreferenceCompat pref = switches.get(0);
|
||||
assertThat(pref.getTitle()).isEqualTo(
|
||||
mContext.getString(com.android.settingslib.R.string.bluetooth_profile_map));
|
||||
assertThat(pref.isChecked()).isFalse();
|
||||
@@ -379,8 +406,8 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
return profile;
|
||||
}
|
||||
|
||||
private SwitchPreference getHighQualityAudioPref() {
|
||||
return (SwitchPreference) mScreen.findPreference(
|
||||
private SwitchPreferenceCompat getHighQualityAudioPref() {
|
||||
return (SwitchPreferenceCompat) mScreen.findPreference(
|
||||
BluetoothDetailsProfilesController.HIGH_QUALITY_AUDIO_PREF_TAG);
|
||||
}
|
||||
|
||||
@@ -389,7 +416,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
setupDevice(makeDefaultDeviceConfig());
|
||||
addMockA2dpProfile(true, true, true);
|
||||
showScreen(mController);
|
||||
SwitchPreference pref = getHighQualityAudioPref();
|
||||
SwitchPreferenceCompat pref = getHighQualityAudioPref();
|
||||
assertThat(pref.getKey()).isEqualTo(
|
||||
BluetoothDetailsProfilesController.HIGH_QUALITY_AUDIO_PREF_TAG);
|
||||
|
||||
@@ -407,7 +434,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
addMockA2dpProfile(true, false, false);
|
||||
showScreen(mController);
|
||||
assertThat(mProfiles.getPreferenceCount()).isEqualTo(2);
|
||||
SwitchPreference pref = (SwitchPreference) mProfiles.getPreference(0);
|
||||
SwitchPreferenceCompat pref = (SwitchPreferenceCompat) mProfiles.getPreference(0);
|
||||
assertThat(pref.getKey())
|
||||
.isNotEqualTo(BluetoothDetailsProfilesController.HIGH_QUALITY_AUDIO_PREF_TAG);
|
||||
assertThat(pref.getTitle()).isEqualTo(
|
||||
@@ -420,7 +447,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
addMockA2dpProfile(true, true, true);
|
||||
when(mCachedDevice.isBusy()).thenReturn(true);
|
||||
showScreen(mController);
|
||||
SwitchPreference pref = getHighQualityAudioPref();
|
||||
SwitchPreferenceCompat pref = getHighQualityAudioPref();
|
||||
assertThat(pref.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@@ -433,14 +460,14 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
|
||||
// Disabling media audio should cause the high quality audio switch to disappear, but not
|
||||
// the regular audio one.
|
||||
SwitchPreference audioPref =
|
||||
(SwitchPreference) mScreen.findPreference(audioProfile.toString());
|
||||
SwitchPreferenceCompat audioPref =
|
||||
(SwitchPreferenceCompat) mScreen.findPreference(audioProfile.toString());
|
||||
audioPref.performClick();
|
||||
verify(audioProfile).setEnabled(mDevice, false);
|
||||
when(audioProfile.isEnabled(mDevice)).thenReturn(false);
|
||||
mController.onDeviceAttributesChanged();
|
||||
assertThat(audioPref.isVisible()).isTrue();
|
||||
SwitchPreference highQualityAudioPref = getHighQualityAudioPref();
|
||||
SwitchPreferenceCompat highQualityAudioPref = getHighQualityAudioPref();
|
||||
assertThat(highQualityAudioPref.isVisible()).isFalse();
|
||||
|
||||
// And re-enabling media audio should make high quality switch to reappear.
|
||||
@@ -457,8 +484,8 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
setupDevice(makeDefaultDeviceConfig());
|
||||
A2dpProfile audioProfile = addMockA2dpProfile(false, true, true);
|
||||
showScreen(mController);
|
||||
SwitchPreference audioPref = mScreen.findPreference(audioProfile.toString());
|
||||
SwitchPreference highQualityAudioPref = getHighQualityAudioPref();
|
||||
SwitchPreferenceCompat audioPref = mScreen.findPreference(audioProfile.toString());
|
||||
SwitchPreferenceCompat highQualityAudioPref = getHighQualityAudioPref();
|
||||
assertThat(audioPref).isNotNull();
|
||||
assertThat(audioPref.isChecked()).isFalse();
|
||||
assertThat(highQualityAudioPref).isNotNull();
|
||||
@@ -489,4 +516,46 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
||||
assertThat(mController.isModelNameInAllowList(null)).isFalse();
|
||||
assertThat(mController.isModelNameInAllowList(NON_LE_DEVICE_MODEL)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prefKeyInBlockingList_hideToggle() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_BLUETOOTH_PROFILE_TOGGLE_VISIBILITY_CHECKER);
|
||||
setupDevice(makeDefaultDeviceConfig());
|
||||
|
||||
LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
|
||||
when(leAudioProfile.getNameResource(mDevice))
|
||||
.thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
|
||||
when(leAudioProfile.isProfileReady()).thenReturn(true);
|
||||
when(leAudioProfile.toString()).thenReturn("LE_AUDIO");
|
||||
when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
|
||||
when(mFeatureProvider.getInvisibleProfilePreferenceKeys(any(), any()))
|
||||
.thenReturn(ImmutableSet.of("LE_AUDIO"));
|
||||
mConnectableProfiles.add(leAudioProfile);
|
||||
|
||||
showScreen(mController);
|
||||
|
||||
List<SwitchPreferenceCompat> switches = getProfileSwitches(false);
|
||||
assertThat(switches.get(0).isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prefKeyNotInBlockingList_showToggle() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_BLUETOOTH_PROFILE_TOGGLE_VISIBILITY_CHECKER);
|
||||
setupDevice(makeDefaultDeviceConfig());
|
||||
|
||||
LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
|
||||
when(leAudioProfile.getNameResource(mDevice))
|
||||
.thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
|
||||
when(leAudioProfile.isProfileReady()).thenReturn(true);
|
||||
when(leAudioProfile.toString()).thenReturn("LE_AUDIO");
|
||||
when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
|
||||
when(mFeatureProvider.getInvisibleProfilePreferenceKeys(any(), any()))
|
||||
.thenReturn(ImmutableSet.of("A2DP"));
|
||||
mConnectableProfiles.add(leAudioProfile);
|
||||
|
||||
showScreen(mController);
|
||||
|
||||
List<SwitchPreferenceCompat> switches = getProfileSwitches(false);
|
||||
assertThat(switches.get(0).isVisible()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.shadows.ShadowLooper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -120,6 +121,7 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails
|
||||
when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
|
||||
|
||||
mController.refresh();
|
||||
ShadowLooper.idleMainLooper();
|
||||
|
||||
assertThat(mSpatialAudioPref.isChecked()).isTrue();
|
||||
}
|
||||
@@ -130,6 +132,7 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails
|
||||
when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
|
||||
|
||||
mController.refresh();
|
||||
ShadowLooper.idleMainLooper();
|
||||
|
||||
assertThat(mSpatialAudioPref.isChecked()).isFalse();
|
||||
}
|
||||
@@ -142,6 +145,7 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails
|
||||
when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true);
|
||||
|
||||
mController.refresh();
|
||||
ShadowLooper.idleMainLooper();
|
||||
|
||||
assertThat(mHeadTrackingPref.isVisible()).isTrue();
|
||||
}
|
||||
@@ -156,6 +160,7 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails
|
||||
when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(false);
|
||||
|
||||
mController.refresh();
|
||||
ShadowLooper.idleMainLooper();
|
||||
|
||||
verify(mProfilesContainer).removePreference(mHeadTrackingPref);
|
||||
}
|
||||
@@ -166,6 +171,7 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails
|
||||
when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
|
||||
|
||||
mController.refresh();
|
||||
ShadowLooper.idleMainLooper();
|
||||
|
||||
verify(mProfilesContainer).removePreference(mHeadTrackingPref);
|
||||
}
|
||||
@@ -181,6 +187,7 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails
|
||||
when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(true);
|
||||
|
||||
mController.refresh();
|
||||
ShadowLooper.idleMainLooper();
|
||||
|
||||
assertThat(mHeadTrackingPref.isChecked()).isTrue();
|
||||
}
|
||||
@@ -196,6 +203,7 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails
|
||||
when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(false);
|
||||
|
||||
mController.refresh();
|
||||
ShadowLooper.idleMainLooper();
|
||||
|
||||
assertThat(mHeadTrackingPref.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.settings.bluetooth;
|
||||
|
||||
import static android.bluetooth.BluetoothDevice.BOND_NONE;
|
||||
|
||||
import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceControlsController.KEY_DEVICE_CONTROLS_GENERAL_GROUP;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -29,8 +31,10 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.companion.CompanionDeviceManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserManager;
|
||||
@@ -49,6 +53,8 @@ import com.android.settings.R;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@@ -65,6 +71,8 @@ import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.fakes.RoboMenu;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
com.android.settings.testutils.shadow.ShadowUserManager.class,
|
||||
@@ -216,6 +224,38 @@ public class BluetoothDeviceDetailsFragmentTest {
|
||||
verify(mFragment).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createPreferenceControllers_launchFromHAPage_deviceControllerNotExist() {
|
||||
BluetoothDeviceDetailsFragment fragment = setupFragment();
|
||||
Intent intent = fragment.getActivity().getIntent();
|
||||
intent.putExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY,
|
||||
SettingsEnums.ACCESSIBILITY_HEARING_AID_SETTINGS);
|
||||
fragment.onAttach(mContext);
|
||||
|
||||
List<AbstractPreferenceController> controllerList = fragment.createPreferenceControllers(
|
||||
mContext);
|
||||
|
||||
assertThat(controllerList.stream()
|
||||
.anyMatch(controller -> controller.getPreferenceKey().equals(
|
||||
KEY_DEVICE_CONTROLS_GENERAL_GROUP))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createPreferenceControllers_notLaunchFromHAPage_deviceControllerExist() {
|
||||
BluetoothDeviceDetailsFragment fragment = setupFragment();
|
||||
Intent intent = fragment.getActivity().getIntent();
|
||||
intent.putExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY,
|
||||
SettingsEnums.PAGE_UNKNOWN);
|
||||
fragment.onAttach(mContext);
|
||||
|
||||
List<AbstractPreferenceController> controllerList = fragment.createPreferenceControllers(
|
||||
mContext);
|
||||
|
||||
assertThat(controllerList.stream()
|
||||
.anyMatch(controller -> controller.getPreferenceKey().equals(
|
||||
KEY_DEVICE_CONTROLS_GENERAL_GROUP))).isTrue();
|
||||
}
|
||||
|
||||
private InputDevice createInputDeviceWithMatchingBluetoothAddress() {
|
||||
doReturn(new int[]{0}).when(mInputManager).getInputDeviceIds();
|
||||
InputDevice device = mock(InputDevice.class);
|
||||
|
||||
@@ -33,6 +33,8 @@ public class BluetoothNameDialogFragmentTest {
|
||||
private TestBluetoothNameDialogFragment mBluetoothNameDialogFragment;
|
||||
private TextView mTextView;
|
||||
|
||||
private static final String NAME_FOR_TEST = "test_device_name";
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -51,12 +53,24 @@ public class BluetoothNameDialogFragmentTest {
|
||||
null)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onEditorAction_ImeNull_setsDeviceName() {
|
||||
|
||||
|
||||
mTextView.setText(NAME_FOR_TEST);
|
||||
assertThat(
|
||||
mBluetoothNameDialogFragment.onEditorAction(mTextView, EditorInfo.IME_NULL,
|
||||
null)).isTrue();
|
||||
assertThat(mBluetoothNameDialogFragment.getDeviceName()).isEqualTo(NAME_FOR_TEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test fragment for {@link BluetoothNameDialogFragment} to test common methods
|
||||
*/
|
||||
public static class TestBluetoothNameDialogFragment extends BluetoothNameDialogFragment {
|
||||
|
||||
private String mName;
|
||||
|
||||
@Override
|
||||
protected int getDialogTitle() {
|
||||
return 0;
|
||||
@@ -64,12 +78,12 @@ public class BluetoothNameDialogFragmentTest {
|
||||
|
||||
@Override
|
||||
protected String getDeviceName() {
|
||||
return null;
|
||||
return mName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setDeviceName(String deviceName) {
|
||||
|
||||
mName = deviceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,8 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -28,8 +30,13 @@ import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.AudioManager;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.settings.connecteddevice.DevicePreferenceCallback;
|
||||
@@ -37,9 +44,12 @@ import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.testutils.shadow.ShadowAudioManager;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowCachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.flags.Flags;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -58,6 +68,10 @@ import java.util.Collection;
|
||||
public class ConnectedBluetoothDeviceUpdaterTest {
|
||||
|
||||
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
|
||||
private static final String FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name";
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
@Mock
|
||||
private DashboardFragment mDashboardFragment;
|
||||
@@ -69,6 +83,8 @@ public class ConnectedBluetoothDeviceUpdaterTest {
|
||||
private BluetoothDevice mBluetoothDevice;
|
||||
@Mock
|
||||
private Drawable mDrawable;
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
|
||||
private Context mContext;
|
||||
private ConnectedBluetoothDeviceUpdater mBluetoothDeviceUpdater;
|
||||
@@ -82,7 +98,7 @@ public class ConnectedBluetoothDeviceUpdaterTest {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
Pair<Drawable, String> pairs = new Pair<>(mDrawable, "fake_device");
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mAudioManager = mContext.getSystemService(AudioManager.class);
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
@@ -92,6 +108,7 @@ public class ConnectedBluetoothDeviceUpdaterTest {
|
||||
mCachedDevices = new ArrayList<>();
|
||||
mCachedDevices.add(mCachedBluetoothDevice);
|
||||
|
||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
when(mCachedBluetoothDevice.getAddress()).thenReturn(MAC_ADDRESS);
|
||||
when(mCachedBluetoothDevice.getDrawableWithDescription()).thenReturn(pairs);
|
||||
@@ -320,4 +337,97 @@ public class ConnectedBluetoothDeviceUpdaterTest {
|
||||
|
||||
assertThat(btPreference.shouldHideSecondTarget()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_notExclusiveManagedDevice_addDevice() {
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater
|
||||
.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
null);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_notAllowedExclusiveManagedDevice_addDevice() {
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater
|
||||
.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME.getBytes());
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_existingExclusivelyManagedDeviceWithPackageInstalled_removePreference()
|
||||
throws Exception {
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater
|
||||
.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
|
||||
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_newExclusivelyManagedDeviceWithPackageInstalled_doNotAddPreference()
|
||||
throws Exception {
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater
|
||||
.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
|
||||
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_exclusivelyManagedDeviceWithoutPackageInstalled_addDevice()
|
||||
throws Exception {
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater
|
||||
.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getPackageInfo(
|
||||
exclusiveManagerName, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.settings.bluetooth;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -28,17 +29,26 @@ import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.settings.connecteddevice.DevicePreferenceCallback;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.flags.Flags;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -56,6 +66,10 @@ import java.util.List;
|
||||
public class SavedBluetoothDeviceUpdaterTest {
|
||||
|
||||
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
|
||||
private static final String FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name";
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
@Mock
|
||||
private DashboardFragment mDashboardFragment;
|
||||
@@ -73,6 +87,8 @@ public class SavedBluetoothDeviceUpdaterTest {
|
||||
private LocalBluetoothManager mBluetoothManager;
|
||||
@Mock
|
||||
private Drawable mDrawable;
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
|
||||
private Context mContext;
|
||||
private SavedBluetoothDeviceUpdater mBluetoothDeviceUpdater;
|
||||
@@ -84,12 +100,13 @@ public class SavedBluetoothDeviceUpdaterTest {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
Pair<Drawable, String> pairs = new Pair<>(mDrawable, "fake_device");
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
doReturn(mContext).when(mDashboardFragment).getContext();
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
when(mCachedBluetoothDevice.getAddress()).thenReturn(MAC_ADDRESS);
|
||||
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mCachedBluetoothDevice.getDrawableWithDescription()).thenReturn(pairs);
|
||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
|
||||
mBluetoothDeviceUpdater = spy(new SavedBluetoothDeviceUpdater(mContext,
|
||||
mDevicePreferenceCallback, false, /* metricsCategory= */ 0));
|
||||
@@ -103,10 +120,10 @@ public class SavedBluetoothDeviceUpdaterTest {
|
||||
mCachedDevices.add(mCachedBluetoothDevice);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_filterMatch_addPreference() {
|
||||
doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState();
|
||||
doReturn(false).when(mBluetoothDevice).isConnected();
|
||||
@@ -118,6 +135,7 @@ public class SavedBluetoothDeviceUpdaterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_filterNotMatch_removePreference() {
|
||||
doReturn(BluetoothDevice.BOND_NONE).when(mBluetoothDevice).getBondState();
|
||||
doReturn(true).when(mBluetoothDevice).isConnected();
|
||||
@@ -298,4 +316,125 @@ public class SavedBluetoothDeviceUpdaterTest {
|
||||
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_notExclusivelyManagedDevice_addDevice() {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
|
||||
cachedDevices.add(mCachedBluetoothDevice);
|
||||
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
|
||||
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBluetoothDevice.isConnected()).thenReturn(false);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
null);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_notAllowedExclusivelyManagedDevice_addDevice() {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
|
||||
cachedDevices.add(mCachedBluetoothDevice);
|
||||
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
|
||||
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBluetoothDevice.isConnected()).thenReturn(false);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME.getBytes());
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_existingExclusivelyManagedDeviceWithPackageInstalled_removePreference()
|
||||
throws Exception {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
|
||||
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBluetoothDevice.isConnected()).thenReturn(false);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
|
||||
doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
|
||||
mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
|
||||
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_newExclusivelyManagedDeviceWithPackageInstalled_doNotAddPreference()
|
||||
throws Exception {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
cachedDevices.add(mCachedBluetoothDevice);
|
||||
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
|
||||
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBluetoothDevice.isConnected()).thenReturn(false);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
|
||||
doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
|
||||
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_exclusivelyManagedDeviceWithoutPackageInstalled_addDevice()
|
||||
throws Exception {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
cachedDevices.add(mCachedBluetoothDevice);
|
||||
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
|
||||
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBluetoothDevice.isConnected()).thenReturn(false);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
|
||||
doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getPackageInfo(
|
||||
exclusiveManagerName, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -31,6 +32,7 @@ import android.content.pm.PackageManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
@@ -40,9 +42,8 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowApplicationPackageManager;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
@@ -50,13 +51,13 @@ import org.robolectric.util.ReflectionHelpers;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = ShadowApplicationPackageManager.class)
|
||||
public class AddDevicePreferenceControllerTest {
|
||||
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
@Mock
|
||||
private BluetoothAdapter mBluetoothAdapter;
|
||||
|
||||
private Context mContext;
|
||||
@Spy
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private AddDevicePreferenceController mAddDevicePreferenceController;
|
||||
private RestrictedPreference mAddDevicePreference;
|
||||
private ShadowApplicationPackageManager mPackageManager;
|
||||
@@ -66,8 +67,7 @@ public class AddDevicePreferenceControllerTest {
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mPackageManager = (ShadowApplicationPackageManager) Shadows.shadowOf(
|
||||
mPackageManager = (ShadowApplicationPackageManager) shadowOf(
|
||||
mContext.getPackageManager());
|
||||
mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, true);
|
||||
|
||||
|
||||
@@ -22,27 +22,23 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothLeBroadcastAssistant;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.AudioManager;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
@@ -51,19 +47,16 @@ import androidx.preference.PreferenceScreen;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.bluetooth.AvailableMediaBluetoothDeviceUpdater;
|
||||
import com.android.settings.bluetooth.Utils;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
||||
import com.android.settings.testutils.shadow.ShadowAudioManager;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.BluetoothCallback;
|
||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.HearingAidInfo;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -76,16 +69,12 @@ import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/** Tests for {@link AvailableMediaDeviceGroupController}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowAudioManager.class,
|
||||
ShadowBluetoothAdapter.class,
|
||||
ShadowBluetoothUtils.class,
|
||||
ShadowAlertDialogCompat.class,
|
||||
})
|
||||
@@ -105,9 +94,7 @@ public class AvailableMediaDeviceGroupControllerTest {
|
||||
@Mock private PackageManager mPackageManager;
|
||||
@Mock private BluetoothEventManager mEventManager;
|
||||
@Mock private LocalBluetoothManager mLocalBluetoothManager;
|
||||
@Mock private LocalBluetoothProfileManager mLocalBtProfileManager;
|
||||
@Mock private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
|
||||
@Mock private CachedBluetoothDevice mCachedBluetoothDevice;
|
||||
|
||||
private PreferenceGroup mPreferenceGroup;
|
||||
@@ -115,13 +102,16 @@ public class AvailableMediaDeviceGroupControllerTest {
|
||||
private Preference mPreference;
|
||||
private AvailableMediaDeviceGroupController mAvailableMediaDeviceGroupController;
|
||||
private AudioManager mAudioManager;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private Lifecycle mLifecycle;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mLifecycleOwner = () -> mLifecycle;
|
||||
mLifecycle = new Lifecycle(mLifecycleOwner);
|
||||
mPreference = new Preference(mContext);
|
||||
mPreference.setKey(PREFERENCE_KEY_1);
|
||||
mPreferenceGroup = spy(new PreferenceScreen(mContext, null));
|
||||
@@ -130,24 +120,17 @@ public class AvailableMediaDeviceGroupControllerTest {
|
||||
doReturn(mPackageManager).when(mContext).getPackageManager();
|
||||
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
|
||||
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_NOT_SUPPORTED);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_NOT_SUPPORTED);
|
||||
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
|
||||
mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
|
||||
mAudioManager = mContext.getSystemService(AudioManager.class);
|
||||
doReturn(mEventManager).when(mLocalBluetoothManager).getEventManager();
|
||||
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBtProfileManager);
|
||||
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
|
||||
when(mCachedDeviceManager.findDevice(any(BluetoothDevice.class)))
|
||||
.thenReturn(mCachedBluetoothDevice);
|
||||
when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS);
|
||||
|
||||
mAvailableMediaDeviceGroupController =
|
||||
spy(new AvailableMediaDeviceGroupController(mContext));
|
||||
spy(new AvailableMediaDeviceGroupController(mContext, null, mLifecycle));
|
||||
mAvailableMediaDeviceGroupController.setBluetoothDeviceUpdater(
|
||||
mAvailableMediaBluetoothDeviceUpdater);
|
||||
mAvailableMediaDeviceGroupController.setFragmentManager(
|
||||
@@ -197,7 +180,7 @@ public class AvailableMediaDeviceGroupControllerTest {
|
||||
@Test
|
||||
public void testRegister() {
|
||||
// register the callback in onStart()
|
||||
mAvailableMediaDeviceGroupController.onStart();
|
||||
mAvailableMediaDeviceGroupController.onStart(mLifecycleOwner);
|
||||
|
||||
verify(mAvailableMediaBluetoothDeviceUpdater).registerCallback();
|
||||
verify(mLocalBluetoothManager.getEventManager())
|
||||
@@ -205,36 +188,15 @@ public class AvailableMediaDeviceGroupControllerTest {
|
||||
verify(mAvailableMediaBluetoothDeviceUpdater).refreshPreference();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void testRegister_audioSharingOn() {
|
||||
setUpBroadcast();
|
||||
// register the callback in onStart()
|
||||
mAvailableMediaDeviceGroupController.onStart();
|
||||
verify(mAssistant)
|
||||
.registerServiceCallBack(
|
||||
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregister() {
|
||||
// unregister the callback in onStop()
|
||||
mAvailableMediaDeviceGroupController.onStop();
|
||||
mAvailableMediaDeviceGroupController.onStop(mLifecycleOwner);
|
||||
verify(mAvailableMediaBluetoothDeviceUpdater).unregisterCallback();
|
||||
verify(mLocalBluetoothManager.getEventManager())
|
||||
.unregisterCallback(any(BluetoothCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void testUnregister_audioSharingOn() {
|
||||
setUpBroadcast();
|
||||
// unregister the callback in onStop()
|
||||
mAvailableMediaDeviceGroupController.onStop();
|
||||
verify(mAssistant)
|
||||
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus_noBluetoothFeature_returnUnSupported() {
|
||||
doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
|
||||
@@ -274,7 +236,7 @@ public class AvailableMediaDeviceGroupControllerTest {
|
||||
mAvailableMediaDeviceGroupController.mLocalBluetoothManager = null;
|
||||
|
||||
// Shouldn't crash
|
||||
mAvailableMediaDeviceGroupController.onStart();
|
||||
mAvailableMediaDeviceGroupController.onStart(mLifecycleOwner);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -282,7 +244,7 @@ public class AvailableMediaDeviceGroupControllerTest {
|
||||
mAvailableMediaDeviceGroupController.mLocalBluetoothManager = null;
|
||||
|
||||
// Shouldn't crash
|
||||
mAvailableMediaDeviceGroupController.onStop();
|
||||
mAvailableMediaDeviceGroupController.onStop(mLifecycleOwner);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -300,19 +262,4 @@ public class AvailableMediaDeviceGroupControllerTest {
|
||||
final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog.isShowing()).isTrue();
|
||||
}
|
||||
|
||||
private void setUpBroadcast() {
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
when(mLocalBtProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
|
||||
doNothing()
|
||||
.when(mAssistant)
|
||||
.registerServiceCallBack(
|
||||
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
|
||||
doNothing()
|
||||
.when(mAssistant)
|
||||
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,22 +20,25 @@ import static com.android.settings.connecteddevice.ConnectedDeviceDashboardFragm
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.connecteddevice.fastpair.FastPairDeviceUpdater;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerListHelper;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.slices.SlicePreferenceController;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowConnectivityManager;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
@@ -53,20 +56,23 @@ import org.robolectric.annotation.Config;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowUserManager.class,
|
||||
ShadowConnectivityManager.class, ShadowBluetoothAdapter.class})
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowUserManager.class,
|
||||
ShadowConnectivityManager.class,
|
||||
ShadowBluetoothAdapter.class
|
||||
})
|
||||
public class ConnectedDeviceDashboardFragmentTest {
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
private static final String KEY_NEARBY_DEVICES = "bt_nearby_slice";
|
||||
private static final String KEY_DISCOVERABLE_FOOTER = "discoverable_footer";
|
||||
private static final String KEY_SAVED_DEVICE_SEE_ALL = "previously_connected_devices_see_all";
|
||||
private static final String KEY_FAST_PAIR_DEVICE_SEE_ALL = "fast_pair_devices_see_all";
|
||||
private static final String KEY_ADD_BT_DEVICES = "add_bt_devices";
|
||||
private static final String KEY_AUDIO_SHARING_DEVICE_LIST = "audio_sharing_device_list";
|
||||
private static final String KEY_AUDIO_SHARING_SETTINGS =
|
||||
"connected_device_audio_sharing_settings";
|
||||
private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
|
||||
private static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui";
|
||||
private static final String SLICE_ACTION = "com.android.settings.SEARCH_RESULT_TRAMPOLINE";
|
||||
@@ -74,8 +80,11 @@ public class ConnectedDeviceDashboardFragmentTest {
|
||||
private static final String TEST_ACTION = "com.testapp.settings.ACTION_START";
|
||||
|
||||
@Mock private PackageManager mPackageManager;
|
||||
@Mock private FastPairDeviceUpdater mFastPairDeviceUpdater;
|
||||
private Context mContext;
|
||||
private ConnectedDeviceDashboardFragment mFragment;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private AvailableMediaDeviceGroupController mMediaDeviceGroupController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -83,6 +92,22 @@ public class ConnectedDeviceDashboardFragmentTest {
|
||||
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mFragment = new ConnectedDeviceDashboardFragment();
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION);
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
when(mFeatureFactory
|
||||
.getFastPairFeatureProvider()
|
||||
.getFastPairDeviceUpdater(
|
||||
any(Context.class), any(DevicePreferenceCallback.class)))
|
||||
.thenReturn(mFastPairDeviceUpdater);
|
||||
when(mFeatureFactory
|
||||
.getAudioSharingFeatureProvider()
|
||||
.createAudioSharingDevicePreferenceController(mContext, null, null))
|
||||
.thenReturn(null);
|
||||
mMediaDeviceGroupController = new AvailableMediaDeviceGroupController(mContext, null, null);
|
||||
when(mFeatureFactory
|
||||
.getAudioSharingFeatureProvider()
|
||||
.createAvailableMediaDeviceGroupController(mContext, null, null))
|
||||
.thenReturn(mMediaDeviceGroupController);
|
||||
doReturn(mPackageManager).when(mContext).getPackageManager();
|
||||
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
|
||||
}
|
||||
@@ -98,7 +123,6 @@ public class ConnectedDeviceDashboardFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void nonIndexableKeys_existInXmlLayout() {
|
||||
final List<String> niks =
|
||||
ConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
|
||||
@@ -111,27 +135,7 @@ public class ConnectedDeviceDashboardFragmentTest {
|
||||
KEY_NEARBY_DEVICES,
|
||||
KEY_DISCOVERABLE_FOOTER,
|
||||
KEY_SAVED_DEVICE_SEE_ALL,
|
||||
KEY_FAST_PAIR_DEVICE_SEE_ALL,
|
||||
KEY_AUDIO_SHARING_SETTINGS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void nonIndexableKeys_existInXmlLayout_flagOff() {
|
||||
final List<String> niks =
|
||||
ConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
|
||||
mContext);
|
||||
|
||||
assertThat(niks)
|
||||
.containsExactly(
|
||||
KEY_CONNECTED_DEVICES,
|
||||
KEY_AVAILABLE_DEVICES,
|
||||
KEY_NEARBY_DEVICES,
|
||||
KEY_DISCOVERABLE_FOOTER,
|
||||
KEY_SAVED_DEVICE_SEE_ALL,
|
||||
KEY_FAST_PAIR_DEVICE_SEE_ALL,
|
||||
KEY_AUDIO_SHARING_DEVICE_LIST,
|
||||
KEY_AUDIO_SHARING_SETTINGS);
|
||||
KEY_FAST_PAIR_DEVICE_SEE_ALL);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -160,10 +164,12 @@ public class ConnectedDeviceDashboardFragmentTest {
|
||||
PreferenceControllerListHelper.getPreferenceControllersFromXml(
|
||||
mContext, R.xml.connected_devices);
|
||||
|
||||
assertThat(controllers
|
||||
.stream()
|
||||
.filter(controller -> controller instanceof SlicePreferenceController)
|
||||
.count())
|
||||
assertThat(
|
||||
controllers.stream()
|
||||
.filter(
|
||||
controller ->
|
||||
controller instanceof SlicePreferenceController)
|
||||
.count())
|
||||
.isEqualTo(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,14 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
@@ -42,11 +47,14 @@ import com.android.settings.bluetooth.BluetoothDevicePreference;
|
||||
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
|
||||
import com.android.settings.connecteddevice.dock.DockUpdater;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.widget.SingleTargetGearPreference;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -70,6 +78,9 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
|
||||
private static final String FAKE_ADDRESS_4 = "AA:AA:AA:AA:AA:04";
|
||||
private static final String FAKE_ADDRESS_5 = "AA:AA:AA:AA:AA:05";
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
@Mock
|
||||
private DashboardFragment mDashboardFragment;
|
||||
@Mock
|
||||
@@ -105,6 +116,9 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
|
||||
@Mock
|
||||
private Drawable mDrawable;
|
||||
|
||||
@Mock private BluetoothManager mBluetoothManager;
|
||||
@Mock private BluetoothAdapter mBluetoothAdapter;
|
||||
|
||||
private Context mContext;
|
||||
private PreviouslyConnectedDevicePreferenceController mPreConnectedDeviceController;
|
||||
private PreferenceGroup mPreferenceGroup;
|
||||
@@ -117,10 +131,8 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
doReturn(mContext).when(mDashboardFragment).getContext();
|
||||
doReturn(mPackageManager).when(mContext).getPackageManager();
|
||||
mPreConnectedDeviceController =
|
||||
new PreviouslyConnectedDevicePreferenceController(mContext, KEY);
|
||||
mPreConnectedDeviceController.setBluetoothDeviceUpdater(mBluetoothDeviceUpdater);
|
||||
mPreConnectedDeviceController.setSavedDockUpdater(mDockUpdater);
|
||||
when(mContext.getSystemService(BluetoothManager.class)).thenReturn(mBluetoothManager);
|
||||
when(mBluetoothManager.getAdapter()).thenReturn(mBluetoothAdapter);
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
|
||||
when(mCachedDevice1.getDevice()).thenReturn(mBluetoothDevice1);
|
||||
@@ -145,7 +157,13 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
|
||||
mMostRecentlyConnectedDevices.add(mBluetoothDevice4);
|
||||
mMostRecentlyConnectedDevices.add(mBluetoothDevice3);
|
||||
mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(mMostRecentlyConnectedDevices);
|
||||
when(mBluetoothAdapter.getMostRecentlyConnectedDevices())
|
||||
.thenReturn(mMostRecentlyConnectedDevices);
|
||||
|
||||
mPreConnectedDeviceController =
|
||||
new PreviouslyConnectedDevicePreferenceController(mContext, KEY);
|
||||
mPreConnectedDeviceController.setBluetoothDeviceUpdater(mBluetoothDeviceUpdater);
|
||||
mPreConnectedDeviceController.setSavedDockUpdater(mDockUpdater);
|
||||
mPreferenceGroup = spy(new PreferenceCategory(mContext));
|
||||
doReturn(mPreferenceManager).when(mPreferenceGroup).getPreferenceManager();
|
||||
mPreferenceGroup.setVisible(false);
|
||||
@@ -205,6 +223,7 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
|
||||
AVAILABLE);
|
||||
}
|
||||
|
||||
@Ignore("b/322712259")
|
||||
@Test
|
||||
public void onDeviceAdded_addDevicePreference_displayIt() {
|
||||
final BluetoothDevicePreference preference1 = new BluetoothDevicePreference(
|
||||
@@ -215,6 +234,7 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Ignore("b/322712259")
|
||||
@Test
|
||||
public void onDeviceAdded_addDockDevicePreference_displayIt() {
|
||||
final SingleTargetGearPreference dockPreference = new SingleTargetGearPreference(
|
||||
@@ -225,6 +245,7 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Ignore("b/322712259")
|
||||
@Test
|
||||
public void onDeviceAdded_addFourDevicePreference_onlyDisplayThree() {
|
||||
final BluetoothDevicePreference preference1 = new BluetoothDevicePreference(
|
||||
@@ -249,6 +270,7 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_SAVED_DEVICES_ORDER_BY_RECENCY)
|
||||
public void onDeviceAdded_addPreferenceNotExistInRecentlyDevices_noCrash() {
|
||||
final BluetoothDevicePreference preference = new BluetoothDevicePreference(
|
||||
mContext, mCachedDevice5, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
@@ -259,6 +281,18 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SAVED_DEVICES_ORDER_BY_RECENCY)
|
||||
public void onDeviceAdded_addPreferenceNotExistInRecentlyDevices_doNothing() {
|
||||
final BluetoothDevicePreference preference = new BluetoothDevicePreference(
|
||||
mContext, mCachedDevice5, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
|
||||
mPreConnectedDeviceController.onDeviceAdded(preference);
|
||||
|
||||
// 1 see all preference
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceRemoved_removeLastDevice_showSeeAllPreference() {
|
||||
final BluetoothDevicePreference preference1 = new BluetoothDevicePreference(
|
||||
@@ -277,6 +311,7 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
|
||||
@Test
|
||||
public void updatePreferenceVisibility_bluetoothIsEnable_shouldShowCorrectText() {
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
mPreConnectedDeviceController.updatePreferenceVisibility();
|
||||
|
||||
verify(mSeeAllPreference).setSummary("");
|
||||
@@ -285,9 +320,78 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
|
||||
@Test
|
||||
public void updatePreferenceVisibility_bluetoothIsDisable_shouldShowCorrectText() {
|
||||
mShadowBluetoothAdapter.setEnabled(false);
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(false);
|
||||
mPreConnectedDeviceController.updatePreferenceVisibility();
|
||||
|
||||
verify(mSeeAllPreference).setSummary(
|
||||
mContext.getString(R.string.connected_device_see_all_summary));
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SAVED_DEVICES_ORDER_BY_RECENCY)
|
||||
public void updatePreferenceGroup_bluetoothIsEnable_shouldOrderByMostRecentlyConnected() {
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
final BluetoothDevicePreference preference4 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice4,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
final BluetoothDevicePreference preference3 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice3,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
final BluetoothDevicePreference preference2 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice2,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
mPreConnectedDeviceController.onDeviceAdded(preference4);
|
||||
mPreConnectedDeviceController.onDeviceAdded(preference3);
|
||||
mPreConnectedDeviceController.onDeviceAdded(preference2);
|
||||
|
||||
mPreConnectedDeviceController.updatePreferenceGroup();
|
||||
|
||||
// Refer to the order of {@link #mMostRecentlyConnectedDevices}, the first one is see all
|
||||
// preference
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(4);
|
||||
assertThat(preference2.getOrder()).isEqualTo(0);
|
||||
assertThat(preference4.getOrder()).isEqualTo(1);
|
||||
assertThat(preference3.getOrder()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SAVED_DEVICES_ORDER_BY_RECENCY)
|
||||
public void updatePreferenceGroup_bluetoothIsDisable_shouldShowOnlySeeAllPreference() {
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(false);
|
||||
final BluetoothDevicePreference preference4 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice4,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
final BluetoothDevicePreference preference3 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice3,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
final BluetoothDevicePreference preference2 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice2,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
mPreConnectedDeviceController.onDeviceAdded(preference4);
|
||||
mPreConnectedDeviceController.onDeviceAdded(preference3);
|
||||
mPreConnectedDeviceController.onDeviceAdded(preference2);
|
||||
|
||||
mPreConnectedDeviceController.updatePreferenceGroup();
|
||||
|
||||
// 1 see all preference
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,29 +25,52 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.android.settings.bluetooth.BluetoothDevicePreference;
|
||||
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
|
||||
import com.android.settings.connecteddevice.dock.DockUpdater;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class SavedDeviceGroupControllerTest {
|
||||
|
||||
private static final String FAKE_ADDRESS_1 = "AA:AA:AA:AA:AA:01";
|
||||
private static final String FAKE_ADDRESS_2 = "AA:AA:AA:AA:AA:02";
|
||||
private static final String FAKE_ADDRESS_3 = "AA:AA:AA:AA:AA:03";
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
@Mock
|
||||
private DashboardFragment mDashboardFragment;
|
||||
@Mock
|
||||
@@ -56,23 +79,57 @@ public class SavedDeviceGroupControllerTest {
|
||||
private DockUpdater mSavedDockUpdater;
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
@Mock private BluetoothManager mBluetoothManager;
|
||||
@Mock private BluetoothAdapter mBluetoothAdapter;
|
||||
@Mock private CachedBluetoothDevice mCachedDevice1;
|
||||
@Mock private CachedBluetoothDevice mCachedDevice2;
|
||||
@Mock private CachedBluetoothDevice mCachedDevice3;
|
||||
@Mock private BluetoothDevice mBluetoothDevice1;
|
||||
@Mock private BluetoothDevice mBluetoothDevice2;
|
||||
@Mock private BluetoothDevice mBluetoothDevice3;
|
||||
@Mock private Drawable mDrawable;
|
||||
@Mock private PreferenceManager mPreferenceManager;
|
||||
|
||||
private Context mContext;
|
||||
private SavedDeviceGroupController mSavedDeviceGroupController;
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private Lifecycle mLifecycle;
|
||||
private PreferenceGroup mPreferenceGroup;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
Pair<Drawable, String> pairs = new Pair<>(mDrawable, "fake_device");
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mLifecycleOwner = () -> mLifecycle;
|
||||
mLifecycle = new Lifecycle(mLifecycleOwner);
|
||||
doReturn(mContext).when(mDashboardFragment).getContext();
|
||||
doReturn(mPackageManager).when(mContext).getPackageManager();
|
||||
|
||||
when(mCachedDevice1.getDevice()).thenReturn(mBluetoothDevice1);
|
||||
when(mCachedDevice1.getAddress()).thenReturn(FAKE_ADDRESS_1);
|
||||
when(mCachedDevice1.getDrawableWithDescription()).thenReturn(pairs);
|
||||
when(mCachedDevice2.getDevice()).thenReturn(mBluetoothDevice2);
|
||||
when(mCachedDevice2.getAddress()).thenReturn(FAKE_ADDRESS_2);
|
||||
when(mCachedDevice2.getDrawableWithDescription()).thenReturn(pairs);
|
||||
when(mCachedDevice3.getDevice()).thenReturn(mBluetoothDevice3);
|
||||
when(mCachedDevice3.getAddress()).thenReturn(FAKE_ADDRESS_3);
|
||||
when(mCachedDevice3.getDrawableWithDescription()).thenReturn(pairs);
|
||||
final List<BluetoothDevice> mMostRecentlyConnectedDevices = new ArrayList<>();
|
||||
mMostRecentlyConnectedDevices.add(mBluetoothDevice1);
|
||||
mMostRecentlyConnectedDevices.add(mBluetoothDevice2);
|
||||
mMostRecentlyConnectedDevices.add(mBluetoothDevice3);
|
||||
when(mContext.getSystemService(BluetoothManager.class)).thenReturn(mBluetoothManager);
|
||||
when(mBluetoothManager.getAdapter()).thenReturn(mBluetoothAdapter);
|
||||
when(mBluetoothAdapter.getMostRecentlyConnectedDevices())
|
||||
.thenReturn(mMostRecentlyConnectedDevices);
|
||||
|
||||
mPreferenceGroup = spy(new PreferenceCategory(mContext));
|
||||
when(mPreferenceGroup.getPreferenceManager()).thenReturn(mPreferenceManager);
|
||||
mSavedDeviceGroupController = new SavedDeviceGroupController(mContext);
|
||||
mSavedDeviceGroupController.setBluetoothDeviceUpdater(mBluetoothDeviceUpdater);
|
||||
mSavedDeviceGroupController.setSavedDockUpdater(mSavedDockUpdater);
|
||||
mSavedDeviceGroupController.setPreferenceGroup(mPreferenceGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -118,4 +175,71 @@ public class SavedDeviceGroupControllerTest {
|
||||
assertThat(mSavedDeviceGroupController.getAvailabilityStatus()).isEqualTo(
|
||||
AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SAVED_DEVICES_ORDER_BY_RECENCY)
|
||||
public void updatePreferenceGroup_bluetoothIsEnable_shouldOrderByMostRecentlyConnected() {
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
final BluetoothDevicePreference preference3 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice3,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
final BluetoothDevicePreference preference2 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice2,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
final BluetoothDevicePreference preference1 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice1,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
mSavedDeviceGroupController.onDeviceAdded(preference3);
|
||||
mSavedDeviceGroupController.onDeviceAdded(preference2);
|
||||
mSavedDeviceGroupController.onDeviceAdded(preference1);
|
||||
|
||||
mSavedDeviceGroupController.updatePreferenceGroup();
|
||||
|
||||
// Refer to the order of {@link #mMostRecentlyConnectedDevices}
|
||||
assertThat(mPreferenceGroup.isVisible()).isTrue();
|
||||
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(3);
|
||||
assertThat(preference1.getOrder()).isEqualTo(0);
|
||||
assertThat(preference2.getOrder()).isEqualTo(1);
|
||||
assertThat(preference3.getOrder()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SAVED_DEVICES_ORDER_BY_RECENCY)
|
||||
public void updatePreferenceGroup_bluetoothIsDisable_shouldShowNoPreference() {
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(false);
|
||||
final BluetoothDevicePreference preference3 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice3,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
final BluetoothDevicePreference preference2 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice2,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
final BluetoothDevicePreference preference1 =
|
||||
new BluetoothDevicePreference(
|
||||
mContext,
|
||||
mCachedDevice2,
|
||||
true,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
mSavedDeviceGroupController.onDeviceAdded(preference3);
|
||||
mSavedDeviceGroupController.onDeviceAdded(preference2);
|
||||
mSavedDeviceGroupController.onDeviceAdded(preference1);
|
||||
|
||||
mSavedDeviceGroupController.updatePreferenceGroup();
|
||||
|
||||
assertThat(mPreferenceGroup.isVisible()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.connecteddevice.audiosharing;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.shadows.androidx.fragment.FragmentController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowAlertDialogCompat.class,
|
||||
ShadowBluetoothAdapter.class,
|
||||
})
|
||||
public class AudioSharingDialogFragmentTest {
|
||||
|
||||
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
private static final String TEST_DEVICE_NAME1 = "test1";
|
||||
|
||||
private static final String TEST_DEVICE_NAME2 = "test2";
|
||||
private static final String TEST_DEVICE_NAME3 = "test3";
|
||||
private static final AudioSharingDeviceItem TEST_DEVICE_ITEM1 =
|
||||
new AudioSharingDeviceItem(TEST_DEVICE_NAME1, /* groupId= */ 1, /* isActive= */ false);
|
||||
private static final AudioSharingDeviceItem TEST_DEVICE_ITEM2 =
|
||||
new AudioSharingDeviceItem(TEST_DEVICE_NAME2, /* groupId= */ 2, /* isActive= */ false);
|
||||
private static final AudioSharingDeviceItem TEST_DEVICE_ITEM3 =
|
||||
new AudioSharingDeviceItem(TEST_DEVICE_NAME3, /* groupId= */ 3, /* isActive= */ false);
|
||||
|
||||
private Fragment mParent;
|
||||
private AudioSharingDialogFragment mFragment;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ShadowAlertDialogCompat.reset();
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mFragment = new AudioSharingDialogFragment();
|
||||
mParent = new Fragment();
|
||||
FragmentController.setupFragment(
|
||||
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_flagOff_dialogNotExist() {
|
||||
mFragment.show(mParent, new ArrayList<>(), (item) -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_flagOn_noConnectedDevice() {
|
||||
mFragment.show(mParent, new ArrayList<>(), (item) -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
TextView subtitle1 = rootView.findViewById(R.id.share_audio_subtitle1);
|
||||
ImageView guidance = rootView.findViewById(R.id.share_audio_guidance);
|
||||
Button shareBtn = rootView.findViewById(R.id.share_btn);
|
||||
assertThat(dialog.isShowing()).isTrue();
|
||||
assertThat(subtitle1.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(guidance.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(shareBtn.getVisibility()).isEqualTo(View.GONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_noConnectedDevice_dialogDismiss() {
|
||||
mFragment.show(mParent, new ArrayList<>(), (item) -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
dialog.findViewById(android.R.id.button2).performClick();
|
||||
shadowMainLooper().idle();
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_flagOn_singleConnectedDevice() {
|
||||
ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
|
||||
list.add(TEST_DEVICE_ITEM1);
|
||||
mFragment.show(mParent, list, (item) -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
TextView subtitle1 = rootView.findViewById(R.id.share_audio_subtitle1);
|
||||
ImageView guidance = rootView.findViewById(R.id.share_audio_guidance);
|
||||
Button shareBtn = rootView.findViewById(R.id.share_btn);
|
||||
assertThat(dialog.isShowing()).isTrue();
|
||||
assertThat(subtitle1.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(subtitle1.getText().toString()).isEqualTo(TEST_DEVICE_NAME1);
|
||||
assertThat(guidance.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(shareBtn.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_singleConnectedDevice_dialogDismiss() {
|
||||
mFragment.show(mParent, new ArrayList<>(), (item) -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
rootView.findViewById(R.id.cancel_btn).performClick();
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_singleConnectedDevice_shareClicked() {
|
||||
AtomicBoolean isShareBtnClicked = new AtomicBoolean(false);
|
||||
mFragment.show(
|
||||
mParent,
|
||||
new ArrayList<>(),
|
||||
(item) -> {
|
||||
isShareBtnClicked.set(true);
|
||||
});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
rootView.findViewById(R.id.share_btn).performClick();
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
assertThat(isShareBtnClicked.get()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_flagOn_multipleConnectedDevice() {
|
||||
ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
|
||||
list.add(TEST_DEVICE_ITEM1);
|
||||
list.add(TEST_DEVICE_ITEM2);
|
||||
list.add(TEST_DEVICE_ITEM3);
|
||||
mFragment.show(mParent, list, (item) -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
TextView subtitle1 = rootView.findViewById(R.id.share_audio_subtitle1);
|
||||
ImageView guidance = rootView.findViewById(R.id.share_audio_guidance);
|
||||
Button shareBtn = rootView.findViewById(R.id.share_btn);
|
||||
RecyclerView recyclerView = rootView.findViewById(R.id.btn_list);
|
||||
assertThat(dialog.isShowing()).isTrue();
|
||||
assertThat(subtitle1.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(guidance.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(shareBtn.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(recyclerView.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(recyclerView.getAdapter().getItemCount()).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_multipleConnectedDevice_dialogDismiss() {
|
||||
ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
|
||||
list.add(TEST_DEVICE_ITEM1);
|
||||
list.add(TEST_DEVICE_ITEM2);
|
||||
list.add(TEST_DEVICE_ITEM3);
|
||||
mFragment.show(mParent, list, (item) -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
rootView.findViewById(R.id.cancel_btn).performClick();
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.connecteddevice.audiosharing;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.shadows.androidx.fragment.FragmentController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowAlertDialogCompat.class,
|
||||
ShadowBluetoothAdapter.class,
|
||||
})
|
||||
public class AudioSharingDisconnectDialogFragmentTest {
|
||||
|
||||
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
private static final String TEST_DEVICE_NAME1 = "test1";
|
||||
private static final String TEST_DEVICE_NAME2 = "test2";
|
||||
private static final String TEST_DEVICE_NAME3 = "test3";
|
||||
private static final AudioSharingDeviceItem TEST_DEVICE_ITEM1 =
|
||||
new AudioSharingDeviceItem(TEST_DEVICE_NAME1, /* groupId= */ 1, /* isActive= */ true);
|
||||
private static final AudioSharingDeviceItem TEST_DEVICE_ITEM2 =
|
||||
new AudioSharingDeviceItem(TEST_DEVICE_NAME2, /* groupId= */ 2, /* isActive= */ false);
|
||||
|
||||
private Fragment mParent;
|
||||
private AudioSharingDisconnectDialogFragment mFragment;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ShadowAlertDialogCompat.reset();
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mFragment = new AudioSharingDisconnectDialogFragment();
|
||||
mParent = new Fragment();
|
||||
FragmentController.setupFragment(
|
||||
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
|
||||
ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
|
||||
list.add(TEST_DEVICE_ITEM1);
|
||||
list.add(TEST_DEVICE_ITEM2);
|
||||
mFragment.show(mParent, list, TEST_DEVICE_NAME3, (item) -> {});
|
||||
shadowMainLooper().idle();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_flagOff_dialogNotExist() {
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_flagOn_dialogShowBtnForTwoDevices() {
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
RecyclerView view = rootView.findViewById(R.id.device_btn_list);
|
||||
assertThat(view.getAdapter().getItemCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_clickCancel_dialogDismiss() {
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
rootView.findViewById(R.id.cancel_btn).performClick();
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.connecteddevice.audiosharing;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.connecteddevice.AvailableMediaDeviceGroupController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class AudioSharingFeatureProviderImplTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
@Mock private CachedBluetoothDevice mCachedDevice;
|
||||
@Mock private LocalBluetoothManager mLocalBtManager;
|
||||
@Mock private DashboardFragment mFragment;
|
||||
private Context mContext;
|
||||
private AudioSharingFeatureProviderImpl mFeatureProvider;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mFeatureProvider = new AudioSharingFeatureProviderImpl();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAudioSharingDevicePreferenceController_returnsNull() {
|
||||
assertThat(
|
||||
mFeatureProvider.createAudioSharingDevicePreferenceController(
|
||||
mContext, mFragment, /* lifecycle= */ null))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAvailableMediaDeviceGroupController_returnsNull() {
|
||||
assertThat(
|
||||
mFeatureProvider.createAvailableMediaDeviceGroupController(
|
||||
mContext, /* fragment= */ null, /* lifecycle= */ null))
|
||||
.isInstanceOf(AvailableMediaDeviceGroupController.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAudioSharingFilterMatched_returnsFalse() {
|
||||
assertThat(mFeatureProvider.isAudioSharingFilterMatched(mCachedDevice, mLocalBtManager))
|
||||
.isFalse();
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.connecteddevice.audiosharing;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.shadows.androidx.fragment.FragmentController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowAlertDialogCompat.class,
|
||||
ShadowBluetoothAdapter.class,
|
||||
})
|
||||
public class AudioSharingJoinDialogFragmentTest {
|
||||
|
||||
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
private static final String TEST_DEVICE_NAME1 = "test1";
|
||||
private static final String TEST_DEVICE_NAME2 = "test2";
|
||||
private static final AudioSharingDeviceItem TEST_DEVICE_ITEM =
|
||||
new AudioSharingDeviceItem(TEST_DEVICE_NAME1, /* groupId= */ 1, /* isActive= */ true);
|
||||
|
||||
private Fragment mParent;
|
||||
private AudioSharingJoinDialogFragment mFragment;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ShadowAlertDialogCompat.reset();
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mFragment = new AudioSharingJoinDialogFragment();
|
||||
mParent = new Fragment();
|
||||
FragmentController.setupFragment(
|
||||
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_flagOff_dialogNotExist() {
|
||||
mFragment.show(mParent, new ArrayList<>(), TEST_DEVICE_NAME2, () -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_flagOn_dialogShowTextForSingleDevice() {
|
||||
mFragment.show(mParent, new ArrayList<>(), TEST_DEVICE_NAME2, () -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog).isNotNull();
|
||||
assertThat(dialog.isShowing()).isTrue();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
TextView subtitle1 = rootView.findViewById(R.id.share_audio_subtitle1);
|
||||
assertThat(subtitle1.getText()).isEqualTo(TEST_DEVICE_NAME2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_flagOn_dialogShowTextForTwoDevice() {
|
||||
ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
|
||||
list.add(TEST_DEVICE_ITEM);
|
||||
mFragment.show(mParent, list, TEST_DEVICE_NAME2, () -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog).isNotNull();
|
||||
assertThat(dialog.isShowing()).isTrue();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
TextView subtitle1 = rootView.findViewById(R.id.share_audio_subtitle1);
|
||||
assertThat(subtitle1.getText()).isEqualTo(TEST_DEVICE_NAME1 + " and " + TEST_DEVICE_NAME2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_clickCancel_dialogDismiss() {
|
||||
mFragment.show(mParent, new ArrayList<>(), TEST_DEVICE_NAME2, () -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
rootView.findViewById(R.id.cancel_btn).performClick();
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_clickShare_callbackTriggered() {
|
||||
AtomicBoolean isShareBtnClicked = new AtomicBoolean(false);
|
||||
mFragment.show(
|
||||
mParent, new ArrayList<>(), TEST_DEVICE_NAME2, () -> isShareBtnClicked.set(true));
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
|
||||
View rootView = shadowDialog.getView();
|
||||
rootView.findViewById(R.id.share_btn).performClick();
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
assertThat(isShareBtnClicked.get()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.connecteddevice.audiosharing;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.shadows.androidx.fragment.FragmentController;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowAlertDialogCompat.class,
|
||||
ShadowBluetoothAdapter.class,
|
||||
})
|
||||
public class AudioSharingStopDialogFragmentTest {
|
||||
|
||||
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
private static final String TEST_DEVICE_NAME = "test";
|
||||
|
||||
private Fragment mParent;
|
||||
private AudioSharingStopDialogFragment mFragment;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ShadowAlertDialogCompat.reset();
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mFragment = new AudioSharingStopDialogFragment();
|
||||
mParent = new Fragment();
|
||||
FragmentController.setupFragment(
|
||||
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_flagOff_dialogNotExist() {
|
||||
mFragment.show(mParent, TEST_DEVICE_NAME, () -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
assertThat(dialog).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_clickCancel_dialogDismiss() {
|
||||
mFragment.show(mParent, TEST_DEVICE_NAME, () -> {});
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
dialog.findViewById(android.R.id.button2).performClick();
|
||||
shadowMainLooper().idle();
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void onCreateDialog_clickShare_callbackTriggered() {
|
||||
AtomicBoolean isStopBtnClicked = new AtomicBoolean(false);
|
||||
mFragment.show(mParent, TEST_DEVICE_NAME, () -> isStopBtnClicked.set(true));
|
||||
shadowMainLooper().idle();
|
||||
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
dialog.findViewById(android.R.id.button1).performClick();
|
||||
shadowMainLooper().idle();
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
assertThat(isStopBtnClicked.get()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.connecteddevice.audiosharing;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Looper;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.widget.Switch;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.widget.SettingsMainSwitchBar;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class AudioSharingSwitchBarControllerTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
@Spy Context mContext = ApplicationProvider.getApplicationContext();
|
||||
@Mock private Switch mSwitch;
|
||||
|
||||
private SettingsMainSwitchBar mSwitchBar;
|
||||
private AudioSharingSwitchBarController mController;
|
||||
private AudioSharingSwitchBarController.OnSwitchBarChangedListener mListener;
|
||||
private boolean mOnSwitchBarChanged;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mSwitchBar = new SettingsMainSwitchBar(mContext);
|
||||
mOnSwitchBarChanged = false;
|
||||
mListener = () -> mOnSwitchBarChanged = true;
|
||||
mController = new AudioSharingSwitchBarController(mContext, mSwitchBar, mListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
public void bluetoothOff_switchDisabled() {
|
||||
mContext.registerReceiver(
|
||||
mController.mReceiver,
|
||||
mController.mIntentFilter,
|
||||
Context.RECEIVER_EXPORTED_UNAUDITED);
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
|
||||
intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
|
||||
mContext.sendBroadcast(intent);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
verify(mSwitch).setEnabled(false);
|
||||
assertThat(mOnSwitchBarChanged).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.connecteddevice.fastpair;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class FastPairDeviceDashboardFragmentTest {
|
||||
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
private FastPairDeviceDashboardFragment mFragment;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mFragment = new FastPairDeviceDashboardFragment();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPreferenceScreenResId_returnsCorrectXml() {
|
||||
assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(R.xml.fast_pair_devices);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLogTag_returnsCorrectTag() {
|
||||
assertThat(mFragment.getLogTag()).isEqualTo("FastPairDeviceFrag");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMetricsCategory_returnsCorrectCategory() {
|
||||
assertThat(mFragment.getMetricsCategory()).isEqualTo(SettingsEnums.FAST_PAIR_DEVICES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHelpResource_returnsCorrectResource() {
|
||||
assertThat(mFragment.getHelpResource())
|
||||
.isEqualTo(R.string.help_url_connected_devices_fast_pair_devices);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
@@ -41,6 +42,7 @@ import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.flags.Flags;
|
||||
@@ -70,10 +72,13 @@ public class FastPairDeviceGroupControllerTest {
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
private static final String KEY = "fast_pair_device_list";
|
||||
|
||||
@Mock private DashboardFragment mDashboardFragment;
|
||||
@Mock private FastPairDeviceUpdater mFastPairDeviceUpdater;
|
||||
@Mock private PackageManager mPackageManager;
|
||||
@Mock private PreferenceManager mPreferenceManager;
|
||||
@Mock private PreferenceScreen mScreen;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
private Context mContext;
|
||||
private FastPairDeviceGroupController mFastPairDeviceGroupController;
|
||||
@@ -96,12 +101,14 @@ public class FastPairDeviceGroupControllerTest {
|
||||
doReturn(mPreferenceManager).when(mPreferenceGroup).getPreferenceManager();
|
||||
mPreferenceGroup.setVisible(false);
|
||||
mFastPairDeviceGroupController.setPreferenceGroup(mPreferenceGroup);
|
||||
when(mScreen.findPreference(KEY)).thenReturn(mPreferenceGroup);
|
||||
when(mScreen.getContext()).thenReturn(mContext);
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void testRegister() {
|
||||
public void onStart_flagOn_registerCallback() {
|
||||
// register the callback in onStart()
|
||||
mFastPairDeviceGroupController.onStart(mLifecycleOwner);
|
||||
verify(mFastPairDeviceUpdater).registerCallback();
|
||||
@@ -114,7 +121,7 @@ public class FastPairDeviceGroupControllerTest {
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void testUnregister() {
|
||||
public void onStop_flagOn_unregisterCallback() {
|
||||
// register broadcast first
|
||||
mContext.registerReceiver(
|
||||
mFastPairDeviceGroupController.mReceiver, null, Context.RECEIVER_EXPORTED);
|
||||
@@ -127,7 +134,33 @@ public class FastPairDeviceGroupControllerTest {
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void testGetAvailabilityStatus_noFastPairFeature_returnUnSupported() {
|
||||
public void onStart_flagOff_registerCallback() {
|
||||
// register the callback in onStart()
|
||||
mFastPairDeviceGroupController.onStart(mLifecycleOwner);
|
||||
assertThat(mFastPairDeviceUpdater).isNull();
|
||||
verify(mContext)
|
||||
.registerReceiver(
|
||||
mFastPairDeviceGroupController.mReceiver,
|
||||
mFastPairDeviceGroupController.mIntentFilter,
|
||||
Context.RECEIVER_EXPORTED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void onStop_flagOff_unregisterCallback() {
|
||||
// register broadcast first
|
||||
mContext.registerReceiver(
|
||||
mFastPairDeviceGroupController.mReceiver, null, Context.RECEIVER_EXPORTED);
|
||||
|
||||
// unregister the callback in onStop()
|
||||
mFastPairDeviceGroupController.onStop(mLifecycleOwner);
|
||||
assertThat(mFastPairDeviceUpdater).isNull();
|
||||
verify(mContext).unregisterReceiver(mFastPairDeviceGroupController.mReceiver);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void getAvailabilityStatus_noFastPairFeature_returnUnSupported() {
|
||||
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
|
||||
|
||||
assertThat(mFastPairDeviceGroupController.getAvailabilityStatus())
|
||||
@@ -135,8 +168,8 @@ public class FastPairDeviceGroupControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void testGetAvailabilityStatus_noBluetoothFeature_returnUnSupported() {
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void getAvailabilityStatus_noBluetoothFastPairFeature_returnUnSupported() {
|
||||
doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
|
||||
|
||||
assertThat(mFastPairDeviceGroupController.getAvailabilityStatus())
|
||||
@@ -145,15 +178,23 @@ public class FastPairDeviceGroupControllerTest {
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void testGetAvailabilityStatus_withBluetoothFastPairFeature_returnSupported() {
|
||||
public void getAvailabilityStatus_noBluetoothFeature_returnUnSupported() {
|
||||
doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
|
||||
|
||||
assertThat(mFastPairDeviceGroupController.getAvailabilityStatus())
|
||||
.isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void getAvailabilityStatus_withBluetoothFastPairFeature_returnSupported() {
|
||||
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
|
||||
|
||||
assertThat(mFastPairDeviceGroupController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void testUpdatePreferenceVisibility_bluetoothIsDisable_shouldHidePreference() {
|
||||
public void updatePreferenceVisibility_bluetoothIsDisable_shouldHidePreference() {
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
final GearPreference preference1 = new GearPreference(mContext, null /* AttributeSet */);
|
||||
mFastPairDeviceGroupController.onDeviceAdded(preference1);
|
||||
@@ -171,4 +212,37 @@ public class FastPairDeviceGroupControllerTest {
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(mPreferenceGroup.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceAdd_bluetoothIsDisable_shouldHidePreference() {
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
final GearPreference preference1 = new GearPreference(mContext, null /* AttributeSet */);
|
||||
mFastPairDeviceGroupController.onDeviceAdded(preference1);
|
||||
assertThat(mPreferenceGroup.isVisible()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceRemoved_bluetoothIsDisable_shouldHidePreference() {
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
final GearPreference preference1 = new GearPreference(mContext, null /* AttributeSet */);
|
||||
mPreferenceGroup.addPreference(preference1);
|
||||
mFastPairDeviceGroupController.onDeviceRemoved(preference1);
|
||||
assertThat(mPreferenceGroup.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void displayPreference_notAvailable_doNothing() {
|
||||
mFastPairDeviceGroupController.displayPreference(mScreen);
|
||||
assertThat(mPreferenceGroup.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void displayPreference_isAvailable_fetchFastPairDevices() {
|
||||
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
|
||||
|
||||
mFastPairDeviceGroupController.displayPreference(mScreen);
|
||||
verify(mFastPairDeviceUpdater).forceUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class FastPairDevicePreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void onStart_registerCallback() {
|
||||
public void onStart_flagOn_registerCallback() {
|
||||
// register the callback in onStart()
|
||||
mFastPairDevicePrefController.onStart(mLifecycleOwner);
|
||||
verify(mFastPairDeviceUpdater).registerCallback();
|
||||
@@ -120,9 +120,22 @@ public class FastPairDevicePreferenceControllerTest {
|
||||
Context.RECEIVER_EXPORTED_UNAUDITED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void onStart_flagOff_registerCallback() {
|
||||
// register the callback in onStart()
|
||||
mFastPairDevicePrefController.onStart(mLifecycleOwner);
|
||||
assertThat(mFastPairDeviceUpdater).isNull();
|
||||
verify(mContext)
|
||||
.registerReceiver(
|
||||
mFastPairDevicePrefController.mReceiver,
|
||||
mFastPairDevicePrefController.mIntentFilter,
|
||||
Context.RECEIVER_EXPORTED_UNAUDITED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void onStop_unregisterCallback() {
|
||||
public void onStop_flagOn_unregisterCallback() {
|
||||
// register broadcast first
|
||||
mContext.registerReceiver(
|
||||
mFastPairDevicePrefController.mReceiver, null, Context.RECEIVER_EXPORTED_UNAUDITED);
|
||||
@@ -133,6 +146,19 @@ public class FastPairDevicePreferenceControllerTest {
|
||||
verify(mContext).unregisterReceiver(mFastPairDevicePrefController.mReceiver);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void onStop_flagOff_unregisterCallback() {
|
||||
// register broadcast first
|
||||
mContext.registerReceiver(
|
||||
mFastPairDevicePrefController.mReceiver, null, Context.RECEIVER_EXPORTED_UNAUDITED);
|
||||
|
||||
// unregister the callback in onStop()
|
||||
mFastPairDevicePrefController.onStop(mLifecycleOwner);
|
||||
assertThat(mFastPairDeviceUpdater).isNull();
|
||||
verify(mContext).unregisterReceiver(mFastPairDevicePrefController.mReceiver);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void getAvailabilityStatus_noBluetoothFeature_returnUnsupported() {
|
||||
@@ -151,6 +177,15 @@ public class FastPairDevicePreferenceControllerTest {
|
||||
.isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void getAvailabilityStatus_noBluetoothFastPairFeature_returnUnsupported() {
|
||||
doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
|
||||
|
||||
assertThat(mFastPairDevicePrefController.getAvailabilityStatus())
|
||||
.isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void getAvailabilityStatus_bothBluetoothFastPairFeature_returnSupported() {
|
||||
@@ -160,7 +195,6 @@ public class FastPairDevicePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void onDeviceAdded_addThreeFastPairDevicePreference_displayThreeNoSeeAll() {
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
final GearPreference preference1 = new GearPreference(mContext, null /* AttributeSet */);
|
||||
@@ -177,7 +211,6 @@ public class FastPairDevicePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void onDeviceAdded_addFourDevicePreference_onlyDisplayThreeWithSeeAll() {
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
final GearPreference preference1 = new GearPreference(mContext, null /* AttributeSet */);
|
||||
@@ -206,7 +239,6 @@ public class FastPairDevicePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void onDeviceRemoved_removeFourthDevice_hideSeeAll() {
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
final GearPreference preference1 = new GearPreference(mContext, null /* AttributeSet */);
|
||||
@@ -238,7 +270,6 @@ public class FastPairDevicePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_SUBSEQUENT_PAIR_SETTINGS_INTEGRATION)
|
||||
public void updatePreferenceVisibility_bluetoothIsDisable_shouldHidePreference() {
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
final GearPreference preference1 = new GearPreference(mContext, null /* AttributeSet */);
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.connecteddevice.fastpair;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.connecteddevice.DevicePreferenceCallback;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class FastPairFeatureProviderImplTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
@Mock private DevicePreferenceCallback mDevicePreferenceCallback;
|
||||
|
||||
private Context mContext;
|
||||
private FastPairFeatureProviderImpl mFeatureProvider;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mFeatureProvider = new FastPairFeatureProviderImpl();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFastPairDeviceUpdater_returnsEmptyClass() {
|
||||
assertThat(mFeatureProvider.getFastPairDeviceUpdater(mContext, mDevicePreferenceCallback))
|
||||
.isInstanceOf(FastPairDeviceUpdater.class);
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,9 @@ public class StylusDevicesControllerTest {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
final var spiedResources = spy(mContext.getResources());
|
||||
when(mContext.getResources()).thenReturn(spiedResources);
|
||||
|
||||
PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
mScreen = preferenceManager.createPreferenceScreen(mContext);
|
||||
mPreferenceContainer = new PreferenceCategory(mContext);
|
||||
@@ -144,6 +147,9 @@ public class StylusDevicesControllerTest {
|
||||
when(mInputDevice.hasKeys(KEYCODE_STYLUS_BUTTON_TAIL)).thenReturn(
|
||||
new boolean[]{true});
|
||||
|
||||
when(spiedResources.getBoolean(
|
||||
com.android.internal.R.bool.config_enableStylusPointerIcon)).thenReturn(true);
|
||||
|
||||
mController = new StylusDevicesController(mContext, mInputDevice, null, mLifecycle);
|
||||
}
|
||||
|
||||
@@ -221,7 +227,7 @@ public class StylusDevicesControllerTest {
|
||||
|
||||
showScreen(controller);
|
||||
|
||||
assertThat(mPreferenceContainer.getPreferenceCount()).isEqualTo(3);
|
||||
assertThat(mPreferenceContainer.getPreferenceCount()).isEqualTo(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -237,7 +243,7 @@ public class StylusDevicesControllerTest {
|
||||
Preference handwritingPref = mPreferenceContainer.getPreference(0);
|
||||
Preference buttonPref = mPreferenceContainer.getPreference(1);
|
||||
|
||||
assertThat(mPreferenceContainer.getPreferenceCount()).isEqualTo(2);
|
||||
assertThat(mPreferenceContainer.getPreferenceCount()).isEqualTo(3);
|
||||
assertThat(handwritingPref.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.stylus_textfield_handwriting));
|
||||
assertThat(handwritingPref.isVisible()).isTrue();
|
||||
@@ -249,11 +255,12 @@ public class StylusDevicesControllerTest {
|
||||
@Test
|
||||
public void btStylusInputDevice_showsAllPreferences() {
|
||||
showScreen(mController);
|
||||
|
||||
Preference defaultNotesPref = mPreferenceContainer.getPreference(0);
|
||||
Preference handwritingPref = mPreferenceContainer.getPreference(1);
|
||||
Preference buttonPref = mPreferenceContainer.getPreference(2);
|
||||
Preference stylusPointerIconPref = mPreferenceContainer.getPreference(3);
|
||||
|
||||
assertThat(mPreferenceContainer.getPreferenceCount()).isEqualTo(3);
|
||||
assertThat(defaultNotesPref.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.stylus_default_notes_app));
|
||||
assertThat(defaultNotesPref.isVisible()).isTrue();
|
||||
@@ -263,6 +270,9 @@ public class StylusDevicesControllerTest {
|
||||
assertThat(buttonPref.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.stylus_ignore_button));
|
||||
assertThat(buttonPref.isVisible()).isTrue();
|
||||
assertThat(stylusPointerIconPref.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.show_stylus_pointer_icon));
|
||||
assertThat(stylusPointerIconPref.isVisible()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -551,6 +561,46 @@ public class StylusDevicesControllerTest {
|
||||
Secure.STYLUS_BUTTONS_ENABLED, -1)).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stylusPointerIconPreference_checkedWhenFlagTrue() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.STYLUS_POINTER_ICON_ENABLED, 1);
|
||||
|
||||
showScreen(mController);
|
||||
SwitchPreferenceCompat stylusPointerIconPref =
|
||||
(SwitchPreferenceCompat) mPreferenceContainer.getPreference(3);
|
||||
|
||||
assertThat(stylusPointerIconPref.isChecked()).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stylusPointerIconPreference_uncheckedWhenFlagFalse() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.STYLUS_POINTER_ICON_ENABLED, 0);
|
||||
|
||||
showScreen(mController);
|
||||
SwitchPreferenceCompat stylusPointerIconPref =
|
||||
(SwitchPreferenceCompat) mPreferenceContainer.getPreference(3);
|
||||
|
||||
assertThat(stylusPointerIconPref.isChecked()).isEqualTo(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stylusPointerIconPreference_updatesFlagOnClick() {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.STYLUS_POINTER_ICON_ENABLED, 0);
|
||||
|
||||
showScreen(mController);
|
||||
SwitchPreferenceCompat stylusPointerIconPref =
|
||||
(SwitchPreferenceCompat) mPreferenceContainer.getPreference(3);
|
||||
|
||||
stylusPointerIconPref.performClick();
|
||||
|
||||
assertThat(stylusPointerIconPref.isChecked()).isEqualTo(true);
|
||||
assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Secure.STYLUS_POINTER_ICON_ENABLED, -1)).isEqualTo(1);
|
||||
}
|
||||
|
||||
private void showScreen(StylusDevicesController controller) {
|
||||
controller.displayPreference(mScreen);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.connecteddevice.usb;
|
||||
|
||||
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Context;
|
||||
import android.hardware.usb.UsbPortStatus;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
|
||||
import com.android.settings.flags.Flags;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowKeyguardManager;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
ShadowKeyguardManager.class
|
||||
})
|
||||
public class UsbDetailsControllerTest {
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
@Mock
|
||||
private UsbBackend mUsbBackend;
|
||||
|
||||
private Context mContext;
|
||||
private UsbDetailsController mUsbDetailsController;
|
||||
private UsbDetailsFragment mUsbDetailsFragment;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = getApplicationContext();
|
||||
mUsbDetailsFragment = new UsbDetailsFragment();
|
||||
mUsbDetailsController = new UsbDetailsController(
|
||||
mContext, mUsbDetailsFragment, mUsbBackend) {
|
||||
@Override
|
||||
protected void refresh(boolean connected, long functions, int powerRole, int dataRole) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_returnsTrue() {
|
||||
assertThat(mUsbDetailsController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_AUTH_CHALLENGE_FOR_USB_PREFERENCES)
|
||||
public void requireAuthAndExecute_whenAlreadyAuthenticated_executes() {
|
||||
mUsbDetailsFragment.setUserAuthenticated(true);
|
||||
Runnable action = () -> mUsbBackend.setDataRole(UsbPortStatus.DATA_ROLE_HOST);
|
||||
|
||||
mUsbDetailsController.requireAuthAndExecute(action);
|
||||
|
||||
verify(mUsbBackend).setDataRole(anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_AUTH_CHALLENGE_FOR_USB_PREFERENCES)
|
||||
public void requireAuthAndExecute_authenticatesAndExecutes() {
|
||||
mUsbDetailsFragment.setUserAuthenticated(false);
|
||||
setAuthPassesAutomatically();
|
||||
Runnable action = () -> mUsbBackend.setDataRole(UsbPortStatus.DATA_ROLE_HOST);
|
||||
|
||||
mUsbDetailsController.requireAuthAndExecute(action);
|
||||
|
||||
assertThat(mUsbDetailsFragment.isUserAuthenticated()).isTrue();
|
||||
verify(mUsbBackend).setDataRole(anyInt());
|
||||
}
|
||||
|
||||
private void setAuthPassesAutomatically() {
|
||||
Shadows.shadowOf(mContext.getSystemService(KeyguardManager.class))
|
||||
.setIsKeyguardSecure(false);
|
||||
}
|
||||
}
|
||||
@@ -25,12 +25,15 @@ import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Context;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.Handler;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
@@ -38,6 +41,7 @@ import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.widget.SelectorWithWidgetPreference;
|
||||
|
||||
@@ -49,6 +53,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@@ -63,12 +68,11 @@ public class UsbDetailsDataRoleControllerTest {
|
||||
private PreferenceCategory mPreference;
|
||||
private PreferenceManager mPreferenceManager;
|
||||
private PreferenceScreen mScreen;
|
||||
private UsbDetailsFragment mFragment;
|
||||
|
||||
@Mock
|
||||
private UsbBackend mUsbBackend;
|
||||
@Mock
|
||||
private UsbDetailsFragment mFragment;
|
||||
@Mock
|
||||
private FragmentActivity mActivity;
|
||||
@Mock
|
||||
private Handler mHandler;
|
||||
@@ -76,7 +80,7 @@ public class UsbDetailsDataRoleControllerTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mFragment = spy(new UsbDetailsFragment());
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mLifecycle = new Lifecycle(() -> mLifecycle);
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
@@ -95,12 +99,12 @@ public class UsbDetailsDataRoleControllerTest {
|
||||
mScreen.addPreference(mPreference);
|
||||
|
||||
mDetailsDataRoleController.mHandler = mHandler;
|
||||
|
||||
mDetailsDataRoleController.displayPreference(mScreen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayRefresh_deviceRole_shouldCheckDevice() {
|
||||
mDetailsDataRoleController.displayPreference(mScreen);
|
||||
|
||||
mDetailsDataRoleController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
|
||||
DATA_ROLE_DEVICE);
|
||||
|
||||
@@ -112,8 +116,6 @@ public class UsbDetailsDataRoleControllerTest {
|
||||
|
||||
@Test
|
||||
public void displayRefresh_hostRole_shouldCheckHost() {
|
||||
mDetailsDataRoleController.displayPreference(mScreen);
|
||||
|
||||
mDetailsDataRoleController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
|
||||
DATA_ROLE_HOST);
|
||||
|
||||
@@ -125,8 +127,6 @@ public class UsbDetailsDataRoleControllerTest {
|
||||
|
||||
@Test
|
||||
public void displayRefresh_disconnected_shouldDisable() {
|
||||
mDetailsDataRoleController.displayPreference(mScreen);
|
||||
|
||||
mDetailsDataRoleController.refresh(false, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
|
||||
DATA_ROLE_DEVICE);
|
||||
|
||||
@@ -135,7 +135,6 @@ public class UsbDetailsDataRoleControllerTest {
|
||||
|
||||
@Test
|
||||
public void onClickDevice_hostEnabled_shouldSetDevice() {
|
||||
mDetailsDataRoleController.displayPreference(mScreen);
|
||||
when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
|
||||
|
||||
final SelectorWithWidgetPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
|
||||
@@ -148,7 +147,6 @@ public class UsbDetailsDataRoleControllerTest {
|
||||
|
||||
@Test
|
||||
public void onClickDeviceTwice_hostEnabled_shouldSetDeviceOnce() {
|
||||
mDetailsDataRoleController.displayPreference(mScreen);
|
||||
when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
|
||||
|
||||
final SelectorWithWidgetPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
|
||||
@@ -162,7 +160,6 @@ public class UsbDetailsDataRoleControllerTest {
|
||||
|
||||
@Test
|
||||
public void onClickDeviceAndRefresh_success_shouldClearSubtext() {
|
||||
mDetailsDataRoleController.displayPreference(mScreen);
|
||||
when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
|
||||
|
||||
final SelectorWithWidgetPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
|
||||
@@ -180,7 +177,6 @@ public class UsbDetailsDataRoleControllerTest {
|
||||
|
||||
@Test
|
||||
public void onClickDeviceAndRefresh_failed_shouldShowFailureText() {
|
||||
mDetailsDataRoleController.displayPreference(mScreen);
|
||||
when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
|
||||
|
||||
final SelectorWithWidgetPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
|
||||
@@ -199,7 +195,6 @@ public class UsbDetailsDataRoleControllerTest {
|
||||
|
||||
@Test
|
||||
public void onClickDevice_timedOut_shouldShowFailureText() {
|
||||
mDetailsDataRoleController.displayPreference(mScreen);
|
||||
when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
|
||||
|
||||
final SelectorWithWidgetPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
|
||||
@@ -218,6 +213,22 @@ public class UsbDetailsDataRoleControllerTest {
|
||||
.isEqualTo(mContext.getString(R.string.usb_switching_failed));
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_AUTH_CHALLENGE_FOR_USB_PREFERENCES)
|
||||
public void onRadioButtonClicked_userAuthenticated() {
|
||||
SelectorWithWidgetPreference preference = getRadioPreference(DATA_ROLE_DEVICE);
|
||||
setAuthPassesAutomatically();
|
||||
|
||||
mDetailsDataRoleController.onRadioButtonClicked(preference);
|
||||
|
||||
assertThat(mFragment.isUserAuthenticated()).isTrue();
|
||||
}
|
||||
|
||||
private void setAuthPassesAutomatically() {
|
||||
Shadows.shadowOf(mContext.getSystemService(KeyguardManager.class))
|
||||
.setIsKeyguardSecure(false);
|
||||
}
|
||||
|
||||
private SelectorWithWidgetPreference getRadioPreference(int role) {
|
||||
return (SelectorWithWidgetPreference)
|
||||
mPreference.findPreference(UsbBackend.dataRoleToString(role));
|
||||
|
||||
@@ -30,15 +30,18 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Context;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.net.TetheringManager;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.widget.SelectorWithWidgetPreference;
|
||||
@@ -51,6 +54,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -70,12 +74,11 @@ public class UsbDetailsFunctionsControllerTest {
|
||||
private PreferenceManager mPreferenceManager;
|
||||
private PreferenceScreen mScreen;
|
||||
private SelectorWithWidgetPreference mRadioButtonPreference;
|
||||
private UsbDetailsFragment mFragment;
|
||||
|
||||
@Mock
|
||||
private UsbBackend mUsbBackend;
|
||||
@Mock
|
||||
private UsbDetailsFragment mFragment;
|
||||
@Mock
|
||||
private FragmentActivity mActivity;
|
||||
@Mock
|
||||
private TetheringManager mTetheringManager;
|
||||
@@ -83,7 +86,7 @@ public class UsbDetailsFunctionsControllerTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mFragment = spy(new UsbDetailsFragment());
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mLifecycle = new Lifecycle(() -> mLifecycle);
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
@@ -334,6 +337,23 @@ public class UsbDetailsFunctionsControllerTest {
|
||||
eq(mDetailsFunctionsController.mOnStartTetheringCallback));
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_AUTH_CHALLENGE_FOR_USB_PREFERENCES)
|
||||
public void onRadioButtonClicked_userAuthenticated() {
|
||||
mRadioButtonPreference.setKey(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_PTP));
|
||||
doReturn(UsbManager.FUNCTION_MTP).when(mUsbBackend).getCurrentFunctions();
|
||||
setAuthPassesAutomatically();
|
||||
|
||||
mDetailsFunctionsController.onRadioButtonClicked(mRadioButtonPreference);
|
||||
|
||||
assertThat(mFragment.isUserAuthenticated()).isTrue();
|
||||
}
|
||||
|
||||
private void setAuthPassesAutomatically() {
|
||||
Shadows.shadowOf(mContext.getSystemService(KeyguardManager.class))
|
||||
.setIsKeyguardSecure(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onTetheringFailed_resetPreviousFunctions() {
|
||||
mDetailsFunctionsController.mPreviousFunction = UsbManager.FUNCTION_PTP;
|
||||
|
||||
@@ -21,11 +21,14 @@ import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Context;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.SystemProperties;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
@@ -33,6 +36,7 @@ import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -43,6 +47,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@@ -57,18 +62,18 @@ public class UsbDetailsTranscodeMtpControllerTest {
|
||||
private PreferenceManager mPreferenceManager;
|
||||
private PreferenceScreen mScreen;
|
||||
private UsbDetailsTranscodeMtpController mUnderTest;
|
||||
private UsbDetailsFragment mFragment;
|
||||
|
||||
@Mock
|
||||
private UsbBackend mUsbBackend;
|
||||
@Mock
|
||||
private UsbDetailsFragment mFragment;
|
||||
@Mock
|
||||
private FragmentActivity mActivity;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mFragment = spy(new UsbDetailsFragment());
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
mScreen = mPreferenceManager.createPreferenceScreen(mContext);
|
||||
@@ -84,11 +89,12 @@ public class UsbDetailsTranscodeMtpControllerTest {
|
||||
mPreference = new PreferenceCategory(mContext);
|
||||
mPreference.setKey(mUnderTest.getPreferenceKey());
|
||||
mScreen.addPreference(mPreference);
|
||||
|
||||
mUnderTest.displayPreference(mScreen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayRefresh_noUsbConnection_shouldDisablePrefCategory() {
|
||||
mUnderTest.displayPreference(mScreen);
|
||||
when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
|
||||
|
||||
mUnderTest.refresh(false /* connected */, UsbManager.FUNCTION_MTP, POWER_ROLE_NONE,
|
||||
@@ -99,7 +105,6 @@ public class UsbDetailsTranscodeMtpControllerTest {
|
||||
|
||||
@Test
|
||||
public void displayRefresh_noDataTransfer_shouldDisablePrefCategory() {
|
||||
mUnderTest.displayPreference(mScreen);
|
||||
when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
|
||||
|
||||
mUnderTest.refresh(true /* connected */, UsbManager.FUNCTION_NONE, POWER_ROLE_NONE,
|
||||
@@ -110,7 +115,6 @@ public class UsbDetailsTranscodeMtpControllerTest {
|
||||
|
||||
@Test
|
||||
public void displayRefresh_noDataRole_shouldDisablePrefCategory() throws InterruptedException {
|
||||
mUnderTest.displayPreference(mScreen);
|
||||
when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
|
||||
|
||||
mUnderTest.refresh(true /* connected */, UsbManager.FUNCTION_MTP, POWER_ROLE_NONE,
|
||||
@@ -122,7 +126,6 @@ public class UsbDetailsTranscodeMtpControllerTest {
|
||||
@Ignore("b/313362757")
|
||||
@Test
|
||||
public void displayRefresh_fileTransfer_withAbsentProp_shouldCheck() {
|
||||
mUnderTest.displayPreference(mScreen);
|
||||
when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
|
||||
|
||||
mUnderTest.refresh(true /* connected */, UsbManager.FUNCTION_MTP, POWER_ROLE_NONE,
|
||||
@@ -134,7 +137,6 @@ public class UsbDetailsTranscodeMtpControllerTest {
|
||||
@Ignore("b/313362757")
|
||||
@Test
|
||||
public void displayRefresh_fileTransfer_withUnsetProp_shouldUncheck() {
|
||||
mUnderTest.displayPreference(mScreen);
|
||||
SystemProperties.set(TRANSCODE_MTP_SYS_PROP_KEY, Boolean.toString(false));
|
||||
when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
|
||||
|
||||
@@ -147,7 +149,6 @@ public class UsbDetailsTranscodeMtpControllerTest {
|
||||
@Ignore("b/313362757")
|
||||
@Test
|
||||
public void displayRefresh_fileTransfer_withSetProp_shouldCheck() {
|
||||
mUnderTest.displayPreference(mScreen);
|
||||
SystemProperties.set(TRANSCODE_MTP_SYS_PROP_KEY, Boolean.toString(true));
|
||||
when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
|
||||
|
||||
@@ -160,7 +161,6 @@ public class UsbDetailsTranscodeMtpControllerTest {
|
||||
@Ignore("b/313362757")
|
||||
@Test
|
||||
public void click_checked_shouldSetSystemProperty() {
|
||||
mUnderTest.displayPreference(mScreen);
|
||||
getSwitchPreference().performClick();
|
||||
assertThat(SystemProperties.getBoolean(TRANSCODE_MTP_SYS_PROP_KEY, false)).isTrue();
|
||||
}
|
||||
@@ -168,7 +168,6 @@ public class UsbDetailsTranscodeMtpControllerTest {
|
||||
@Ignore("b/313362757")
|
||||
@Test
|
||||
public void click_unChecked_shouldUnsetSystemProperty() {
|
||||
mUnderTest.displayPreference(mScreen);
|
||||
getSwitchPreference().performClick();
|
||||
getSwitchPreference().performClick();
|
||||
assertThat(SystemProperties.getBoolean(TRANSCODE_MTP_SYS_PROP_KEY, true)).isFalse();
|
||||
@@ -181,6 +180,21 @@ public class UsbDetailsTranscodeMtpControllerTest {
|
||||
assertThat(mUnderTest.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_AUTH_CHALLENGE_FOR_USB_PREFERENCES)
|
||||
public void onClick_userAuthenticated() {
|
||||
setAuthPassesAutomatically();
|
||||
|
||||
mUnderTest.onPreferenceClick(null);
|
||||
|
||||
assertThat(mFragment.isUserAuthenticated()).isTrue();
|
||||
}
|
||||
|
||||
private void setAuthPassesAutomatically() {
|
||||
Shadows.shadowOf(mContext.getSystemService(KeyguardManager.class))
|
||||
.setIsKeyguardSecure(false);
|
||||
}
|
||||
|
||||
private SwitchPreference getSwitchPreference() {
|
||||
return (SwitchPreference) mPreference.getPreference(0);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Application;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -62,6 +63,7 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
@@ -83,16 +85,16 @@ import com.android.settingslib.drawer.Tile;
|
||||
import com.android.settingslib.drawer.TileUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowActivity;
|
||||
@@ -104,10 +106,14 @@ import java.util.List;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = ShadowUserManager.class)
|
||||
public class DashboardFeatureProviderImplTest {
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
private static final String KEY = "key";
|
||||
private static final String SWITCH_URI = "content://com.android.settings/tile_switch";
|
||||
|
||||
private final Application mApplication = ApplicationProvider.getApplicationContext();
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private FragmentActivity mActivity;
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
@@ -126,9 +132,8 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
doReturn(RuntimeEnvironment.application).when(mActivity).getApplicationContext();
|
||||
mContext = spy(mApplication);
|
||||
doReturn(mApplication).when(mActivity).getApplicationContext();
|
||||
mForceRoundedIcon = false;
|
||||
mActivityInfo = new ActivityInfo();
|
||||
mActivityInfo.packageName = mContext.getPackageName();
|
||||
@@ -163,7 +168,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindPreference_shouldBindAllData() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
final Tile tile = spy(new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
|
||||
mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10);
|
||||
doReturn(Icon.createWithBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565)))
|
||||
@@ -183,7 +188,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindPreference_shouldBindAllSwitchData() {
|
||||
final Preference preference = new SwitchPreference(RuntimeEnvironment.application);
|
||||
final Preference preference = new SwitchPreference(mApplication);
|
||||
final Tile tile = spy(new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE,
|
||||
mSwitchMetaData));
|
||||
mSwitchMetaData.putInt(META_DATA_KEY_ORDER, 10);
|
||||
@@ -204,7 +209,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindPreference_providerTileWithPendingIntent_shouldBindIntent() {
|
||||
final Preference preference = new SwitchPreference(RuntimeEnvironment.application);
|
||||
final Preference preference = new SwitchPreference(mApplication);
|
||||
Bundle metaData = new Bundle();
|
||||
metaData.putInt(META_DATA_PREFERENCE_TITLE, R.string.settings_label);
|
||||
metaData.putInt(META_DATA_PREFERENCE_SUMMARY, R.string.about_settings_summary);
|
||||
@@ -212,7 +217,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
metaData.putString(META_DATA_PREFERENCE_KEYHINT, KEY);
|
||||
final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE, metaData);
|
||||
PendingIntent pendingIntent =
|
||||
PendingIntent.getActivity(RuntimeEnvironment.application, 0, new Intent("test"), 0);
|
||||
PendingIntent.getActivity(mApplication, 0, new Intent("test"), 0);
|
||||
tile.pendingIntentMap.put(UserHandle.CURRENT, pendingIntent);
|
||||
|
||||
mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon,
|
||||
@@ -225,7 +230,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindPreference_noFragmentMetadata_shouldBindIntent() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10);
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
|
||||
@@ -237,10 +242,9 @@ public class DashboardFeatureProviderImplTest {
|
||||
assertThat(preference.getOrder()).isEqualTo(tile.getOrder());
|
||||
}
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Test
|
||||
public void bindPreference_noFragmentMetadata_shouldBindToProfileSelector() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
tile.userHandle = new ArrayList<>();
|
||||
tile.userHandle.add(mock(UserHandle.class));
|
||||
@@ -255,7 +259,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindPreference_noFragmentMetadataSingleUser_shouldBindToDirectLaunchIntent() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
tile.userHandle = new ArrayList<>();
|
||||
tile.userHandle.add(mock(UserHandle.class));
|
||||
@@ -276,8 +280,8 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindPreference_toInternalSettingActivity_shouldBindToDirectLaunchIntentAndNotLog() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName();
|
||||
final Preference preference = new Preference(mApplication);
|
||||
mActivityInfo.packageName = mApplication.getPackageName();
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
tile.userHandle = new ArrayList<>();
|
||||
tile.userHandle.add(mock(UserHandle.class));
|
||||
@@ -303,7 +307,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindPreference_withNullKeyNullPriority_shouldGenerateKeyAndPriority() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon,
|
||||
preference, tile, null /* key */,
|
||||
@@ -315,7 +319,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindPreference_noSummary_shouldSetNullSummary() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
mActivityInfo.metaData.remove(META_DATA_PREFERENCE_SUMMARY);
|
||||
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
@@ -329,7 +333,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
@Config(shadows = {ShadowTileUtils.class})
|
||||
public void bindPreference_hasSummaryUri_shouldLoadSummaryFromContentProviderAndHaveObserver() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
final String uriString = "content://com.android.settings/tile_summary";
|
||||
mActivityInfo.metaData.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, uriString);
|
||||
@@ -349,7 +353,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
@Config(shadows = {ShadowTileUtils.class})
|
||||
public void bindPreference_hasTitleUri_shouldLoadFromContentProviderAndHaveObserver() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
final String uriString = "content://com.android.settings/tile_title";
|
||||
mActivityInfo.metaData.putString(TileUtils.META_DATA_PREFERENCE_TITLE_URI, uriString);
|
||||
@@ -369,7 +373,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
@Config(shadows = {ShadowTileUtils.class})
|
||||
public void bindPreference_onCheckedChanged_shouldPutStateToContentProvider() {
|
||||
final SwitchPreference preference = new SwitchPreference(RuntimeEnvironment.application);
|
||||
final SwitchPreference preference = new SwitchPreference(mApplication);
|
||||
final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE,
|
||||
mSwitchMetaData);
|
||||
final Bundle bundle = new Bundle();
|
||||
@@ -390,7 +394,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
@Config(shadows = {ShadowTileUtils.class})
|
||||
public void bindPreference_onCheckedChangedError_shouldRevertCheckedState() {
|
||||
final SwitchPreference preference = new SwitchPreference(RuntimeEnvironment.application);
|
||||
final SwitchPreference preference = new SwitchPreference(mApplication);
|
||||
final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE,
|
||||
mSwitchMetaData);
|
||||
final Bundle bundle = new Bundle();
|
||||
@@ -411,7 +415,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
@Config(shadows = {ShadowTileUtils.class})
|
||||
public void bindPreference_callbackOnChanged_shouldLoadFromContentProvider() {
|
||||
final SwitchPreference preference = new SwitchPreference(RuntimeEnvironment.application);
|
||||
final SwitchPreference preference = new SwitchPreference(mApplication);
|
||||
final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE,
|
||||
mSwitchMetaData);
|
||||
final List<DynamicDataObserver> observers = mImpl.bindPreferenceToTileAndGetObservers(
|
||||
@@ -432,7 +436,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindPreference_withNullKeyTileKey_shouldUseTileKey() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon,
|
||||
@@ -443,8 +447,8 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindIcon_withStaticIcon_shouldLoadStaticIcon() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName();
|
||||
final Preference preference = new Preference(mApplication);
|
||||
mActivityInfo.packageName = mApplication.getPackageName();
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, R.drawable.ic_add_40dp);
|
||||
@@ -461,8 +465,8 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
@Config(shadows = {ShadowTileUtils.class})
|
||||
public void bindIcon_withIconUri_shouldLoadIconFromContentProvider() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName();
|
||||
final Preference preference = new Preference(mApplication);
|
||||
mActivityInfo.packageName = mApplication.getPackageName();
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_ICON_URI,
|
||||
@@ -476,8 +480,8 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
@Config(shadows = {ShadowTileUtils.class})
|
||||
public void bindIcon_withStaticIconAndIconUri_shouldLoadIconFromContentProvider() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName();
|
||||
final Preference preference = new Preference(mApplication);
|
||||
mActivityInfo.packageName = mApplication.getPackageName();
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, R.drawable.ic_add_40dp);
|
||||
@@ -503,8 +507,8 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
@Config(shadows = {ShadowTileUtils.class})
|
||||
public void bindIcon_noIcon_shouldNotLoadIcon() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName();
|
||||
final Preference preference = new Preference(mApplication);
|
||||
mActivityInfo.packageName = mApplication.getPackageName();
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
|
||||
@@ -516,7 +520,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
public void bindPreference_withBaseOrder_shouldOffsetOrder() {
|
||||
final int baseOrder = 100;
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10);
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
|
||||
@@ -528,7 +532,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindPreference_withOrderMetadata_shouldUseOrderInMetadata() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
final int testOrder = -30;
|
||||
mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10);
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
@@ -541,7 +545,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void bindPreference_invalidOrderMetadata_shouldIgnore() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mActivityInfo.metaData.putString(META_DATA_KEY_ORDER, "hello");
|
||||
|
||||
@@ -554,7 +558,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
public void bindPreference_withIntentActionMetadata_shouldSetLaunchAction() {
|
||||
FragmentActivity activity = Robolectric.buildActivity(FragmentActivity.class).get();
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
mActivityInfo.metaData.putString("com.android.settings.intent.action", "TestAction");
|
||||
@@ -583,7 +587,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
String clickPrefKey = "highlight_pref_key";
|
||||
String highlightMixinPrefKey = "highlight_pref_key";
|
||||
FragmentActivity activity = Robolectric.buildActivity(FragmentActivity.class).get();
|
||||
Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
Preference preference = new Preference(mApplication);
|
||||
Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
mActivityInfo.metaData.putString("com.android.settings.intent.action", "TestAction");
|
||||
@@ -614,7 +618,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
String clickPrefKey = "not_highlight_pref_key";
|
||||
String highlightMixinPrefKey = "highlight_pref_key";
|
||||
FragmentActivity activity = Robolectric.buildActivity(FragmentActivity.class).get();
|
||||
Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
Preference preference = new Preference(mApplication);
|
||||
Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
mActivityInfo.metaData.putString("com.android.settings.intent.action", "TestAction");
|
||||
@@ -637,9 +641,9 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
public void clickPreference_withUnresolvableIntent_shouldNotLaunchAnything() {
|
||||
ReflectionHelpers.setField(
|
||||
mImpl, "mPackageManager", RuntimeEnvironment.application.getPackageManager());
|
||||
mImpl, "mPackageManager", mApplication.getPackageManager());
|
||||
FragmentActivity activity = Robolectric.buildActivity(FragmentActivity.class).get();
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Preference preference = new Preference(mApplication);
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
mActivityInfo.metaData.putString("com.android.settings.intent.action", "TestAction");
|
||||
@@ -657,7 +661,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
|
||||
@Test
|
||||
public void clickPreference_providerTileWithPendingIntent_singleUser_executesPendingIntent() {
|
||||
final Preference preference = new SwitchPreference(RuntimeEnvironment.application);
|
||||
final Preference preference = new SwitchPreference(mApplication);
|
||||
Bundle metaData = new Bundle();
|
||||
metaData.putInt(META_DATA_PREFERENCE_TITLE, R.string.settings_label);
|
||||
metaData.putInt(META_DATA_PREFERENCE_SUMMARY, R.string.about_settings_summary);
|
||||
@@ -665,7 +669,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
metaData.putString(META_DATA_PREFERENCE_KEYHINT, KEY);
|
||||
final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE, metaData);
|
||||
PendingIntent pendingIntent =
|
||||
PendingIntent.getActivity(RuntimeEnvironment.application, 0, new Intent("test"), 0);
|
||||
PendingIntent.getActivity(mApplication, 0, new Intent("test"), 0);
|
||||
tile.pendingIntentMap.put(UserHandle.CURRENT, pendingIntent);
|
||||
|
||||
mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon,
|
||||
@@ -673,14 +677,14 @@ public class DashboardFeatureProviderImplTest {
|
||||
preference.performClick();
|
||||
|
||||
Intent nextStartedActivity =
|
||||
Shadows.shadowOf(RuntimeEnvironment.application).peekNextStartedActivity();
|
||||
Shadows.shadowOf(mApplication).peekNextStartedActivity();
|
||||
assertThat(nextStartedActivity).isNotNull();
|
||||
assertThat(nextStartedActivity.getAction()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clickPreference_providerTileWithPendingIntent_multiUser_showsProfileDialog() {
|
||||
final Preference preference = new SwitchPreference(RuntimeEnvironment.application);
|
||||
final Preference preference = new SwitchPreference(mApplication);
|
||||
Bundle metaData = new Bundle();
|
||||
metaData.putInt(META_DATA_PREFERENCE_TITLE, R.string.settings_label);
|
||||
metaData.putInt(META_DATA_PREFERENCE_SUMMARY, R.string.about_settings_summary);
|
||||
@@ -688,7 +692,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
metaData.putString(META_DATA_PREFERENCE_KEYHINT, KEY);
|
||||
final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE, metaData);
|
||||
PendingIntent pendingIntent =
|
||||
PendingIntent.getActivity(RuntimeEnvironment.application, 0, new Intent("test"), 0);
|
||||
PendingIntent.getActivity(mApplication, 0, new Intent("test"), 0);
|
||||
tile.pendingIntentMap.put(UserHandle.CURRENT, pendingIntent);
|
||||
tile.pendingIntentMap.put(new UserHandle(10), pendingIntent);
|
||||
|
||||
@@ -700,11 +704,10 @@ public class DashboardFeatureProviderImplTest {
|
||||
mActivity.getSupportFragmentManager().findFragmentByTag("select_profile");
|
||||
assertThat(dialogFragment).isNotNull();
|
||||
Intent nextStartedActivity =
|
||||
Shadows.shadowOf(RuntimeEnvironment.application).peekNextStartedActivity();
|
||||
Shadows.shadowOf(mApplication).peekNextStartedActivity();
|
||||
assertThat(nextStartedActivity).isNull();
|
||||
}
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Test
|
||||
public void openTileIntent_profileSelectionDialog_shouldShow() {
|
||||
ShadowUserManager.getShadow().addUser(10, "Someone", 0);
|
||||
@@ -721,7 +724,6 @@ public class DashboardFeatureProviderImplTest {
|
||||
verify(mActivity).getSupportFragmentManager();
|
||||
}
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Test
|
||||
public void openTileIntent_profileSelectionDialog_explicitMetadataShouldShow() {
|
||||
ShadowUserManager.getShadow().addUser(10, "Someone", 0);
|
||||
@@ -739,7 +741,6 @@ public class DashboardFeatureProviderImplTest {
|
||||
verify(mActivity).getSupportFragmentManager();
|
||||
}
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Test
|
||||
public void openTileIntent_profileSelectionDialog_shouldNotShow() {
|
||||
ShadowUserManager.getShadow().addUser(10, "Someone", 0);
|
||||
@@ -757,7 +758,6 @@ public class DashboardFeatureProviderImplTest {
|
||||
verify(mActivity, never()).getSupportFragmentManager();
|
||||
}
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Test
|
||||
public void openTileIntent_profileSelectionDialog_validUserHandleShouldNotShow() {
|
||||
final int userId = 10;
|
||||
@@ -780,7 +780,6 @@ public class DashboardFeatureProviderImplTest {
|
||||
verify(mActivity, never()).getSupportFragmentManager();
|
||||
}
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Test
|
||||
public void openTileIntent_profileSelectionDialog_invalidUserHandleShouldShow() {
|
||||
ShadowUserManager.getShadow().addUser(10, "Someone", 0);
|
||||
@@ -799,7 +798,6 @@ public class DashboardFeatureProviderImplTest {
|
||||
verify(mActivity).getSupportFragmentManager();
|
||||
}
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Test
|
||||
public void openTileIntent_profileSelectionDialog_unresolvableWorkProfileIntentShouldNotShow() {
|
||||
final int userId = 10;
|
||||
|
||||
@@ -49,7 +49,8 @@ import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.preference.SwitchPreferenceCompat;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
@@ -66,13 +67,13 @@ import com.android.settingslib.drawer.ProviderTile;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
@@ -86,6 +87,10 @@ import java.util.Map;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class DashboardFragmentTest {
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
private final Context mAppContext = ApplicationProvider.getApplicationContext();
|
||||
|
||||
@Mock
|
||||
private FakeFeatureFactory mFakeFeatureFactory;
|
||||
@@ -98,8 +103,7 @@ public class DashboardFragmentTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mContext = spy(mAppContext);
|
||||
final ActivityInfo activityInfo = new ActivityInfo();
|
||||
activityInfo.packageName = "pkg";
|
||||
activityInfo.name = "class";
|
||||
@@ -120,11 +124,11 @@ public class DashboardFragmentTest {
|
||||
mProviderTile = new ProviderTile(providerInfo, mDashboardCategory.key, metaData);
|
||||
mDashboardCategory.addTile(mProviderTile);
|
||||
|
||||
mTestFragment = new TestFragment(RuntimeEnvironment.application);
|
||||
mTestFragment = new TestFragment(mAppContext);
|
||||
when(mFakeFeatureFactory.dashboardFeatureProvider
|
||||
.getTilesForCategory(nullable(String.class)))
|
||||
.thenReturn(mDashboardCategory);
|
||||
mTestFragment.onAttach(RuntimeEnvironment.application);
|
||||
mTestFragment.onAttach(mAppContext);
|
||||
when(mContext.getPackageName()).thenReturn("TestPackage");
|
||||
mControllers = new ArrayList<>();
|
||||
}
|
||||
@@ -297,7 +301,7 @@ public class DashboardFragmentTest {
|
||||
preferenceControllers.add(mockController2);
|
||||
when(mockController1.isAvailable()).thenReturn(false);
|
||||
when(mockController2.isAvailable()).thenReturn(true);
|
||||
mTestFragment.onAttach(RuntimeEnvironment.application);
|
||||
mTestFragment.onAttach(mAppContext);
|
||||
mTestFragment.onResume();
|
||||
|
||||
verify(mockController1).getPreferenceKey();
|
||||
@@ -387,12 +391,11 @@ public class DashboardFragmentTest {
|
||||
assertThat(mTestFragment.mBlockerController).isNull();
|
||||
}
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Test
|
||||
public void createPreference_isProviderTile_returnSwitchPreference() {
|
||||
final Preference pref = mTestFragment.createPreference(mProviderTile);
|
||||
|
||||
assertThat(pref).isInstanceOf(SwitchPreference.class);
|
||||
assertThat(pref).isInstanceOf(SwitchPreferenceCompat.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -401,7 +404,7 @@ public class DashboardFragmentTest {
|
||||
|
||||
assertThat(pref).isInstanceOf(Preference.class);
|
||||
assertThat(pref).isNotInstanceOf(PrimarySwitchPreference.class);
|
||||
assertThat(pref).isNotInstanceOf(SwitchPreference.class);
|
||||
assertThat(pref).isNotInstanceOf(SwitchPreferenceCompat.class);
|
||||
assertThat(pref.getWidgetLayoutResource()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@@ -431,7 +434,7 @@ public class DashboardFragmentTest {
|
||||
|
||||
assertThat(pref).isInstanceOf(Preference.class);
|
||||
assertThat(pref).isNotInstanceOf(PrimarySwitchPreference.class);
|
||||
assertThat(pref).isNotInstanceOf(SwitchPreference.class);
|
||||
assertThat(pref).isNotInstanceOf(SwitchPreferenceCompat.class);
|
||||
assertThat(pref.getWidgetLayoutResource())
|
||||
.isEqualTo(R.layout.preference_external_action_icon);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.pm.UserProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.widget.TextView;
|
||||
@@ -42,16 +43,19 @@ import com.android.settingslib.drawer.Tile;
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ProfileSelectDialogTest {
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
private static final UserHandle NORMAL_USER = new UserHandle(1111);
|
||||
private static final UserHandle REMOVED_USER = new UserHandle(2222);
|
||||
@@ -67,11 +71,12 @@ public class ProfileSelectDialogTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
final UserInfo userInfo = new UserInfo(
|
||||
NORMAL_USER.getIdentifier(), "test_user", UserInfo.FLAG_RESTRICTED);
|
||||
when(mUserManager.getUserInfo(NORMAL_USER.getIdentifier())).thenReturn(userInfo);
|
||||
final UserProperties userProperties = new UserProperties.Builder().build();
|
||||
when(mUserManager.getUserProperties(NORMAL_USER)).thenReturn(userProperties);
|
||||
mActivityInfo = new ActivityInfo();
|
||||
mActivityInfo.packageName = "pkg";
|
||||
mActivityInfo.name = "cls";
|
||||
@@ -89,7 +94,6 @@ public class ProfileSelectDialogTest {
|
||||
verify(mUserManager, never()).getUserInfo(NORMAL_USER.getIdentifier());
|
||||
}
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Test
|
||||
public void updateUserHandlesIfNeeded_Remove() {
|
||||
final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
@@ -105,7 +109,6 @@ public class ProfileSelectDialogTest {
|
||||
verify(mUserManager, times(2)).getUserInfo(REMOVED_USER.getIdentifier());
|
||||
}
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Test
|
||||
public void updateUserHandlesIfNeeded_removesCloneProfile() {
|
||||
final UserInfo userInfo = new UserInfo(CLONE_USER.getIdentifier(), "clone_user", null,
|
||||
@@ -122,7 +125,6 @@ public class ProfileSelectDialogTest {
|
||||
verify(mUserManager, times(1)).getUserInfo(CLONE_USER.getIdentifier());
|
||||
}
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Test
|
||||
public void updatePendingIntentsIfNeeded_removesUsersWithNoPendingIntentsAndCloneProfile() {
|
||||
final UserInfo userInfo = new UserInfo(CLONE_USER.getIdentifier(), "clone_user", null,
|
||||
|
||||
@@ -16,27 +16,58 @@
|
||||
|
||||
package com.android.settings.dashboard.profileselector;
|
||||
|
||||
import static android.os.UserManager.USER_TYPE_FULL_SYSTEM;
|
||||
import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
|
||||
import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE;
|
||||
|
||||
import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.EXTRA_PROFILE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.pm.UserInfo;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@Ignore("b/313569889")
|
||||
@Config(shadows = {
|
||||
ShadowUserManager.class,
|
||||
})
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ProfileSelectLocationFragmentTest {
|
||||
private static final String PERSONAL_PROFILE_NAME = "personal";
|
||||
private static final String WORK_PROFILE_NAME = "work";
|
||||
private static final String PRIVATE_PROFILE_NAME = "private";
|
||||
@Rule
|
||||
public final MockitoRule rule = MockitoJUnit.rule();
|
||||
|
||||
private ShadowUserManager mUserManager;
|
||||
private ProfileSelectLocationFragment mProfileSelectLocationFragment;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mProfileSelectLocationFragment = new ProfileSelectLocationFragment();
|
||||
mUserManager = ShadowUserManager.getShadow();
|
||||
mUserManager.addProfile(
|
||||
new UserInfo(0, PERSONAL_PROFILE_NAME, null, 0, USER_TYPE_FULL_SYSTEM));
|
||||
mUserManager.addProfile(
|
||||
new UserInfo(1, WORK_PROFILE_NAME, null, 0, USER_TYPE_PROFILE_MANAGED));
|
||||
mUserManager.addProfile(
|
||||
new UserInfo(11, PRIVATE_PROFILE_NAME, null, 0, USER_TYPE_PROFILE_PRIVATE));
|
||||
mProfileSelectLocationFragment = spy(new ProfileSelectLocationFragment());
|
||||
when(mProfileSelectLocationFragment.getContext()).thenReturn(
|
||||
ApplicationProvider.getApplicationContext());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -46,7 +77,7 @@ public class ProfileSelectLocationFragmentTest {
|
||||
EXTRA_PROFILE, -1)).isEqualTo(ProfileSelectFragment.ProfileType.PERSONAL);
|
||||
assertThat(mProfileSelectLocationFragment.getFragments()[1].getArguments().getInt(
|
||||
EXTRA_PROFILE, -1)).isEqualTo(ProfileSelectFragment.ProfileType.WORK);
|
||||
assertThat(mProfileSelectLocationFragment.getFragments()[1].getArguments().getInt(
|
||||
assertThat(mProfileSelectLocationFragment.getFragments()[2].getArguments().getInt(
|
||||
EXTRA_PROFILE, -1)).isEqualTo(ProfileSelectFragment.ProfileType.PRIVATE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.datausage
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.NetworkTemplate
|
||||
import android.os.Bundle
|
||||
import android.os.UserManager
|
||||
import android.provider.Settings
|
||||
import androidx.preference.Preference
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.settings.datausage.DataUsageListTest.ShadowDataUsageBaseFragment
|
||||
import com.android.settings.datausage.TemplatePreference.NetworkServices
|
||||
import com.android.settings.datausage.lib.BillingCycleRepository
|
||||
import com.android.settings.testutils.FakeFeatureFactory
|
||||
import com.android.settingslib.NetworkPolicyEditor
|
||||
import com.android.settingslib.core.AbstractPreferenceController
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.doNothing
|
||||
import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.mockito.Spy
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoRule
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.robolectric.annotation.Implementation
|
||||
import org.robolectric.annotation.Implements
|
||||
import org.robolectric.util.ReflectionHelpers
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(shadows = [ShadowDataUsageBaseFragment::class])
|
||||
class DataUsageListTest {
|
||||
@get:Rule
|
||||
val mockito: MockitoRule = MockitoJUnit.rule()
|
||||
|
||||
@Mock
|
||||
private lateinit var networkServices: NetworkServices
|
||||
|
||||
@Mock
|
||||
private lateinit var userManager: UserManager
|
||||
|
||||
@Mock
|
||||
private lateinit var billingCycleRepository: BillingCycleRepository
|
||||
|
||||
@Mock
|
||||
private lateinit var dataUsageListHeaderController: DataUsageListHeaderController
|
||||
|
||||
@Spy
|
||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
|
||||
@Spy
|
||||
private val dataUsageList = TestDataUsageList()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
FakeFeatureFactory.setupForTest()
|
||||
networkServices.mPolicyEditor = mock(NetworkPolicyEditor::class.java)
|
||||
doReturn(context).`when`(dataUsageList).context
|
||||
doReturn(userManager).`when`(context).getSystemService(UserManager::class.java)
|
||||
doReturn(false).`when`(userManager).isGuestUser
|
||||
ReflectionHelpers.setField(dataUsageList, "services", networkServices)
|
||||
doNothing().`when`(dataUsageList).updateSubscriptionInfoEntity()
|
||||
`when`(billingCycleRepository.isBandwidthControlEnabled()).thenReturn(true)
|
||||
dataUsageList.dataUsageListHeaderController = dataUsageListHeaderController
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onCreate_isNotGuestUser_shouldNotFinish() {
|
||||
dataUsageList.template = mock<NetworkTemplate>(NetworkTemplate::class.java)
|
||||
doReturn(false).`when`(userManager).isGuestUser
|
||||
doNothing().`when`(dataUsageList).processArgument()
|
||||
dataUsageList.onCreate(null)
|
||||
verify(dataUsageList, never()).finish()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onCreate_isGuestUser_shouldFinish() {
|
||||
doReturn(true).`when`(userManager).isGuestUser
|
||||
dataUsageList.onCreate(null)
|
||||
verify(dataUsageList).finish()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun processArgument_shouldGetTemplateFromArgument() {
|
||||
val args = Bundle()
|
||||
args.putParcelable(
|
||||
DataUsageList.EXTRA_NETWORK_TEMPLATE, mock(
|
||||
NetworkTemplate::class.java
|
||||
)
|
||||
)
|
||||
args.putInt(DataUsageList.EXTRA_SUB_ID, 3)
|
||||
dataUsageList.arguments = args
|
||||
dataUsageList.processArgument()
|
||||
assertThat(dataUsageList.template).isNotNull()
|
||||
assertThat(dataUsageList.subId).isEqualTo(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun processArgument_fromIntent_shouldGetTemplateFromIntent() {
|
||||
val intent = Intent()
|
||||
intent.putExtra(
|
||||
Settings.EXTRA_NETWORK_TEMPLATE, mock(
|
||||
NetworkTemplate::class.java
|
||||
)
|
||||
)
|
||||
intent.putExtra(Settings.EXTRA_SUB_ID, 3)
|
||||
doReturn(intent).`when`(dataUsageList).intent
|
||||
dataUsageList.processArgument()
|
||||
assertThat(dataUsageList.template).isNotNull()
|
||||
assertThat(dataUsageList.subId).isEqualTo(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updatePolicy_setConfigButtonVisible() {
|
||||
dataUsageList.template = mock(NetworkTemplate::class.java)
|
||||
dataUsageList.onCreate(null)
|
||||
|
||||
dataUsageList.updatePolicy()
|
||||
|
||||
verify(dataUsageListHeaderController).setConfigButtonVisible(true)
|
||||
}
|
||||
|
||||
@Implements(DataUsageBaseFragment::class)
|
||||
class ShadowDataUsageBaseFragment {
|
||||
@Implementation
|
||||
fun onCreate(@Suppress("UNUSED_PARAMETER") icicle: Bundle?) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
open inner class TestDataUsageList : DataUsageList() {
|
||||
override fun <T : AbstractPreferenceController?> use(clazz: Class<T>): T = mock(clazz)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : Preference?> findPreference(key: CharSequence): T =
|
||||
mock(Preference::class.java) as T
|
||||
|
||||
public override fun getIntent() = Intent()
|
||||
|
||||
override fun createBillingCycleRepository() = billingCycleRepository
|
||||
|
||||
override fun isBillingCycleModifiable() = true
|
||||
}
|
||||
}
|
||||
@@ -1,352 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.datausage;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.NetworkTemplate;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.SubscriptionPlan;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.RecurrenceRule;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settingslib.net.DataUsageController;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = ShadowEntityHeaderController.class)
|
||||
public class DataUsageSummaryPreferenceControllerTest {
|
||||
|
||||
private static final long UPDATE_BACKOFF_MS = TimeUnit.MINUTES.toMillis(13);
|
||||
private static final long CYCLE_BACKOFF_MS = TimeUnit.DAYS.toMillis(6);
|
||||
private static final long CYCLE_LENGTH_MS = TimeUnit.DAYS.toMillis(30);
|
||||
private static final long USAGE1 = 373 * BillingCycleSettings.MIB_IN_BYTES;
|
||||
private static final long LIMIT1 = BillingCycleSettings.GIB_IN_BYTES;
|
||||
private static final String CARRIER_NAME = "z-mobile";
|
||||
private static final String PERIOD = "Feb";
|
||||
|
||||
@Mock
|
||||
private DataUsageController mDataUsageController;
|
||||
@Mock
|
||||
private DataUsageSummaryPreference mSummaryPreference;
|
||||
@Mock
|
||||
private NetworkTemplate mNetworkTemplate;
|
||||
@Mock
|
||||
private SubscriptionInfo mSubscriptionInfo;
|
||||
@Mock
|
||||
private SubscriptionPlan mSubscriptionPlan;
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private EntityHeaderController mHeaderController;
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
@Mock
|
||||
private PackageManager mPm;
|
||||
|
||||
private DataUsageInfoController mDataInfoController;
|
||||
|
||||
private FakeFeatureFactory mFactory;
|
||||
private FragmentActivity mActivity;
|
||||
private Context mContext;
|
||||
private DataUsageSummaryPreferenceController mController;
|
||||
private int mDefaultSubscriptionId;
|
||||
private List<SubscriptionPlan> mSubscriptionPlans;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
|
||||
doReturn("%1$s %2%s").when(mContext)
|
||||
.getString(com.android.internal.R.string.fileSizeSuffix);
|
||||
|
||||
mDefaultSubscriptionId = 1234;
|
||||
mSubscriptionPlans = new ArrayList<SubscriptionPlan>();
|
||||
|
||||
mFactory = FakeFeatureFactory.setupForTest();
|
||||
when(mFactory.metricsFeatureProvider.getMetricsCategory(any(Object.class)))
|
||||
.thenReturn(MetricsProto.MetricsEvent.SETTINGS_APP_NOTIF_CATEGORY);
|
||||
ShadowEntityHeaderController.setUseMock(mHeaderController);
|
||||
|
||||
mDataInfoController = spy(new DataUsageInfoController());
|
||||
doReturn(-1L).when(mDataInfoController).getSummaryLimit(any());
|
||||
|
||||
mActivity = spy(Robolectric.buildActivity(FragmentActivity.class).get());
|
||||
doReturn(mTelephonyManager).when(mActivity).getSystemService(TelephonyManager.class);
|
||||
doReturn(mTelephonyManager).when(mTelephonyManager)
|
||||
.createForSubscriptionId(mDefaultSubscriptionId);
|
||||
doReturn(mPm).when(mActivity).getPackageManager();
|
||||
doReturn(TelephonyManager.SIM_STATE_READY).when(mTelephonyManager).getSimState();
|
||||
|
||||
mController = spy(new DataUsageSummaryPreferenceController(
|
||||
mDataUsageController,
|
||||
mDataInfoController,
|
||||
mNetworkTemplate,
|
||||
mActivity, mDefaultSubscriptionId));
|
||||
doReturn(null).when(mController).getSubscriptionInfo(
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
doReturn(null).when(mController).getSubscriptionPlans(
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
|
||||
doReturn(CARRIER_NAME).when(mSubscriptionInfo).getCarrierName();
|
||||
doReturn(mSubscriptionInfo).when(mController).getSubscriptionInfo(mDefaultSubscriptionId);
|
||||
doReturn(mSubscriptionPlans).when(mController).getSubscriptionPlans(mDefaultSubscriptionId);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowEntityHeaderController.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSummaryUpdate_onePlan_basic() {
|
||||
final long now = System.currentTimeMillis();
|
||||
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||
|
||||
doReturn(info).when(mDataUsageController).getDataUsageInfo(any());
|
||||
setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS);
|
||||
createTestDataPlan(info.cycleStart, info.cycleEnd);
|
||||
|
||||
mController.updateState(mSummaryPreference);
|
||||
|
||||
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
|
||||
verify(mSummaryPreference).setLimitInfo(captor.capture());
|
||||
CharSequence value = captor.getValue();
|
||||
assertThat(value.toString()).isEqualTo("512 MB data warning / 1.00 GB data limit");
|
||||
|
||||
// TODO (b/170330084): return intent instead of null for mSummaryPreference
|
||||
verify(mSummaryPreference).setUsageInfo((info.cycleEnd / 1000) * 1000,
|
||||
now - UPDATE_BACKOFF_MS,
|
||||
CARRIER_NAME, 1 /* numPlans */);
|
||||
verify(mSummaryPreference).setChartEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSummaryUpdate_noPlan_basic() {
|
||||
final long now = System.currentTimeMillis();
|
||||
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||
|
||||
doReturn(info).when(mDataUsageController).getDataUsageInfo(any());
|
||||
setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS);
|
||||
|
||||
mController.updateState(mSummaryPreference);
|
||||
|
||||
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
|
||||
verify(mSummaryPreference).setLimitInfo(captor.capture());
|
||||
CharSequence value = captor.getValue();
|
||||
assertThat(value.toString()).isEqualTo("512 MB data warning / 1.00 GB data limit");
|
||||
|
||||
verify(mSummaryPreference).setUsageInfo(
|
||||
info.cycleEnd,
|
||||
-1L /* snapshotTime */,
|
||||
CARRIER_NAME,
|
||||
0 /* numPlans */);
|
||||
verify(mSummaryPreference).setChartEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSummaryUpdate_noCarrier_basic() {
|
||||
final long now = System.currentTimeMillis();
|
||||
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||
|
||||
doReturn(info).when(mDataUsageController).getDataUsageInfo(any());
|
||||
doReturn(null).when(mSubscriptionInfo).getCarrierName();
|
||||
setupTestDataUsage(LIMIT1, USAGE1, -1L /* snapshotTime */);
|
||||
|
||||
mController.updateState(mSummaryPreference);
|
||||
|
||||
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
|
||||
verify(mSummaryPreference).setLimitInfo(captor.capture());
|
||||
CharSequence value = captor.getValue();
|
||||
assertThat(value.toString()).isEqualTo("512 MB data warning / 1.00 GB data limit");
|
||||
|
||||
verify(mSummaryPreference).setUsageInfo(
|
||||
info.cycleEnd,
|
||||
-1L /* snapshotTime */,
|
||||
null /* carrierName */,
|
||||
0 /* numPlans */);
|
||||
verify(mSummaryPreference).setChartEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSummaryUpdate_noPlanData_basic() {
|
||||
final long now = System.currentTimeMillis();
|
||||
|
||||
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||
|
||||
doReturn(info).when(mDataUsageController).getDataUsageInfo(any());
|
||||
doReturn(null).when(mSubscriptionInfo).getCarrierName();
|
||||
setupTestDataUsage(-1L /* dataPlanSize */, USAGE1, -1L /* snapshotTime */);
|
||||
|
||||
mController.updateState(mSummaryPreference);
|
||||
|
||||
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
|
||||
verify(mSummaryPreference).setLimitInfo(captor.capture());
|
||||
CharSequence value = captor.getValue();
|
||||
assertThat(value.toString()).isEqualTo("512 MB data warning / 1.00 GB data limit");
|
||||
verify(mSummaryPreference).setUsageInfo(
|
||||
info.cycleEnd,
|
||||
-1L /* snapshotTime */,
|
||||
null /* carrierName */,
|
||||
0 /* numPlans */);
|
||||
verify(mSummaryPreference).setChartEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSummaryUpdate_noLimitNoWarning() {
|
||||
final long now = System.currentTimeMillis();
|
||||
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||
info.warningLevel = 0L;
|
||||
info.limitLevel = 0L;
|
||||
|
||||
doReturn(info).when(mDataUsageController).getDataUsageInfo(any());
|
||||
setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS);
|
||||
|
||||
mController.updateState(mSummaryPreference);
|
||||
verify(mSummaryPreference).setLimitInfo(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSummaryUpdate_warningOnly() {
|
||||
final long now = System.currentTimeMillis();
|
||||
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||
info.warningLevel = BillingCycleSettings.MIB_IN_BYTES;
|
||||
info.limitLevel = 0L;
|
||||
|
||||
doReturn(info).when(mDataUsageController).getDataUsageInfo(any());
|
||||
setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS);
|
||||
|
||||
mController.updateState(mSummaryPreference);
|
||||
|
||||
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
|
||||
verify(mSummaryPreference).setLimitInfo(captor.capture());
|
||||
CharSequence value = captor.getValue();
|
||||
assertThat(value.toString()).isEqualTo("1.00 MB data warning");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSummaryUpdate_limitOnly() {
|
||||
final long now = System.currentTimeMillis();
|
||||
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||
info.warningLevel = 0L;
|
||||
info.limitLevel = BillingCycleSettings.MIB_IN_BYTES;
|
||||
|
||||
doReturn(info).when(mDataUsageController).getDataUsageInfo(any());
|
||||
setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS);
|
||||
|
||||
mController.updateState(mSummaryPreference);
|
||||
|
||||
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
|
||||
verify(mSummaryPreference).setLimitInfo(captor.capture());
|
||||
CharSequence value = captor.getValue();
|
||||
assertThat(value.toString()).isEqualTo("1.00 MB data limit");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSummaryUpdate_limitAndWarning() {
|
||||
final long now = System.currentTimeMillis();
|
||||
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||
info.warningLevel = BillingCycleSettings.MIB_IN_BYTES;
|
||||
info.limitLevel = BillingCycleSettings.MIB_IN_BYTES;
|
||||
|
||||
doReturn(info).when(mDataUsageController).getDataUsageInfo(any());
|
||||
setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS);
|
||||
|
||||
mController.updateState(mSummaryPreference);
|
||||
|
||||
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
|
||||
verify(mSummaryPreference).setLimitInfo(captor.capture());
|
||||
CharSequence value = captor.getValue();
|
||||
assertThat(value.toString()).isEqualTo("1.00 MB data warning / 1.00 MB data limit");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMobileData_preferenceAvailable() {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMobileData_noSim_preferenceDisabled() {
|
||||
final int subscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
mController.init(subscriptionId);
|
||||
mController.mDataUsageController = mDataUsageController;
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
private DataUsageController.DataUsageInfo createTestDataUsageInfo(long now) {
|
||||
DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
|
||||
info.carrier = CARRIER_NAME;
|
||||
info.period = PERIOD;
|
||||
info.startDate = now;
|
||||
info.limitLevel = LIMIT1;
|
||||
info.warningLevel = LIMIT1 >> 1;
|
||||
info.usageLevel = USAGE1;
|
||||
info.cycleStart = now - CYCLE_BACKOFF_MS;
|
||||
info.cycleEnd = info.cycleStart + CYCLE_LENGTH_MS;
|
||||
return info;
|
||||
}
|
||||
|
||||
private void setupTestDataUsage(long dataPlanSize, long dataUsageSize, long snapshotTime) {
|
||||
doReturn(dataPlanSize).when(mSubscriptionPlan).getDataLimitBytes();
|
||||
doReturn(dataUsageSize).when(mSubscriptionPlan).getDataUsageBytes();
|
||||
doReturn(snapshotTime).when(mSubscriptionPlan).getDataUsageTime();
|
||||
|
||||
doReturn(dataPlanSize).when(mDataInfoController).getSummaryLimit(any());
|
||||
}
|
||||
|
||||
private void createTestDataPlan(long startTime, long endTime) {
|
||||
final RecurrenceRule recurrenceRule = new RecurrenceRule(
|
||||
Instant.ofEpochMilli(startTime).atZone(ZoneId.systemDefault()),
|
||||
Instant.ofEpochMilli(endTime).atZone(ZoneId.systemDefault()),
|
||||
null);
|
||||
doReturn(recurrenceRule).when(mSubscriptionPlan).getCycleRule();
|
||||
mSubscriptionPlans.add(mSubscriptionPlan);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -163,6 +164,81 @@ public class UnrestrictedDataAccessPreferenceControllerTest {
|
||||
mController.onRebuildComplete(createAppEntries(testPkg1, testPkg2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebuildComplete_ecmRestricted_shouldBeDisabled() {
|
||||
mFragment = spy(new UnrestrictedDataAccess());
|
||||
mContext = spy(mContext);
|
||||
doNothing().when(mFragment).setLoading(anyBoolean(), anyBoolean());
|
||||
mController.setParentFragment(mFragment);
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
mPreferenceScreen = spy(mPreferenceManager.createPreferenceScreen(mContext));
|
||||
doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
|
||||
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
|
||||
doReturn(0).when(mPreferenceScreen).getPreferenceCount();
|
||||
final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
|
||||
ReflectionHelpers.setField(mController, "mDataSaverBackend", dataSaverBackend);
|
||||
ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen);
|
||||
|
||||
final String testPkg = "com.example.disabled";
|
||||
doNothing().when(mContext).startActivity(any());
|
||||
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(testPkg);
|
||||
|
||||
doAnswer((invocation) -> {
|
||||
final UnrestrictedDataAccessPreference preference = invocation.getArgument(0);
|
||||
// Verify preference is disabled by ecm and the summary is changed accordingly.
|
||||
assertThat(preference.isDisabledByEcm()).isTrue();
|
||||
assertThat(preference.getSummary().toString()).isEqualTo(
|
||||
mContext.getString(
|
||||
com.android.settingslib.R.string.disabled_by_app_ops_text));
|
||||
assertThat(preference.isChecked()).isFalse();
|
||||
preference.performClick();
|
||||
// Verify that when the preference is clicked, ecm details intent is launched
|
||||
assertThat(preference.isChecked()).isFalse();
|
||||
verify(mContext).startActivity(any());
|
||||
|
||||
return null;
|
||||
}).when(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
|
||||
|
||||
mController.onRebuildComplete(createAppEntries(testPkg));
|
||||
verify(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebuildComplete_ecmNotRestricted_notDisabled() {
|
||||
mFragment = spy(new UnrestrictedDataAccess());
|
||||
mContext = spy(mContext);
|
||||
doNothing().when(mFragment).setLoading(anyBoolean(), anyBoolean());
|
||||
mController.setParentFragment(mFragment);
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
mPreferenceScreen = spy(mPreferenceManager.createPreferenceScreen(mContext));
|
||||
doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
|
||||
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
|
||||
doReturn(0).when(mPreferenceScreen).getPreferenceCount();
|
||||
final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
|
||||
ReflectionHelpers.setField(mController, "mDataSaverBackend", dataSaverBackend);
|
||||
ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen);
|
||||
|
||||
final String testPkg = "com.example.enabled";
|
||||
doNothing().when(mContext).startActivity(any());
|
||||
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
|
||||
|
||||
doAnswer((invocation) -> {
|
||||
final UnrestrictedDataAccessPreference preference = invocation.getArgument(0);
|
||||
assertThat(preference.isDisabledByEcm()).isFalse();
|
||||
assertThat(preference.getSummary()).isEqualTo("");
|
||||
assertThat(preference.isChecked()).isFalse();
|
||||
preference.performClick();
|
||||
// Verify that when the preference is clicked, ecm details intent is not launched
|
||||
assertThat(preference.isChecked()).isTrue();
|
||||
verify(mContext, never()).startActivity(any());
|
||||
|
||||
return null;
|
||||
}).when(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
|
||||
|
||||
mController.onRebuildComplete(createAppEntries(testPkg));
|
||||
verify(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
|
||||
}
|
||||
|
||||
private ArrayList<AppEntry> createAppEntries(String... packageNames) {
|
||||
final ArrayList<AppEntry> appEntries = new ArrayList<>();
|
||||
for (int i = 0; i < packageNames.length; ++i) {
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.development;
|
||||
|
||||
import static com.android.settings.development.BluetoothLeAudioModePreferenceController
|
||||
.LE_AUDIO_DYNAMIC_SWITCHER_MODE_PROPERTY;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.Context;
|
||||
import android.os.SystemProperties;
|
||||
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class BluetoothLeAudioModePreferenceControllerTest {
|
||||
|
||||
@Mock
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
@Mock
|
||||
private DevelopmentSettingsDashboardFragment mFragment;
|
||||
@Mock
|
||||
private BluetoothAdapter mBluetoothAdapter;
|
||||
@Mock
|
||||
private ListPreference mPreference;
|
||||
|
||||
private Context mContext;
|
||||
private BluetoothLeAudioModePreferenceController mController;
|
||||
private String[] mListValues;
|
||||
private String[] mListSummaries;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mListValues = mContext.getResources().getStringArray(
|
||||
R.array.bluetooth_leaudio_mode_values);
|
||||
mListSummaries = mContext.getResources().getStringArray(
|
||||
R.array.bluetooth_leaudio_mode);
|
||||
mController = spy(new BluetoothLeAudioModePreferenceController(mContext, mFragment));
|
||||
when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
|
||||
.thenReturn(mPreference);
|
||||
mController.mBluetoothAdapter = mBluetoothAdapter;
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebootDialogConfirmed_changeLeAudioMode_shouldSetLeAudioMode() {
|
||||
mController.mChanged = true;
|
||||
SystemProperties.set(LE_AUDIO_DYNAMIC_SWITCHER_MODE_PROPERTY, mListValues[0]);
|
||||
mController.mNewMode = mListValues[1];
|
||||
|
||||
mController.onRebootDialogConfirmed();
|
||||
assertThat(SystemProperties.get(LE_AUDIO_DYNAMIC_SWITCHER_MODE_PROPERTY, mListValues[0])
|
||||
.equals(mController.mNewMode)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebootDialogConfirmed_notChangeLeAudioMode_shouldNotSetLeAudioMode() {
|
||||
mController.mChanged = false;
|
||||
SystemProperties.set(LE_AUDIO_DYNAMIC_SWITCHER_MODE_PROPERTY, mListValues[0]);
|
||||
mController.mNewMode = mListValues[1];
|
||||
|
||||
mController.onRebootDialogConfirmed();
|
||||
assertThat(SystemProperties.get(LE_AUDIO_DYNAMIC_SWITCHER_MODE_PROPERTY, mListValues[0])
|
||||
.equals(mController.mNewMode)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebootDialogCanceled_shouldNotSetLeAudioMode() {
|
||||
mController.mChanged = true;
|
||||
SystemProperties.set(LE_AUDIO_DYNAMIC_SWITCHER_MODE_PROPERTY, mListValues[0]);
|
||||
mController.mNewMode = mListValues[1];
|
||||
|
||||
mController.onRebootDialogCanceled();
|
||||
assertThat(SystemProperties.get(LE_AUDIO_DYNAMIC_SWITCHER_MODE_PROPERTY, mListValues[0])
|
||||
.equals(mController.mNewMode)).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.development;
|
||||
|
||||
import static android.hardware.display.DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED;
|
||||
|
||||
import static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE;
|
||||
import static com.android.settings.development.ForcePeakRefreshRatePreferenceController.NO_CONFIG;
|
||||
|
||||
@@ -24,19 +26,28 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.provider.Settings;
|
||||
import android.testing.TestableContext;
|
||||
import android.view.Display;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.android.server.display.feature.flags.Flags;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@@ -46,14 +57,51 @@ public class ForcePeakRefreshRatePreferenceControllerTest {
|
||||
private SwitchPreference mPreference;
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
@Mock
|
||||
private DisplayManager mDisplayManagerMock;
|
||||
@Mock
|
||||
private Display mDisplayMock;
|
||||
@Mock
|
||||
private Display mDisplayMock2;
|
||||
|
||||
private Context mContext;
|
||||
private ForcePeakRefreshRatePreferenceController mController;
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
@Rule
|
||||
public final TestableContext mContext = new TestableContext(
|
||||
InstrumentationRegistry.getInstrumentation().getContext());
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mContext.addMockSystemService(DisplayManager.class, mDisplayManagerMock);
|
||||
|
||||
Display.Mode[] modes = new Display.Mode[]{
|
||||
new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600,
|
||||
/* refreshRate= */ 60),
|
||||
new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600,
|
||||
/* refreshRate= */ 120),
|
||||
new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600,
|
||||
/* refreshRate= */ 90)
|
||||
};
|
||||
when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(mDisplayMock);
|
||||
when(mDisplayMock.getSupportedModes()).thenReturn(modes);
|
||||
|
||||
Display.Mode[] modes2 = new Display.Mode[]{
|
||||
new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600,
|
||||
/* refreshRate= */ 70),
|
||||
new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600,
|
||||
/* refreshRate= */ 130),
|
||||
new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600,
|
||||
/* refreshRate= */ 80)
|
||||
};
|
||||
when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY + 1)).thenReturn(mDisplayMock2);
|
||||
when(mDisplayMock2.getSupportedModes()).thenReturn(modes2);
|
||||
|
||||
when(mDisplayManagerMock.getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED))
|
||||
.thenReturn(new Display[]{ mDisplayMock, mDisplayMock2 });
|
||||
|
||||
mController = new ForcePeakRefreshRatePreferenceController(mContext);
|
||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
|
||||
when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
|
||||
@@ -61,7 +109,19 @@ public class ForcePeakRefreshRatePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_preferenceChecked_shouldEnableForcePeak() {
|
||||
@RequiresFlagsDisabled(Flags.FLAG_BACK_UP_SMOOTH_DISPLAY_AND_FORCE_PEAK_REFRESH_RATE)
|
||||
public void onPreferenceChange_preferenceChecked_shouldEnableForcePeak_featureFlagOff() {
|
||||
mController.mPeakRefreshRate = 88f;
|
||||
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
|
||||
assertThat(Settings.System.getFloat(mContext.getContentResolver(),
|
||||
Settings.System.MIN_REFRESH_RATE, NO_CONFIG)).isEqualTo(88f);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_BACK_UP_SMOOTH_DISPLAY_AND_FORCE_PEAK_REFRESH_RATE)
|
||||
public void onPreferenceChange_preferenceChecked_shouldEnableForcePeak_featureFlagOn() {
|
||||
mController.mPeakRefreshRate = 88f;
|
||||
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
@@ -88,6 +148,7 @@ public class ForcePeakRefreshRatePreferenceControllerTest {
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference).setChecked(true);
|
||||
assertThat(mController.isForcePeakRefreshRateEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -98,6 +159,7 @@ public class ForcePeakRefreshRatePreferenceControllerTest {
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference).setChecked(false);
|
||||
assertThat(mController.isForcePeakRefreshRateEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,4 +191,16 @@ public class ForcePeakRefreshRatePreferenceControllerTest {
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsDisabled(Flags.FLAG_BACK_UP_SMOOTH_DISPLAY_AND_FORCE_PEAK_REFRESH_RATE)
|
||||
public void peakRefreshRate_highestOfDefaultDisplay_featureFlagOff() {
|
||||
assertThat(mController.mPeakRefreshRate).isEqualTo(120);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_BACK_UP_SMOOTH_DISPLAY_AND_FORCE_PEAK_REFRESH_RATE)
|
||||
public void peakRefreshRate_highestOfAllDisplays_featureFlagOn() {
|
||||
assertThat(mController.mPeakRefreshRate).isEqualTo(130);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* 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 com.android.settings.development;
|
||||
|
||||
import static com.android.settings.development.GameDefaultFrameRatePreferenceController.Injector;
|
||||
import static com.android.settings.development.GameDefaultFrameRatePreferenceController.PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.IGameManagerService;
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.TwoStatePreference;
|
||||
|
||||
import com.android.settings.flags.Flags;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class GameDefaultFrameRatePreferenceControllerTest {
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
@Mock
|
||||
private TwoStatePreference mPreference;
|
||||
@Mock
|
||||
private IGameManagerService mGameManagerService;
|
||||
@Mock
|
||||
private DevelopmentSystemPropertiesWrapper mSysPropsMock;
|
||||
|
||||
private GameDefaultFrameRatePreferenceController mController;
|
||||
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = new GameDefaultFrameRatePreferenceController(mContext, mGameManagerService,
|
||||
new Injector(){
|
||||
@Override
|
||||
public DevelopmentSystemPropertiesWrapper createSystemPropertiesWrapper() {
|
||||
return mSysPropsMock;
|
||||
}
|
||||
});
|
||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
|
||||
mController.displayPreference(mScreen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_settingEnabled_shouldChecked() throws RemoteException {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_DEVELOPMENT_GAME_DEFAULT_FRAME_RATE);
|
||||
assertTrue(mController.isAvailable());
|
||||
when(mSysPropsMock.getBoolean(
|
||||
ArgumentMatchers.eq(PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED),
|
||||
ArgumentMatchers.eq(false)))
|
||||
.thenReturn(true);
|
||||
|
||||
mController.onPreferenceChange(mPreference, true /* new value */);
|
||||
verify(mPreference).setChecked(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_settingDisabled_shouldUnchecked() throws RemoteException {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_DEVELOPMENT_GAME_DEFAULT_FRAME_RATE);
|
||||
assertTrue(mController.isAvailable());
|
||||
when(mSysPropsMock.getBoolean(
|
||||
ArgumentMatchers.eq(PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED),
|
||||
ArgumentMatchers.eq(false)))
|
||||
.thenReturn(false);
|
||||
mController.onPreferenceChange(mPreference, false /* new value */);
|
||||
verify(mPreference).setChecked(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_settingEnabled_shouldChecked() throws RemoteException {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_DEVELOPMENT_GAME_DEFAULT_FRAME_RATE);
|
||||
assertTrue(mController.isAvailable());
|
||||
when(mSysPropsMock.getBoolean(
|
||||
ArgumentMatchers.eq(PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED),
|
||||
ArgumentMatchers.eq(false)))
|
||||
.thenReturn(true);
|
||||
mController.updateState(mPreference);
|
||||
verify(mPreference).setChecked(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_settingDisabled_shouldUnchecked() throws RemoteException {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_DEVELOPMENT_GAME_DEFAULT_FRAME_RATE);
|
||||
assertTrue(mController.isAvailable());
|
||||
when(mSysPropsMock.getBoolean(
|
||||
ArgumentMatchers.eq(PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED),
|
||||
ArgumentMatchers.eq(false)))
|
||||
.thenReturn(false);
|
||||
mController.updateState(mPreference);
|
||||
verify(mPreference).setChecked(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void settingNotAvailable_flagsOff() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_DEVELOPMENT_GAME_DEFAULT_FRAME_RATE);
|
||||
mController = new GameDefaultFrameRatePreferenceController(
|
||||
mContext, mGameManagerService, new Injector());
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void settingAvailable_flagsOn() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_DEVELOPMENT_GAME_DEFAULT_FRAME_RATE);
|
||||
mController = new GameDefaultFrameRatePreferenceController(
|
||||
mContext, mGameManagerService, new Injector());
|
||||
assertTrue(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeveloperOptionsSwitchDisabled_preferenceUnchecked_shouldNotTurnOffPreference()
|
||||
throws RemoteException {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_DEVELOPMENT_GAME_DEFAULT_FRAME_RATE);
|
||||
when(mSysPropsMock.getBoolean(
|
||||
ArgumentMatchers.eq(PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED),
|
||||
ArgumentMatchers.eq(false)))
|
||||
.thenReturn(false);
|
||||
assertTrue(mController.isAvailable());
|
||||
when(mPreference.isChecked()).thenReturn(false);
|
||||
mController.onDeveloperOptionsSwitchDisabled();
|
||||
|
||||
verify(mPreference).setChecked(false);
|
||||
verify(mPreference).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeveloperOptionsSwitchDisabled_preferenceChecked_shouldTurnOffPreference()
|
||||
throws RemoteException {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_DEVELOPMENT_GAME_DEFAULT_FRAME_RATE);
|
||||
when(mSysPropsMock.getBoolean(
|
||||
ArgumentMatchers.eq(PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED),
|
||||
ArgumentMatchers.eq(false)))
|
||||
.thenReturn(true);
|
||||
assertTrue(mController.isAvailable());
|
||||
|
||||
when(mPreference.isChecked()).thenReturn(true);
|
||||
mController.onDeveloperOptionsSwitchDisabled();
|
||||
|
||||
verify(mPreference).setChecked(false);
|
||||
verify(mPreference).setEnabled(false);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user