fix: 引入Settings的Module

This commit is contained in:
2024-12-10 14:57:24 +08:00
parent ad8fc8731d
commit df105485bd
6934 changed files with 896168 additions and 2 deletions

View File

@@ -0,0 +1,112 @@
package {
default_team: "trendy_team_android_settings_app",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "packages_apps_Settings_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["packages_apps_Settings_license"],
}
// Build SettingsRoboTestStub.apk which includes test-only resources.
android_app {
name: "SettingsRoboTestStub",
defaults: [
"SettingsLibDefaults",
"SettingsLib-search-defaults",
],
platform_apis: true,
certificate: "platform",
privileged: true,
use_resource_processor: true,
resource_dirs: ["res"],
static_libs: [
"Settings-core",
"androidx.fragment_fragment-testing",
"frameworks-base-testutils",
"androidx.fragment_fragment",
"androidx.lifecycle_lifecycle-runtime-testing",
"kotlinx_coroutines_test",
],
aaptflags: ["--extra-packages com.android.settings"],
libs: [
"telephony-common",
"ims-common",
],
uses_libs: ["org.apache.http.legacy"],
optional_uses_libs: [
"androidx.window.extensions",
"androidx.window.sidecar",
],
}
// Settings Robolectric test target.
android_robolectric_test {
name: "SettingsRoboTests",
srcs: [
"src/**/*.java",
"src/**/*.kt",
],
// test_suites attribute is not needed. This module will be configured in ATP GCL file.
static_libs: [
"Robolectric_shadows_androidx_fragment_upstream",
"Settings_robolectric_meta_service_file",
"SettingsLib-robo-testutils",
"Settings-robo-testutils",
"android.webkit.flags-aconfig-java",
"androidx.test.core",
"androidx.test.espresso.core",
"androidx.test.ext.junit",
"androidx.test.rules",
"androidx.test.runner",
"flag-junit",
"flag-junit-base",
"aconfig_settings_flags_lib",
"platform-test-annotations",
"Settings-testutils2",
"notification_flags_lib",
"com_android_server_accessibility_flags_lib",
"testables",
],
libs: [
"ims-common",
"android.test.mock",
],
java_resource_dirs: [
"config",
"resources",
],
instrumentation_for: "SettingsRoboTestStub",
test_options: {
timeout: 36000,
shards: 10,
},
coverage_libs: [
"Settings-core",
"SettingsLib",
"SettingsLib-search",
],
upstream: true,
}
java_library {
name: "Settings-robo-testutils",
srcs: ["testutils/**/*.java"],
libs: [
"Robolectric_all-target_upstream",
"Settings-core",
"mockito-robolectric-prebuilt",
"truth",
],
}

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
coreApp="true"
package="com.android.settings">
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<application>
<activity android:name="com.android.settings.security.TestActivity" android:exported="true" />
</application>
</manifest>

View File

@@ -0,0 +1,2 @@
# We do not guard tests - everyone is welcomed to contribute to tests.
per-file *.java=*

View File

@@ -0,0 +1,24 @@
# Running Settings Robolectric tests
## The full suite
```
$ croot
$ make RunSettingsRoboTests
```
## Running a single test class
```
$ croot
$ make RunSettingsRoboTests ROBOTEST_FILTER=<ClassName>
```
For example:
```
make RunSettingsRoboTests ROBOTEST_FILTER=CodeInspectionTest
```
You can also use partial class name in ROBOTEST_FILTER. If the partial class name matches
multiple file names, all of them will be executed.

Binary file not shown.

View File

@@ -0,0 +1,14 @@
com.android.settings.applications.appinfo.AppButtonsPreferenceController
com.android.settings.applications.appinfo.AppBatteryPreferenceController
com.android.settings.applications.appinfo.AppHeaderViewPreferenceController
com.android.settings.applications.appinfo.AppMemoryPreferenceController
com.android.settings.applications.appinfo.InstantAppButtonsPreferenceController
com.android.settings.bluetooth.BluetoothDeviceNamePreferenceController
com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController
com.android.settings.datausage.DataUsageSummaryPreferenceController
com.android.settings.datausage.WifiDataUsageSummaryPreferenceController
com.android.settings.fuelgauge.RestrictAppPreferenceController
com.android.settings.fuelgauge.batterysaver.BatterySaverButtonPreferenceController
com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController
com.android.settings.security.VisiblePatternProfilePreferenceController
com.android.settings.wifi.details2.WifiMeteredPreferenceController2

View File

@@ -0,0 +1,94 @@
com.android.settings.accessibility.AccessibilitySettingsForSetupWizard
com.android.settings.accessibility.ToggleAccessibilityServicePreferenceFragment
com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragment
com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragmentForSetupWizard
com.android.settings.accessibility.ToggleScreenReaderPreferenceFragmentForSetupWizard
com.android.settings.accessibility.ToggleSelectToSpeakPreferenceFragmentForSetupWizard
com.android.settings.accounts.AccountDetailDashboardFragment
com.android.settings.accounts.AccountPersonalDashboardFragment
com.android.settings.accounts.AccountWorkProfileDashboardFragment
com.android.settings.accounts.AccountSyncSettings
com.android.settings.accounts.ChooseAccountFragment
com.android.settings.applications.appinfo.AppInfoDashboardFragment
com.android.settings.applications.appinfo.DrawOverlayDetails
com.android.settings.applications.appinfo.ExternalSourcesDetails
com.android.settings.applications.appinfo.WriteSettingsDetails
com.android.settings.applications.AppLaunchSettings
com.android.settings.applications.AppStorageSettings
com.android.settings.applications.ProcessStatsDetail
com.android.settings.applications.ProcessStatsSummary
com.android.settings.applications.ProcessStatsUi
com.android.settings.applications.RunningServices
com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureDetails
com.android.settings.applications.specialaccess.zenaccess.ZenAccessDetails
com.android.settings.applications.UsageAccessDetails
com.android.settings.backup.ToggleBackupSettingFragment
com.android.settings.biometrics.fingerprint.FingerprintSettings$FingerprintSettingsFragment
com.android.settings.bluetooth.BluetoothDeviceDetailsFragment
com.android.settings.bluetooth.BluetoothPairingDetail
com.android.settings.bluetooth.DevicePickerFragment
com.android.settings.dashboard.profileselector.ProfileSelectAccountFragment
com.android.settings.dashboard.profileselector.ProfileSelectManageApplications
com.android.settings.dashboard.profileselector.ProfileSelectLocationFragment
com.android.settings.datausage.AppDataUsage
com.android.settings.datausage.DataUsageList
com.android.settings.datausage.DataUsageSummary
com.android.settings.datetime.timezone.TimeZoneSettings
com.android.settings.development.compat.PlatformCompatDashboard
com.android.settings.deviceinfo.PublicVolumeSettings
com.android.settings.deviceinfo.StorageDashboardNoHeaderFragment
com.android.settings.deviceinfo.legal.ModuleLicensesDashboard
com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionCamera
com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionLocation
com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionMicrophone
com.android.settings.enterprise.ApplicationListFragment$EnterpriseInstalledPackages
com.android.settings.enterprise.EnterpriseSetDefaultAppsListFragment
com.android.settings.fuelgauge.AdvancedPowerUsageDetail
com.android.settings.fuelgauge.InactiveApps
com.android.settings.fuelgauge.RestrictedAppDetails
com.android.settings.IccLockSettings
com.android.settings.inputmethod.InputMethodAndSubtypeEnabler
com.android.settings.inputmethod.KeyboardLayoutPickerFragment
com.android.settings.inputmethod.SpellCheckersSettings
com.android.settings.location.LocationPersonalSettings
com.android.settings.location.LocationWorkProfileSettings
com.android.settings.network.apn.ApnEditor
com.android.settings.network.apn.ApnSettings
com.android.settings.network.telephony.NetworkSelectSettings
com.android.settings.notification.app.AppNotificationSettings
com.android.settings.notification.app.ChannelNotificationSettings
com.android.settings.notification.history.NotificationStation
com.android.settings.notification.RedactionInterstitial$RedactionInterstitialFragment
com.android.settings.notification.zen.ZenModeEventRuleSettings
com.android.settings.notification.zen.ZenModeScheduleRuleSettings
com.android.settings.notification.zen.ZenCustomRuleNotificationsSettings
com.android.settings.notification.zen.ZenCustomRuleCallsSettings
com.android.settings.notification.zen.ZenCustomRuleConfigSettings
com.android.settings.notification.zen.ZenCustomRuleSettings
com.android.settings.notification.zen.ZenCustomRuleBlockedEffectsSettings
com.android.settings.notification.zen.ZenCustomRuleMessagesSettings
com.android.settings.password.ChooseLockGeneric$ChooseLockGenericFragment
com.android.settings.password.SetupChooseLockGeneric$InternalActivity$InternalSetupChooseLockGenericFragment
com.android.settings.password.SetupChooseLockGeneric$SetupChooseLockGenericFragment
com.android.settings.print.PrintJobSettingsFragment
com.android.settings.print.PrintServiceSettingsFragment
com.android.settings.SetupRedactionInterstitial$SetupRedactionInterstitialFragment
com.android.settings.shortcut.CreateShortcut
com.android.settings.TestingSettings
com.android.settings.UserCredentialsSettings
com.android.settings.users.AppRestrictionsFragment
com.android.settings.users.RestrictedProfileSettings
com.android.settings.users.UserDetailsSettings
com.android.settings.vpn2.AppManagementFragment
com.android.settings.vpn2.VpnSettings
com.android.settings.wallpaper.WallpaperTypeSettings
com.android.settings.wifi.ChangeWifiStateDetails
com.android.settings.wifi.calling.WifiCallingSettingsForSub
com.android.settings.wifi.details.WifiNetworkDetailsFragment
com.android.settings.wifi.dpp.WifiNetworkListFragment
com.android.settings.wifi.p2p.WifiP2pSettings
com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings
com.android.settings.wifi.WifiInfo
com.android.settings.applications.specialaccess.notificationaccess.NotificationAccessDetails
com.android.settings.wifi.details2.WifiNetworkDetailsFragment2
com.android.settings.wifi.savedaccesspoints2.SavedAccessPointsWifiSettings2

View File

@@ -0,0 +1,9 @@
com.android.settings.deletionhelper.ActivationWarningFragment
com.android.settings.applications.appops.AppOpsCategory
com.android.settings.CustomListPreference$CustomListPreferenceDialogFragment
com.android.settings.password.SaveAndFinishWorker
com.android.settings.RestrictedListPreference$RestrictedListPreferenceDialogFragment
com.android.settings.password.ConfirmDeviceCredentialBaseFragment$LastTryDialog
com.android.settings.password.CredentialCheckResultTracker
com.android.settings.dashboard.profileselector.ProfileSelectDialog
com.android.settings.panel.PanelFragment

View File

@@ -0,0 +1 @@
com.android.settings.search.FakeSettingsFragment

View File

@@ -0,0 +1,20 @@
com.android.settings.accessibility.AccessibilitySlicePreferenceController
com.android.settings.accessibility.MagnificationAlwaysOnPreferenceController
com.android.settings.accessibility.MagnificationFollowTypingPreferenceController
com.android.settings.accessibility.MagnificationJoystickPreferenceController
com.android.settings.accessibility.ReduceBrightColorsIntensityPreferenceController
com.android.settings.accessibility.ReduceBrightColorsPersistencePreferenceController
com.android.settings.biometrics.face.FaceSettingsAttentionPreferenceController
com.android.settings.core.TogglePreferenceControllerTest$FakeToggle
com.android.settings.display.DeviceStateAutoRotateSettingController
com.android.settings.display.SmartAutoRotatePreferenceController
com.android.settings.gestures.OneHandedMainSwitchPreferenceController
com.android.settings.network.telephony.AutoDataSwitchPreferenceController
com.android.settings.network.telephony.Enhanced4gBasePreferenceController
com.android.settings.network.telephony.MmsMessagePreferenceController
com.android.settings.notification.RingVolumePreferenceController
com.android.settings.testutils.FakeInvalidSliderController
com.android.settings.testutils.FakeSliderController
com.android.settings.testutils.FakeToggleController
com.android.settings.users.GuestTelephonyPreferenceController
com.android.settings.wifi.details2.WifiAutoConnectPreferenceController2

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,5 @@
sdk=NEWEST_SDK
shadows=\
com.android.settings.testutils.shadow.ShadowThreadUtils \
com.android.settings.network.ShadowServiceManagerExtend
instrumentedPackages=androidx.preference

View File

@@ -0,0 +1,16 @@
#!/bin/bash
# This script detects the presence of new robolectric java tests within
# commits to be uploaded. If a new file is detected the script will print an
# error message and return an error code. Intended to be used as a repo hook.
new_robolectric_tests=$(
git diff --name-status $REPO_LREV | grep "^A.*tests/robotests.*\.java")
if [ $new_robolectric_tests != "" ]
then
echo "New Robolectric unit tests detected. Please submit junit tests" \
"instead, in the tests/junit directory." \
"See go/android-platform-robolectric-cleanup."
echo $new_robolectric_tests
exit 1
fi

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017 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.
-->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
style="?attr/fingerprint_layout_theme"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:clipToPadding="false"
android:clipChildren="false">
<FrameLayout
android:layout_width="@dimen/fingerprint_find_sensor_graphic_size"
android:layout_height="@dimen/fingerprint_find_sensor_graphic_size"
android:layout_gravity="center_horizontal|bottom">
<ImageView
android:id="@+id/fingerprint_sensor_location_animation"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/security_settings_fingerprint_enroll_find_sensor_content_description"
android:src="@drawable/fingerprint_sensor_location"
android:scaleType="centerInside"/>
</FrameLayout>
<LinearLayout
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:clipToPadding="false"
android:clipChildren="false">
<TextView
style="@style/SudDescription.Glif"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/sud_description_glif_margin_top"
android:text="@string/security_settings_fingerprint_enroll_find_sensor_message"/>
<View
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="1"/>
<Button
style="@style/SudGlifButton.Secondary"
android:id="@+id/next_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_gravity="end"
android:text="@string/fingerprint_enroll_button_next" />
</LinearLayout>
</FrameLayout>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/GlifV3Theme.Footer"
android:orientation="vertical"
android:icon="@drawable/ic_delete_accent"
app:sucHeaderText="@string/main_clear_title">
<ScrollView
android:id="@+id/main_clear_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/main_clear_container"
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
style="@style/TextAppearance.SudGlifItemSummary"
android:id="@+id/sud_layout_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/main_clear_desc"/>
<TextView
android:id="@+id/also_erases_external"
style="@style/TextAppearance.SudGlifItemSummary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="@string/main_clear_desc_also_erases_external"/>
<TextView
android:id="@+id/also_erases_esim"
style="@style/TextAppearance.SudGlifItemSummary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="@string/main_clear_desc_also_erases_esim"/>
<TextView
android:id="@+id/accounts_label"
style="@style/TextAppearance.SudGlifItemSummary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="@string/main_clear_accounts"/>
<LinearLayout
android:id="@+id/accounts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<!-- Do not add any children here as they will be removed in the MainClear.java
code. A list of accounts will be inserted programmatically. -->
</LinearLayout>
<TextView
android:id="@+id/other_users_present"
style="@style/TextAppearance.SudGlifItemSummary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="@string/main_clear_other_users_present"/>
<TextView
android:id="@+id/no_cancel_mobile_plan"
style="@style/TextAppearance.SudGlifItemSummary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="@string/main_clear_desc_no_cancel_mobile_plan"/>
<TextView
android:id="@+id/erase_external_option_text"
style="@style/TextAppearance.SudGlifItemSummary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/main_clear_desc_erase_external_storage"/>
<LinearLayout
android:id="@+id/erase_external_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:focusable="true"
android:clickable="true">
<CheckBox
android:id="@+id/erase_external"
style="@style/SudCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:focusable="false"
android:clickable="false"
android:duplicateParentState="true"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="vertical">
<TextView
style="@style/TextAppearance.SudGlifItemTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/erase_external_storage"/>
<TextView
style="@style/TextAppearance.SudGlifItemSummary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/erase_external_storage_description"/>
</LinearLayout>
</LinearLayout>
<include layout="@layout/reset_esim_checkbox"/>
</LinearLayout>
</ScrollView>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/SudThemeGlifV3.DayNight"
android:orientation="vertical"
android:id="@+id/setup_wizard_layout"
android:icon="@drawable/ic_delete_accent"
app:sucHeaderText="@string/main_clear_confirm_title">
<LinearLayout
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/sud_layout_description"
style="@style/SudItemTitle.GlifDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/main_clear_final_desc"/>
</LinearLayout>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 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.
-->
<!-- A test preference layout containing all required widgets -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
android:textColor="?android:attr/textColorPrimary"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
android:visibility="gone"
android:textAlignment="viewStart"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="10" />
<LinearLayout
android:id="@android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minWidth="58dip"
android:gravity="end|center_vertical"
android:orientation="vertical" />
</LinearLayout>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<!-- Since Robolectric can't inflate @*android:layout/alert_dialog_button_bar_material in
../res/layout/wifi_add_network_view.xml, so this Layout overrides button bar part. -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
layout="@layout/wifi_dialog"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<Button
android:id="@android:id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@android:id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</RelativeLayout>

Binary file not shown.

View File

@@ -0,0 +1,20 @@
<!--
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.
-->
<resources>
<!-- List of packages that should be allowlisted for slice uri access. Do not translate -->
<string-array name="slice_allowlist_package_names" translatable="false"/>
</resources>

View File

@@ -0,0 +1,103 @@
<!--
Copyright (C) 2017 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.
-->
<resources>
<bool name="config_enableColorTemperature">false</bool>
<bool name="config_show_camera_laser_sensor">false</bool>
<bool name="config_show_connectivity_monitor">false</bool>
<bool name="config_additional_system_update_setting_enable">true</bool>
<bool name="config_show_wifi_settings">false</bool>
<bool name="config_show_toggle_airplane">false</bool>
<bool name="config_show_private_dns_settings">false</bool>
<bool name="config_show_app_info_settings_memory">true</bool>
<bool name="config_show_app_info_settings_battery">false</bool>
<bool name="config_show_high_power_apps">false</bool>
<bool name="config_show_alarm_volume">false</bool>
<bool name="config_show_charging_sounds">false</bool>
<bool name="config_show_media_volume">false</bool>
<bool name="config_show_notification_ringtone">false</bool>
<bool name="config_show_notification_volume">false</bool>
<bool name="config_show_screen_locking_sounds">false</bool>
<bool name="config_show_touch_sounds">false</bool>
<bool name="config_show_encryption_and_credentials_encryption_status">false</bool>
<bool name="config_show_premium_sms">false</bool>
<bool name="config_show_data_saver">false</bool>
<bool name="config_show_enabled_vr_listeners">false</bool>
<bool name="config_location_mode_available">false</bool>
<bool name="config_show_location_scanning">false</bool>
<bool name="config_show_location_services">false</bool>
<bool name="config_show_manage_device_admin">false</bool>
<bool name="config_show_unlock_set_or_change">false</bool>
<bool name="config_show_screen_pinning_settings">false</bool>
<bool name="config_show_manage_trust_agents">false</bool>
<bool name="config_show_show_password">false</bool>
<bool name="config_show_trust_agent_click_intent">false</bool>
<bool name="config_show_wallpaper_attribution">false</bool>
<bool name="config_show_assist_and_voice_input">false</bool>
<bool name="config_show_phone_language">false</bool>
<bool name="config_show_virtual_keyboard_pref">false</bool>
<bool name="config_show_physical_keyboard_pref">false</bool>
<bool name="config_show_tts_settings_summary">false</bool>
<bool name="config_show_pointer_speed">false</bool>
<bool name="config_show_vibrate_input_devices">false</bool>
<bool name="config_show_reset_dashboard">false</bool>
<bool name="config_show_device_model">false</bool>
<bool name="config_show_top_level_accessibility">false</bool>
<bool name="config_show_top_level_battery">false</bool>
<bool name="config_show_top_level_connected_devices">false</bool>
<bool name="config_show_top_level_display">false</bool>
<bool name="config_show_wifi_ip_address">false</bool>
<bool name="config_show_wifi_mac_address">false</bool>
<bool name="config_disable_uninstall_update">true</bool>
<bool name="config_show_device_name">false</bool>
<bool name="config_use_legacy_suggestion">false</bool>
<bool name="config_show_avatar_in_homepage">true</bool>
<bool name="config_show_branded_account_in_device_info">false</bool>
<bool name="config_show_emergency_info_in_device_info">false</bool>
<bool name="config_show_smooth_display">false</bool>
<bool name="config_settingsintelligence_slice_supported">true</bool>
<!-- Whether or not extra preview panels should be used for screen zoom setting. -->
<bool name="config_enable_extra_screen_zoom_preview">false</bool>
<!-- Whether dismissal timestamp should be kept before deletion -->
<bool name="config_keep_contextual_card_dismissal_timestamp">true</bool>
<!-- List of a11y components on the device allowed to be enabled by Settings Slices -->
<string-array name="config_settings_slices_accessibility_components" translatable="false">
<item>fake_package/fake_service</item>
</string-array>
<!-- List of packages that should be allowlisted for slice uri access. Do not translate -->
<string-array name="slice_allowlist_package_names" translatable="false">
<item>com.android.settings.slice_allowlist_package</item>
</string-array>
<!-- Email address for the homepage contextual cards feedback -->
<string name="config_contextual_card_feedback_email" translatable="false">test@test.test</string>
<!-- Grayscale settings intent -->
<string name="config_grayscale_settings_intent" translatable="false">intent:#Intent;action=test.test;end</string>
<!-- List containing the injected tile keys which are suppressed. -->
<string-array name="config_suppress_injected_tile_keys" translatable="false">
<item>injected_tile_key</item>
<item>injected_tile_key2</item>
</string-array>
<!-- Uri to query non-public Slice Uris. -->
<string name="config_non_public_slice_query_uri" translatable="false">content://com.android.settings.slices/test</string>
</resources>

View File

@@ -0,0 +1,24 @@
<!--
Copyright (C) 2017 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.
-->
<resources>
<!-- Whether or not new device intro suggestion is supported for this device -->
<bool name="config_enableColorTemperature">true</bool>
<bool name="config_show_camera_laser_sensor">true</bool>
<bool name="config_show_connectivity_monitor">true</bool>
<bool name="config_show_smooth_display">true</bool>
<bool name="config_show_location_services">true</bool>
</resources>

View File

@@ -0,0 +1,22 @@
<resources>
<style name="Theme.Settings" parent="@android:style/Theme.DeviceDefault.Settings">
<!-- For AndroidX AlertDialogs -->
<item name="alertDialogTheme">@style/Theme.AppCompat.DayNight.Dialog.Alert</item>
</style>
<!-- Override the main app's style for ActionPrimaryButton to get around lack of new style
support in robolectric -->
<style name="ActionPrimaryButton" parent="android:Widget.DeviceDefault.Button"/>
<!-- Test version of Theme.Settings.Home. Needed to build homepage activity in Robolectric -->
<style name="Theme.Settings.Home" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="colorPrimary">#ffffff</item>
<item name="colorPrimaryDark">#ffffff</item>
<item name="colorAccent">#ffffff</item>
<item name="preferenceTheme">@style/SettingsPreferenceTheme</item>
<item name="android:windowLightStatusBar">true</item>
<!-- Define this color for material design -->
<item name="colorPrimaryVariant">@android:color/white</item>
</style>
</resources>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="fake_title_key"
android:title="screen_title">
<Preference
android:key="key1"
android:title="title"
android:icon="@drawable/ic_android"
android:summary="summary1"
settings:controller="com.android.settings.core.BadPreferenceController"/>
<Preference
android:key="key2"
android:title="title"
android:icon="@drawable/ic_android"
android:summary="summary2"
settings:controller="com.android.settings.slices.FakePreferenceController"/>
</PreferenceScreen>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2019 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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<com.android.settings.widget.SeekBarPreference
android:key="seek_bar"
android:title="seek_bar_title"/>
</PreferenceScreen >

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/battery_saver_schedule_settings_title"
settings:staticPreferenceLocation="append">
</PreferenceScreen >

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017 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.
-->
<!--
WARNING: This resource file is used to test Settings Search indexing.
If you change something in here, please run the settings robotests and
make sure they still pass.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="page_title"
settings:keywords="keywords">
<Preference
android:key="pref_key_1"
android:title="pref_title_1"
android:summary="summary_1"
settings:keywords="keywords1, keywords2, keywords3" />
<SwitchPreference
android:key="pref_key_2"
android:title="pref_title_2"
android:summary="summary_2"
settings:keywords="keywords1, keywords2, keywords3" />
<Preference
android:key="pref_key_3"
android:title="pref_title_3"
android:summary="summary_3"
android:icon="@drawable/ic_android"
settings:keywords="keywords1, keywords2, keywords3" />
<ListPreference
android:key="pref_key_4"
android:title="pref_title_4"
android:summary="summary_4"
android:entries="@array/mvno_type_entries"
android:entryValues="@array/mvno_type_values"
settings:keywords="keywords1, keywords2, keywords3" />
<CheckBoxPreference
android:key="pref_key_5"
android:title="pref_title_5"
android:summaryOn="summary_on"
android:summaryOff="summary_off"
settings:searchable="false"
settings:keywords="keywords1, keywords2, keywords3" />
</PreferenceScreen>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="fake_title_key"
android:title="screen_title">
<Preference
android:key="key"
android:title="title"
android:icon="@drawable/ic_android"
android:summary="summary"
settings:highlightableMenuKey="menu_key"
settings:controller="com.android.settings.slices.FakePreferenceController"
settings:keywords="a, b, c"
settings:unavailableSliceSubtitle="subtitleOfUnavailableSlice"/>
</PreferenceScreen>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="fake_title_key"
android:title="screen_title">
<Preference
android:key="key1"
android:title="title"
android:icon="@drawable/ic_android"
android:summary="summary"
settings:controller="com.android.settings.slices.FakePreferenceController"
settings:keywords="keyword"/>
<Preference
android:key="key2"
android:title="title"
android:icon="@drawable/ic_android"
android:summary="summary"
settings:controller="com.android.settings.slices.FakePreferenceController"
settings:keywords="keyword"
settings:unavailableSliceSubtitle="subtitleOfUnavailable"/>
</PreferenceScreen>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2019 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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<com.android.settings.widget.SeekBarPreference
android:key="seek_bar"
android:selectable="true"
android:title="seek_bar_title"/>
</PreferenceScreen >

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2019 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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto">
<com.android.settings.widget.VideoPreference
android:key="video1"
settings:animation="@raw/face_education"
settings:preview="@drawable/face_enroll_intro_illustration"
android:title="seek_bar_title"/>
<com.android.settings.widget.VideoPreference
android:key="video2"
settings:animation="@raw/face_education"
settings:preview="@drawable/face_enroll_intro_illustration"
settings:vectorAnimation="@drawable/face_enroll_intro_illustration"
android:title="seek_bar_title"/>
</PreferenceScreen >

View File

@@ -0,0 +1 @@
org.robolectric.android.internal.RobolectricThreadChecker

View File

@@ -0,0 +1 @@
org.robolectric.android.internal.LocalActivityInvoker

View File

@@ -0,0 +1 @@
org.robolectric.android.internal.LocalPermissionGranter

View File

@@ -0,0 +1 @@
org.robolectric.android.internal.LocalControlledLooper

View File

@@ -0,0 +1 @@
org.robolectric.android.internal.LocalUiController

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2019 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;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.telephony.TelephonyManager;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowSettings;
@RunWith(AndroidJUnit4.class)
public final class AirplaneModeEnablerTest {
private Context mContext;
@Mock
private AirplaneModeChangedListener mAirplaneModeChangedListener;
private AirplaneModeEnabler mAirplaneModeEnabler;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application.getBaseContext();
mAirplaneModeEnabler = new AirplaneModeEnabler(mContext,
mAirplaneModeChangedListener);
}
@Test
public void onRadioPowerStateChanged_beenInvoke_invokeOnAirplaneModeChanged() {
mAirplaneModeEnabler.start();
ShadowSettings.setAirplaneMode(true);
mAirplaneModeEnabler.mPhoneStateListener.onRadioPowerStateChanged(
TelephonyManager.RADIO_POWER_OFF);
verify(mAirplaneModeChangedListener, times(1)).onAirplaneModeChanged(true);
}
private class AirplaneModeChangedListener
implements AirplaneModeEnabler.OnAirplaneModeChangedListener {
public void onAirplaneModeChanged(boolean isAirplaneModeOn) {}
}
}

View File

@@ -0,0 +1,38 @@
package com.android.settings;
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.settingslib.core.AbstractPreferenceController;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class DisplaySettingsTest {
@Test
public void testPreferenceControllers_getPreferenceKeys_existInPreferenceScreen() {
final Context context = ApplicationProvider.getApplicationContext();
final DisplaySettings fragment = new DisplaySettings();
final List<String> preferenceScreenKeys = XmlTestUtils.getKeysFromPreferenceXml(context,
fragment.getPreferenceScreenResId());
final List<String> preferenceKeys = new ArrayList<>();
for (AbstractPreferenceController controller : fragment.createPreferenceControllers(context)) {
preferenceKeys.add(controller.getPreferenceKey());
}
// Nightmode is currently hidden
preferenceKeys.remove("night_mode");
assertThat(preferenceScreenKeys).containsAtLeastElementsIn(preferenceKeys);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2017 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;
import static com.google.common.truth.Truth.assertThat;
import android.content.Intent;
import com.android.settings.testutils.shadow.ShadowHelpUtils;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
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;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowHelpUtils.class)
public class HelpTrampolineTest {
@After
public void tearDown() {
ShadowHelpUtils.reset();
}
@Test
public void launchHelp_noExtra_shouldDoNothing() {
final Intent intent = new Intent().setClassName(
RuntimeEnvironment.application.getPackageName(), HelpTrampoline.class.getName());
Robolectric.buildActivity(HelpTrampoline.class, intent).create().get();
assertThat(ShadowHelpUtils.isGetHelpIntentCalled()).isFalse();
}
@Test
public void launchHelp_hasExtra_shouldLaunchHelp() {
final Intent intent = new Intent().setClassName(
RuntimeEnvironment.application.getPackageName(), HelpTrampoline.class.getName())
.putExtra(Intent.EXTRA_TEXT, "help_url_upgrading");
final ShadowActivity shadow = Shadows.
shadowOf(Robolectric.buildActivity(HelpTrampoline.class, intent).create().get());
final Intent launchedIntent = shadow.getNextStartedActivity();
assertThat(ShadowHelpUtils.isGetHelpIntentCalled()).isTrue();
assertThat(launchedIntent).isNotNull();
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2017 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;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import com.android.settings.testutils.XmlTestUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class LegalSettingsTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void getNonIndexableKeys_existInXmlLayout() {
final Context context = RuntimeEnvironment.application;
final List<String> niks =
LegalSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(context);
final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(context, R.xml.about_legal);
assertThat(keys).containsAtLeastElementsIn(niks);
}
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (C) 2019 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;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
import android.app.admin.FactoryResetProtectionPolicy;
import android.content.Context;
import android.service.persistentdata.PersistentDataBlockManager;
import android.view.LayoutInflater;
import android.widget.TextView;
import androidx.fragment.app.FragmentActivity;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.ArrayList;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class MainClearConfirmTest {
private FragmentActivity mActivity;
@Mock
private FragmentActivity mMockActivity;
@Mock
private DevicePolicyManager mDevicePolicyManager;
@Mock
private PersistentDataBlockManager mPersistentDataBlockManager;
private MainClearConfirm mMainClearConfirm;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mActivity = Robolectric.setupActivity(FragmentActivity.class);
mMainClearConfirm = spy(new MainClearConfirm());
}
@Test
public void setSubtitle_eraseEsim() {
MainClearConfirm mainClearConfirm = new MainClearConfirm();
mainClearConfirm.mEraseEsims = true;
mainClearConfirm.mContentView =
LayoutInflater.from(mActivity).inflate(R.layout.main_clear_confirm, null);
mainClearConfirm.setSubtitle();
assertThat(((TextView) mainClearConfirm.mContentView
.findViewById(R.id.sud_layout_description)).getText())
.isEqualTo(mActivity.getString(R.string.main_clear_final_desc_esim));
}
@Test
public void setSubtitle_notEraseEsim() {
MainClearConfirm mainClearConfirm = new MainClearConfirm();
mainClearConfirm.mEraseEsims = false;
mainClearConfirm.mContentView =
LayoutInflater.from(mActivity).inflate(R.layout.main_clear_confirm, null);
mainClearConfirm.setSubtitle();
assertThat(((TextView) mainClearConfirm.mContentView
.findViewById(R.id.sud_layout_description)).getText())
.isEqualTo(mActivity.getString(R.string.main_clear_final_desc));
}
@Test
public void shouldWipePersistentDataBlock_noPersistentDataBlockManager_shouldReturnFalse() {
assertThat(mMainClearConfirm.shouldWipePersistentDataBlock(null)).isFalse();
}
@Test
public void shouldWipePersistentDataBlock_deviceIsStillBeingProvisioned_shouldReturnFalse() {
doReturn(true).when(mMainClearConfirm).isDeviceStillBeingProvisioned();
assertThat(mMainClearConfirm.shouldWipePersistentDataBlock(
mPersistentDataBlockManager)).isFalse();
}
@Test
public void shouldWipePersistentDataBlock_oemUnlockAllowed_shouldReturnFalse() {
doReturn(false).when(mMainClearConfirm).isDeviceStillBeingProvisioned();
doReturn(true).when(mMainClearConfirm).isOemUnlockedAllowed();
assertThat(mMainClearConfirm.shouldWipePersistentDataBlock(
mPersistentDataBlockManager)).isFalse();
}
@Test
public void shouldWipePersistentDataBlock_frpPolicyNotSupported_shouldReturnFalse() {
when(mMainClearConfirm.getActivity()).thenReturn(mMockActivity);
doReturn(false).when(mMainClearConfirm).isDeviceStillBeingProvisioned();
doReturn(false).when(mMainClearConfirm).isOemUnlockedAllowed();
when(mMockActivity.getSystemService(Context.DEVICE_POLICY_SERVICE))
.thenReturn(mDevicePolicyManager);
when(mDevicePolicyManager.isFactoryResetProtectionPolicySupported()).thenReturn(false);
assertThat(mMainClearConfirm.shouldWipePersistentDataBlock(
mPersistentDataBlockManager)).isFalse();
}
@Test
public void shouldWipePersistentDataBlock_hasFactoryResetProtectionPolicy_shouldReturnFalse() {
when(mMainClearConfirm.getActivity()).thenReturn(mMockActivity);
doReturn(false).when(mMainClearConfirm).isDeviceStillBeingProvisioned();
doReturn(false).when(mMainClearConfirm).isOemUnlockedAllowed();
ArrayList<String> accounts = new ArrayList<>();
accounts.add("test");
FactoryResetProtectionPolicy frp = new FactoryResetProtectionPolicy.Builder()
.setFactoryResetProtectionAccounts(accounts)
.setFactoryResetProtectionEnabled(true)
.build();
when(mMockActivity.getSystemService(Context.DEVICE_POLICY_SERVICE))
.thenReturn(mDevicePolicyManager);
when(mDevicePolicyManager.isFactoryResetProtectionPolicySupported()).thenReturn(true);
when(mDevicePolicyManager.getFactoryResetProtectionPolicy(null)).thenReturn(frp);
when(mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()).thenReturn(true);
assertThat(mMainClearConfirm.shouldWipePersistentDataBlock(
mPersistentDataBlockManager)).isFalse();
}
@Test
public void shouldWipePersistentDataBlock_isNotOrganizationOwnedDevice_shouldReturnTrue() {
when(mMainClearConfirm.getActivity()).thenReturn(mMockActivity);
doReturn(false).when(mMainClearConfirm).isDeviceStillBeingProvisioned();
doReturn(false).when(mMainClearConfirm).isOemUnlockedAllowed();
when(mMockActivity.getSystemService(Context.DEVICE_POLICY_SERVICE))
.thenReturn(mDevicePolicyManager);
when(mDevicePolicyManager.isFactoryResetProtectionPolicySupported()).thenReturn(true);
when(mDevicePolicyManager.getFactoryResetProtectionPolicy(null)).thenReturn(null);
when(mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()).thenReturn(false);
assertThat(mMainClearConfirm.shouldWipePersistentDataBlock(
mPersistentDataBlockManager)).isTrue();
}
}

View File

@@ -0,0 +1,477 @@
/*
* Copyright (C) 2016 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;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
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 static org.mockito.Mockito.when;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserManager;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.settingslib.development.DevelopmentSettingsEnabler;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowActivity;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowUtils.class,
ShadowUserManager.class,
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class MainClearTest {
private static final String TEST_ACCOUNT_TYPE = "android.test.account.type";
private static final String TEST_CONFIRMATION_PACKAGE = "android.test.conf.pkg";
private static final String TEST_CONFIRMATION_CLASS = "android.test.conf.pkg.ConfActivity";
private static final String TEST_ACCOUNT_NAME = "test@example.com";
@Mock
private ScrollView mScrollView;
@Mock
private LinearLayout mLinearLayout;
@Mock
private PackageManager mPackageManager;
@Mock
private AccountManager mAccountManager;
@Mock
private FragmentActivity mMockActivity;
@Mock
private Intent mMockIntent;
private MainClear mMainClear;
private ShadowActivity mShadowActivity;
private FragmentActivity mActivity;
private ShadowUserManager mShadowUserManager;
private View mContentView;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mMainClear = spy(new MainClear() {
@Override
boolean showAnySubscriptionInfo(Context context) { return true; }
});
mActivity = Robolectric.setupActivity(FragmentActivity.class);
mShadowActivity = Shadows.shadowOf(mActivity);
UserManager userManager = mActivity.getSystemService(UserManager.class);
mShadowUserManager = Shadow.extract(userManager);
mShadowUserManager.setIsAdminUser(true);
mContentView = LayoutInflater.from(mActivity).inflate(R.layout.main_clear, null);
// Make scrollView only have one child
when(mScrollView.getChildAt(0)).thenReturn(mLinearLayout);
when(mScrollView.getChildCount()).thenReturn(1);
}
@After
public void tearDown() {
mShadowUserManager.setIsAdminUser(false);
}
@Test
public void testShowFinalConfirmation_eraseEsimVisible_eraseEsimChecked() {
final Context context = mock(Context.class);
when(mMainClear.getContext()).thenReturn(context);
mMainClear.mEsimStorage = mContentView.findViewById(R.id.erase_esim);
mMainClear.mExternalStorage = mContentView.findViewById(R.id.erase_external);
mMainClear.mEsimStorageContainer = mContentView.findViewById(R.id.erase_esim_container);
mMainClear.mEsimStorageContainer.setVisibility(View.VISIBLE);
mMainClear.mEsimStorage.setChecked(true);
mMainClear.showFinalConfirmation();
final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
verify(context).startActivity(intent.capture());
assertThat(intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
.getBoolean(MainClear.ERASE_ESIMS_EXTRA, false))
.isTrue();
}
@Test
public void testShowFinalConfirmation_eraseEsimVisible_eraseEsimUnchecked() {
final Context context = mock(Context.class);
when(mMainClear.getContext()).thenReturn(context);
mMainClear.mEsimStorage = mContentView.findViewById(R.id.erase_esim);
mMainClear.mExternalStorage = mContentView.findViewById(R.id.erase_external);
mMainClear.mEsimStorageContainer = mContentView.findViewById(R.id.erase_esim_container);
mMainClear.mEsimStorageContainer.setVisibility(View.VISIBLE);
mMainClear.mEsimStorage.setChecked(false);
mMainClear.showFinalConfirmation();
final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
verify(context).startActivity(intent.capture());
assertThat(intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
.getBoolean(MainClear.ERASE_ESIMS_EXTRA, false))
.isFalse();
}
@Test
public void testShowFinalConfirmation_eraseEsimGone_eraseEsimChecked() {
final Context context = mock(Context.class);
when(mMainClear.getContext()).thenReturn(context);
mMainClear.mEsimStorage = mContentView.findViewById(R.id.erase_esim);
mMainClear.mExternalStorage = mContentView.findViewById(R.id.erase_external);
mMainClear.mEsimStorageContainer = mContentView.findViewById(R.id.erase_esim_container);
mMainClear.mEsimStorageContainer.setVisibility(View.GONE);
mMainClear.mEsimStorage.setChecked(true);
mMainClear.showFinalConfirmation();
final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
verify(context).startActivity(intent.capture());
assertThat(intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
.getBoolean(MainClear.ERASE_ESIMS_EXTRA, false))
.isTrue();
}
@Test
public void testShowFinalConfirmation_eraseEsimGone_eraseEsimUnchecked() {
final Context context = mock(Context.class);
when(mMainClear.getContext()).thenReturn(context);
mMainClear.mEsimStorage = mContentView.findViewById(R.id.erase_esim);
mMainClear.mExternalStorage = mContentView.findViewById(R.id.erase_external);
mMainClear.mEsimStorageContainer = mContentView.findViewById(R.id.erase_esim_container);
mMainClear.mEsimStorageContainer.setVisibility(View.GONE);
mMainClear.mEsimStorage.setChecked(false);
mMainClear.showFinalConfirmation();
final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
verify(context).startActivity(intent.capture());
assertThat(intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
.getBoolean(MainClear.ERASE_ESIMS_EXTRA, false))
.isFalse();
}
@Test
public void testShowWipeEuicc_euiccDisabled() {
prepareEuiccState(
false /* isEuiccEnabled */,
true /* isEuiccProvisioned */,
false /* isDeveloper */);
assertThat(mMainClear.showWipeEuicc()).isFalse();
}
@Test
public void testShowWipeEuicc_euiccEnabled_unprovisioned() {
prepareEuiccState(
true /* isEuiccEnabled */,
false /* isEuiccProvisioned */,
false /* isDeveloper */);
assertThat(mMainClear.showWipeEuicc()).isFalse();
}
@Test
public void testShowWipeEuicc_euiccEnabled_provisioned() {
prepareEuiccState(
true /* isEuiccEnabled */,
true /* isEuiccProvisioned */,
false /* isDeveloper */);
assertThat(mMainClear.showWipeEuicc()).isTrue();
}
@Ignore("b/313566998")
@Test
public void testShowWipeEuicc_developerMode_unprovisioned() {
prepareEuiccState(
true /* isEuiccEnabled */,
false /* isEuiccProvisioned */,
true /* isDeveloper */);
assertThat(mMainClear.showWipeEuicc()).isTrue();
}
@Test
public void testEsimRecheckBoxDefaultChecked() {
assertThat(((CheckBox) mContentView.findViewById(R.id.erase_esim)).isChecked()).isFalse();
}
@Test
public void testHasReachedBottom_NotScrollDown_returnFalse() {
initScrollView(100, 0, 200);
assertThat(mMainClear.hasReachedBottom(mScrollView)).isFalse();
}
@Test
public void testHasReachedBottom_CanNotScroll_returnTrue() {
initScrollView(100, 0, 80);
assertThat(mMainClear.hasReachedBottom(mScrollView)).isTrue();
}
@Test
public void testHasReachedBottom_ScrollToBottom_returnTrue() {
initScrollView(100, 100, 200);
assertThat(mMainClear.hasReachedBottom(mScrollView)).isTrue();
}
@Test
public void testInitiateMainClear_inDemoMode_sendsIntent() {
ShadowUtils.setIsDemoUser(true);
final ComponentName componentName =
ComponentName.unflattenFromString("com.android.retaildemo/.DeviceAdminReceiver");
ShadowUtils.setDeviceOwnerComponent(componentName);
mMainClear.mInitiateListener.onClick(mContentView);
final Intent intent = mShadowActivity.getNextStartedActivity();
assertThat(Intent.ACTION_FACTORY_RESET).isEqualTo(intent.getAction());
assertThat(componentName).isNotNull();
assertThat(componentName.getPackageName()).isEqualTo(intent.getPackage());
}
@Test
public void testOnActivityResultInternal_invalideRequest() {
int invalidRequestCode = -1;
doReturn(false).when(mMainClear).isValidRequestCode(eq(invalidRequestCode));
mMainClear.onActivityResultInternal(invalidRequestCode, Activity.RESULT_OK, null);
verify(mMainClear, times(1)).isValidRequestCode(eq(invalidRequestCode));
verify(mMainClear, times(0)).establishInitialState();
verify(mMainClear, times(0)).getAccountConfirmationIntent();
verify(mMainClear, times(0)).showFinalConfirmation();
}
@Test
public void testOnActivityResultInternal_resultCanceled() {
doReturn(true).when(mMainClear).isValidRequestCode(eq(MainClear.KEYGUARD_REQUEST));
doNothing().when(mMainClear).establishInitialState();
mMainClear
.onActivityResultInternal(MainClear.KEYGUARD_REQUEST, Activity.RESULT_CANCELED,
null);
verify(mMainClear, times(1)).isValidRequestCode(eq(MainClear.KEYGUARD_REQUEST));
verify(mMainClear, times(1)).establishInitialState();
verify(mMainClear, times(0)).getAccountConfirmationIntent();
verify(mMainClear, times(0)).showFinalConfirmation();
}
@Test
public void testOnActivityResultInternal_keyguardRequestTriggeringConfirmAccount() {
doReturn(true).when(mMainClear).isValidRequestCode(eq(MainClear.KEYGUARD_REQUEST));
doReturn(mMockIntent).when(mMainClear).getAccountConfirmationIntent();
doNothing().when(mMainClear).showAccountCredentialConfirmation(eq(mMockIntent));
mMainClear
.onActivityResultInternal(MainClear.KEYGUARD_REQUEST, Activity.RESULT_OK, null);
verify(mMainClear, times(1)).isValidRequestCode(eq(MainClear.KEYGUARD_REQUEST));
verify(mMainClear, times(0)).establishInitialState();
verify(mMainClear, times(1)).getAccountConfirmationIntent();
verify(mMainClear, times(1)).showAccountCredentialConfirmation(eq(mMockIntent));
}
@Test
public void testOnActivityResultInternal_keyguardRequestTriggeringShowFinal() {
doReturn(true).when(mMainClear).isValidRequestCode(eq(MainClear.KEYGUARD_REQUEST));
doReturn(null).when(mMainClear).getAccountConfirmationIntent();
doNothing().when(mMainClear).showFinalConfirmation();
mMainClear
.onActivityResultInternal(MainClear.KEYGUARD_REQUEST, Activity.RESULT_OK, null);
verify(mMainClear, times(1)).isValidRequestCode(eq(MainClear.KEYGUARD_REQUEST));
verify(mMainClear, times(0)).establishInitialState();
verify(mMainClear, times(1)).getAccountConfirmationIntent();
verify(mMainClear, times(1)).showFinalConfirmation();
}
@Test
public void testOnActivityResultInternal_confirmRequestTriggeringShowFinal() {
doReturn(true).when(mMainClear)
.isValidRequestCode(eq(MainClear.CREDENTIAL_CONFIRM_REQUEST));
doNothing().when(mMainClear).showFinalConfirmation();
mMainClear.onActivityResultInternal(
MainClear.CREDENTIAL_CONFIRM_REQUEST, Activity.RESULT_OK, null);
verify(mMainClear, times(1))
.isValidRequestCode(eq(MainClear.CREDENTIAL_CONFIRM_REQUEST));
verify(mMainClear, times(0)).establishInitialState();
verify(mMainClear, times(0)).getAccountConfirmationIntent();
verify(mMainClear, times(1)).showFinalConfirmation();
}
@Test
public void testGetAccountConfirmationIntent_unsupported() {
when(mMainClear.getActivity()).thenReturn(mActivity);
/* Using the default resources, account confirmation shouldn't trigger */
assertThat(mMainClear.getAccountConfirmationIntent()).isNull();
}
@Test
public void testGetAccountConfirmationIntent_no_relevant_accounts() {
when(mMainClear.getActivity()).thenReturn(mMockActivity);
when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE);
when(mMockActivity.getString(R.string.account_confirmation_package))
.thenReturn(TEST_CONFIRMATION_PACKAGE);
when(mMockActivity.getString(R.string.account_confirmation_class))
.thenReturn(TEST_CONFIRMATION_CLASS);
Account[] accounts = new Account[0];
when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager);
when(mAccountManager.getAccountsByType(TEST_ACCOUNT_TYPE)).thenReturn(accounts);
assertThat(mMainClear.getAccountConfirmationIntent()).isNull();
}
@Test
public void testGetAccountConfirmationIntent_unresolved() {
when(mMainClear.getActivity()).thenReturn(mMockActivity);
when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE);
when(mMockActivity.getString(R.string.account_confirmation_package))
.thenReturn(TEST_CONFIRMATION_PACKAGE);
when(mMockActivity.getString(R.string.account_confirmation_class))
.thenReturn(TEST_CONFIRMATION_CLASS);
Account[] accounts = new Account[]{new Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_TYPE)};
when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager);
when(mAccountManager.getAccountsByType(TEST_ACCOUNT_TYPE)).thenReturn(accounts);
// The package manager should not resolve the confirmation intent targeting the non-existent
// confirmation package.
when(mMockActivity.getPackageManager()).thenReturn(mPackageManager);
assertThat(mMainClear.getAccountConfirmationIntent()).isNull();
}
@Test
public void testTryShowAccountConfirmation_ok() {
when(mMainClear.getActivity()).thenReturn(mMockActivity);
// Only try to show account confirmation if the appropriate resource overlays are available.
when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE);
when(mMockActivity.getString(R.string.account_confirmation_package))
.thenReturn(TEST_CONFIRMATION_PACKAGE);
when(mMockActivity.getString(R.string.account_confirmation_class))
.thenReturn(TEST_CONFIRMATION_CLASS);
// Add accounts to trigger the search for a resolving intent.
Account[] accounts = new Account[]{new Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_TYPE)};
when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager);
when(mAccountManager.getAccountsByType(TEST_ACCOUNT_TYPE)).thenReturn(accounts);
// The package manager should not resolve the confirmation intent targeting the non-existent
// confirmation package.
when(mMockActivity.getPackageManager()).thenReturn(mPackageManager);
ActivityInfo activityInfo = new ActivityInfo();
activityInfo.packageName = TEST_CONFIRMATION_PACKAGE;
ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.activityInfo = activityInfo;
when(mPackageManager.resolveActivity(any(), eq(0))).thenReturn(resolveInfo);
Intent actualIntent = mMainClear.getAccountConfirmationIntent();
assertThat(TEST_CONFIRMATION_PACKAGE).isEqualTo(
actualIntent.getComponent().getPackageName());
assertThat(TEST_CONFIRMATION_CLASS).isEqualTo(actualIntent.getComponent().getClassName());
}
@Test
public void testShowAccountCredentialConfirmation() {
// Finally mock out the startActivityForResultCall
doNothing().when(mMainClear)
.startActivityForResult(eq(mMockIntent),
eq(MainClear.CREDENTIAL_CONFIRM_REQUEST));
mMainClear.showAccountCredentialConfirmation(mMockIntent);
verify(mMainClear, times(1))
.startActivityForResult(eq(mMockIntent),
eq(MainClear.CREDENTIAL_CONFIRM_REQUEST));
}
@Test
public void testIsValidRequestCode() {
assertThat(mMainClear.isValidRequestCode(MainClear.KEYGUARD_REQUEST)).isTrue();
assertThat(mMainClear.isValidRequestCode(MainClear.CREDENTIAL_CONFIRM_REQUEST))
.isTrue();
assertThat(mMainClear.isValidRequestCode(0)).isFalse();
}
@Test
public void testOnGlobalLayout_shouldNotRemoveListener() {
final ViewTreeObserver viewTreeObserver = mock(ViewTreeObserver.class);
mMainClear.mScrollView = mScrollView;
doNothing().when(mMainClear).onGlobalLayout();
doReturn(true).when(mMainClear).hasReachedBottom(any());
when(mScrollView.getViewTreeObserver()).thenReturn(viewTreeObserver);
mMainClear.onGlobalLayout();
verify(viewTreeObserver, never()).removeOnGlobalLayoutListener(mMainClear);
}
private void prepareEuiccState(
boolean isEuiccEnabled, boolean isEuiccProvisioned, boolean isDeveloper) {
doReturn(mActivity).when(mMainClear).getContext();
doReturn(isEuiccEnabled).when(mMainClear).isEuiccEnabled(any());
ContentResolver cr = mActivity.getContentResolver();
Settings.Global.putInt(cr, Settings.Global.EUICC_PROVISIONED, isEuiccProvisioned ? 1 : 0);
DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(mActivity, isDeveloper);
}
private void initScrollView(int height, int scrollY, int childBottom) {
when(mScrollView.getHeight()).thenReturn(height);
when(mScrollView.getScrollY()).thenReturn(scrollY);
when(mLinearLayout.getBottom()).thenReturn(childBottom);
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2020 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;
import static android.view.HapticFeedbackConstants.CLOCK_TICK;
import static android.view.HapticFeedbackConstants.CONTEXT_CLICK;
import static com.google.common.truth.Truth.assertThat;
import static org.robolectric.Shadows.shadowOf;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.SeekBar;
import com.android.settings.testutils.shadow.ShadowInteractionJankMonitor;
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;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowInteractionJankMonitor.class})
public class PointerSpeedPreferenceTest {
private Context mContext;
private AttributeSet mAttrs;
private SeekBar mSeekBar;
private PointerSpeedPreference mPointerSpeedPreference;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mSeekBar = new SeekBar(mContext, mAttrs);
mPointerSpeedPreference = new PointerSpeedPreference(mContext, mAttrs);
}
@Test
public void onProgressChanged_minimumValue_clockTickFeedbackPerformed() {
mSeekBar.performHapticFeedback(CONTEXT_CLICK);
mPointerSpeedPreference.onProgressChanged(mSeekBar, 0, true);
assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isEqualTo(CLOCK_TICK);
}
}

View File

@@ -0,0 +1,124 @@
/*
* 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;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Looper;
import android.view.LayoutInflater;
import android.widget.TextView;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowRecoverySystem;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.LooperMode;
@RunWith(RobolectricTestRunner.class)
@LooperMode(LooperMode.Mode.LEGACY)
@Config(shadows = {ShadowRecoverySystem.class, ShadowBluetoothAdapter.class})
public class ResetNetworkConfirmTest {
private static final String TEST_PACKAGE = "com.android.settings";
private FragmentActivity mActivity;
@Mock
private ResetNetworkConfirm mResetNetworkConfirm;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mResetNetworkConfirm = new ResetNetworkConfirm();
mActivity = spy(Robolectric.setupActivity(FragmentActivity.class));
mResetNetworkConfirm.mActivity = mActivity;
}
@After
public void tearDown() {
ShadowRecoverySystem.reset();
}
@Test
public void testResetNetworkData_notResetEsim() {
mResetNetworkConfirm.mResetNetworkRequest =
new ResetNetworkRequest(ResetNetworkRequest.RESET_NONE);
mResetNetworkConfirm.mResetSubscriptionContract =
new ResetSubscriptionContract(mActivity,
mResetNetworkConfirm.mResetNetworkRequest) {
@Override
public void onSubscriptionInactive(int subscriptionId) {
mActivity.onBackPressed();
}
};
mResetNetworkConfirm.mFinalClickListener.onClick(null /* View */);
Robolectric.getBackgroundThreadScheduler().advanceToLastPostedRunnable();
assertThat(ShadowRecoverySystem.getWipeEuiccCalledCount()).isEqualTo(0);
}
@Test
public void setSubtitle_eraseEsim() {
mResetNetworkConfirm.mResetNetworkRequest =
new ResetNetworkRequest(ResetNetworkRequest.RESET_NONE);
mResetNetworkConfirm.mResetNetworkRequest.setResetEsim(TEST_PACKAGE);
mResetNetworkConfirm.mContentView =
LayoutInflater.from(mActivity).inflate(R.layout.reset_network_confirm, null);
mResetNetworkConfirm.setSubtitle();
assertThat(((TextView) mResetNetworkConfirm.mContentView
.findViewById(R.id.reset_network_confirm)).getText())
.isEqualTo(mActivity.getString(R.string.reset_network_final_desc_esim));
}
@Test
public void setSubtitle_notEraseEsim() {
mResetNetworkConfirm.mResetNetworkRequest =
new ResetNetworkRequest(ResetNetworkRequest.RESET_NONE);
mResetNetworkConfirm.mContentView =
LayoutInflater.from(mActivity).inflate(R.layout.reset_network_confirm, null);
mResetNetworkConfirm.setSubtitle();
assertThat(((TextView) mResetNetworkConfirm.mContentView
.findViewById(R.id.reset_network_confirm)).getText())
.isEqualTo(mActivity.getString(R.string.reset_network_final_desc));
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2019 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;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.widget.CheckBox;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class ResetNetworkTest {
private Activity mActivity;
private ResetNetwork mResetNetwork;
@Before
public void setUp() {
mActivity = Robolectric.setupActivity(Activity.class);
mResetNetwork = spy(new ResetNetwork());
when(mResetNetwork.getContext()).thenReturn(mActivity);
mResetNetwork.mEsimContainer = new View(mActivity);
mResetNetwork.mEsimCheckbox = new CheckBox(mActivity);
}
@Test
@Ignore
public void showFinalConfirmation_checkboxVisible_eraseEsimChecked() {
mResetNetwork.mEsimContainer.setVisibility(View.VISIBLE);
mResetNetwork.mEsimCheckbox.setChecked(true);
mResetNetwork.showFinalConfirmation();
Intent intent = shadowOf(mActivity).getNextStartedActivity();
assertThat(intent.getStringExtra(ResetNetworkRequest.KEY_ESIM_PACKAGE))
.isNotNull();
}
@Test
public void showFinalConfirmation_checkboxVisible_eraseEsimUnchecked() {
mResetNetwork.mEsimContainer.setVisibility(View.VISIBLE);
mResetNetwork.mEsimCheckbox.setChecked(false);
mResetNetwork.showFinalConfirmation();
Intent intent = shadowOf(mActivity).getNextStartedActivity();
assertThat(intent.getStringExtra(ResetNetworkRequest.KEY_ESIM_PACKAGE))
.isNull();
}
@Test
public void showFinalConfirmation_checkboxGone_eraseEsimChecked() {
mResetNetwork.mEsimContainer.setVisibility(View.GONE);
mResetNetwork.mEsimCheckbox.setChecked(true);
mResetNetwork.showFinalConfirmation();
Intent intent = shadowOf(mActivity).getNextStartedActivity();
assertThat(intent.getStringExtra(ResetNetworkRequest.KEY_ESIM_PACKAGE))
.isNull();
}
@Test
public void showFinalConfirmation_checkboxGone_eraseEsimUnchecked() {
mResetNetwork.mEsimContainer.setVisibility(View.GONE);
mResetNetwork.mEsimCheckbox.setChecked(false);
mResetNetwork.showFinalConfirmation();
Intent intent = shadowOf(mActivity).getNextStartedActivity();
assertThat(intent.getStringExtra(ResetNetworkRequest.KEY_ESIM_PACKAGE))
.isNull();
}
}

View File

@@ -0,0 +1,128 @@
/*
* 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;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.RuntimeEnvironment.application;
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.Intent;
import android.os.Bundle;
import android.util.AttributeSet;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.RestrictedPreferenceHelper;
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.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowKeyguardManager;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowUserManager.class, ShadowKeyguardManager.class})
public class RestrictedListPreferenceTest {
private static final int PROFILE_USER_ID = 11;
// From UnlaunchableAppActivity
private static final int UNLAUNCHABLE_REASON_QUIET_MODE = 1;
private static final String EXTRA_UNLAUNCHABLE_REASON = "unlaunchable_reason";
private Activity mActivity;
private ShadowUserManager mShadowUserManager;
private ShadowKeyguardManager mShadowKeyguardManager;
private RestrictedListPreference mPreference;
private RestrictedPreferenceHelper mMockHelper;
@Before
public void setUp() {
mActivity = Robolectric.setupActivity(Activity.class);
mShadowKeyguardManager =
Shadows.shadowOf(application.getSystemService(KeyguardManager.class));
mMockHelper = mock(RestrictedPreferenceHelper.class);
mShadowUserManager = ShadowUserManager.getShadow();
AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
mPreference = new RestrictedListPreference(mActivity, attributeSet);
mPreference.setProfileUserId(PROFILE_USER_ID);
ReflectionHelpers.setField(mPreference, "mHelper", mMockHelper);
}
@Test
public void performClick_profileLocked() {
mPreference.setRequiresActiveUnlockedProfile(true);
mShadowUserManager.setQuietModeEnabled(false);
mShadowKeyguardManager.setIsDeviceLocked(PROFILE_USER_ID, true);
// Device has to be marked as secure so the real KeyguardManager will create a non-null
// intent.
mShadowKeyguardManager.setIsDeviceSecure(PROFILE_USER_ID, true);
mPreference.performClick();
// Make sure that the performClick method on the helper is never reached.
verify(mMockHelper, never()).performClick();
// Assert that a CONFIRM_DEVICE_CREDENTIAL intent has been started.
Intent started = Shadows.shadowOf(mActivity).getNextStartedActivity();
assertThat(started.getExtras().getInt(Intent.EXTRA_USER_ID)).isEqualTo(PROFILE_USER_ID);
assertThat(started.getAction())
.isEqualTo(KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER);
}
@Test
public void performClick_profileDisabled() {
mPreference.setRequiresActiveUnlockedProfile(true);
mShadowUserManager.setQuietModeEnabled(true);
mShadowKeyguardManager.setIsDeviceLocked(PROFILE_USER_ID, false);
mPreference.performClick();
// Make sure that the performClick method on the helper is never reached.
verify(mMockHelper, never()).performClick();
// Assert that a new intent for enabling the work profile is started.
Intent started = Shadows.shadowOf(mActivity).getNextStartedActivity();
Bundle extras = started.getExtras();
int reason = extras.getInt(EXTRA_UNLAUNCHABLE_REASON);
assertThat(reason).isEqualTo(UNLAUNCHABLE_REASON_QUIET_MODE);
}
@Test
public void performClick_profileAvailable() {
// Verify that the helper's perfomClick method is called if the profile is
// available and unlocked.
mPreference.setRequiresActiveUnlockedProfile(true);
mShadowUserManager.setQuietModeEnabled(false);
mShadowKeyguardManager.setIsDeviceLocked(PROFILE_USER_ID, false);
when(mMockHelper.performClick()).thenReturn(true);
mPreference.performClick();
verify(mMockHelper).performClick();
}
@Test
public void performClick_profileLockedAndUnlockedProfileNotRequired() {
// Verify that even if the profile is disabled, if the Preference class does not
// require it than the regular flow takes place.
mPreference.setRequiresActiveUnlockedProfile(false);
mShadowUserManager.setQuietModeEnabled(true);
when(mMockHelper.performClick()).thenReturn(true);
mPreference.performClick();
verify(mMockHelper).performClick();
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.Activity;
import androidx.appcompat.app.AlertDialog;
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;
@RunWith(RobolectricTestRunner.class)
public class RestrictedSettingsFragmentTest {
@Mock
private AlertDialog mAlertDialog;
private RestrictedSettingsFragment mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void onActivityResult_dismissesDialogOnOk() {
mFragment = new RestrictedSettingsFragment("fake_key") {
@Override
public int getMetricsCategory() {
return 0;
}
};
doReturn(true).when(mAlertDialog).isShowing();
mFragment.mActionDisabledDialog = mAlertDialog;
mFragment.onActivityResult(RestrictedSettingsFragment.REQUEST_PIN_CHALLENGE,
Activity.RESULT_OK,
null);
// dialog should be gone
verify(mAlertDialog, times(1)).setOnDismissListener(isNull());
verify(mAlertDialog, times(1)).dismiss();
}
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (C) 2016 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;
import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT;
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.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.android.settings.core.OnActivityResultListener;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowUserManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
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.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowUserManager.class)
public class SettingsActivityTest {
@Mock
private FragmentManager mFragmentManager;
@Mock
private ActivityManager.TaskDescription mTaskDescription;
private SettingsActivity mActivity;
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mActivity = spy(Robolectric.buildActivity(SettingsActivity.class).create().get());
}
@Test
public void launchSettingFragment_nullExtraShowFragment_shouldNotCrash() {
when(mActivity.getSupportFragmentManager()).thenReturn(mFragmentManager);
doReturn(mContext.getContentResolver()).when(mActivity).getContentResolver();
when(mFragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class));
doReturn(RuntimeEnvironment.application.getClassLoader()).when(mActivity).getClassLoader();
mActivity.launchSettingFragment(null, mock(Intent.class));
}
@Test
public void setTaskDescription_shouldUpdateIcon() {
mActivity.setTaskDescription(mTaskDescription);
verify(mTaskDescription).setIcon(any());
}
@Test
public void getSharedPreferences_intentExtraIsNull_shouldNotCrash() {
final Intent intent = new Intent();
intent.putExtra(EXTRA_SHOW_FRAGMENT, (String)null);
doReturn(intent).when(mActivity).getIntent();
doReturn(mContext.getPackageName()).when(mActivity).getPackageName();
FakeFeatureFactory.setupForTest();
mActivity.getSharedPreferences(mContext.getPackageName() + "_preferences", 0);
}
@Test
public void onActivityResult_shouldDelegateToListener() {
final List<Fragment> fragments = new ArrayList<>();
fragments.add(new Fragment());
fragments.add(new ListenerFragment());
final FragmentManager manager = mock(FragmentManager.class);
when(mActivity.getSupportFragmentManager()).thenReturn(manager);
when(manager.getFragments()).thenReturn(fragments);
mActivity.onActivityResult(0, 0, new Intent());
assertThat(((ListenerFragment) fragments.get(1)).mOnActivityResultCalled).isTrue();
}
public static class ListenerFragment extends Fragment implements OnActivityResultListener {
private boolean mOnActivityResultCalled;
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mOnActivityResultCalled = true;
}
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2016 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;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Dialog;
import androidx.fragment.app.Fragment;
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 SettingsDialogFragmentTest {
private static final int DIALOG_ID = 15;
@Mock
private DialogCreatableFragment mDialogCreatable;
private SettingsPreferenceFragment.SettingsDialogFragment mDialogFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testGetMetrics_shouldGetMetricFromDialogCreatable() {
when(mDialogCreatable.getDialogMetricsCategory(DIALOG_ID)).thenReturn(1);
mDialogFragment = SettingsPreferenceFragment.SettingsDialogFragment.newInstance(
mDialogCreatable, DIALOG_ID);
mDialogFragment.onAttach(RuntimeEnvironment.application);
mDialogFragment.getMetricsCategory();
// getDialogMetricsCategory called in onAttach, and explicitly in test.
verify(mDialogCreatable, times(2)).getDialogMetricsCategory(DIALOG_ID);
}
@Test
public void testGetInvalidMetricsValue_shouldCrash() {
when(mDialogCreatable.getDialogMetricsCategory(DIALOG_ID)).thenReturn(-1);
try {
mDialogFragment = SettingsPreferenceFragment.SettingsDialogFragment.newInstance(
mDialogCreatable, DIALOG_ID);
mDialogFragment.onAttach(RuntimeEnvironment.application);
fail("Should fail with IllegalStateException");
} catch (IllegalStateException e) {
// getDialogMetricsCategory called in constructor
verify(mDialogCreatable).getDialogMetricsCategory(DIALOG_ID);
}
}
public static class DialogCreatableFragment extends Fragment implements DialogCreatable {
@Override
public Dialog onCreateDialog(int dialogId) {
return null;
}
@Override
public int getDialogMetricsCategory(int dialogId) {
return 0;
}
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2016 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;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
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.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
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 java.io.PrintWriter;
import java.io.StringWriter;
@RunWith(RobolectricTestRunner.class)
public class SettingsDumpServiceTest {
private static final String PACKAGE_BROWSER = "com.android.test.browser";
private static final String PACKAGE_NULL = "android";
private static final int ANOMALY_VERSION = 2;
@Mock
private PackageManager mPackageManager;
@Mock
private ResolveInfo mResolveInfo;
private TestService mTestService;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mPackageManager.resolveActivity(TestService.BROWSER_INTENT,
PackageManager.MATCH_DEFAULT_ONLY)).thenReturn(mResolveInfo);
mTestService = spy(new TestService());
mTestService.setPackageManager(mPackageManager);
}
@Test
public void testDumpDefaultBrowser_DefaultBrowser_ReturnBrowserName() {
mResolveInfo.activityInfo = new ActivityInfo();
mResolveInfo.activityInfo.packageName = PACKAGE_BROWSER;
assertThat(mTestService.dumpDefaultBrowser()).isEqualTo(PACKAGE_BROWSER);
}
@Test
public void testDumpDefaultBrowser_NoDefault_ReturnNull() {
mResolveInfo.activityInfo = new ActivityInfo();
mResolveInfo.activityInfo.packageName = PACKAGE_NULL;
assertThat(mTestService.dumpDefaultBrowser()).isEqualTo(null);
}
@Test
public void testDump_printServiceAsKey() {
mResolveInfo.activityInfo = new ActivityInfo();
mResolveInfo.activityInfo.packageName = PACKAGE_BROWSER;
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
mTestService.dump(null, printWriter, null);
assertThat(stringWriter.toString())
.contains("{\"" + SettingsDumpService.KEY_SERVICE + "\":");
}
/**
* Test service used to pass in the mock {@link PackageManager}
*/
private class TestService extends SettingsDumpService {
private PackageManager mPm;
public void setPackageManager(PackageManager pm) {
mPm = pm;
}
@Override
public PackageManager getPackageManager() {
return mPm;
}
}
}

View File

@@ -0,0 +1,99 @@
/*
* 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;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class SettingsInitializeTest {
private Context mContext;
private SettingsInitialize mSettingsInitialize;
private ShortcutManager mShortcutManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mSettingsInitialize = new SettingsInitialize();
mShortcutManager = (ShortcutManager) mContext.getSystemService(Context.SHORTCUT_SERVICE);
}
@Test
public void refreshExistingShortcuts_shouldUpdateLaunchIntentFlagsForExistingShortcut() {
final String id = "test_shortcut_id";
final Intent intent = new Intent(Intent.ACTION_DEFAULT);
intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
final ShortcutInfo info = new ShortcutInfo.Builder(mContext, id)
.setShortLabel("test123")
.setIntent(intent)
.build();
mShortcutManager.addDynamicShortcuts(Collections.singletonList(info));
mShortcutManager.requestPinShortcut(info, null);
mSettingsInitialize.refreshExistingShortcuts(mContext);
final List<ShortcutInfo> updatedShortcuts = mShortcutManager.getPinnedShortcuts();
assertThat(updatedShortcuts).hasSize(1);
final ShortcutInfo updateInfo = updatedShortcuts.get(0);
assertThat(updateInfo.getId()).isEqualTo(id);
final int flags = updateInfo.getIntent().getFlags();
// The original flag should be removed
assertThat(flags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED).isEqualTo(0);
// The new flags should be set
assertThat(flags & Intent.FLAG_ACTIVITY_NEW_TASK).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK);
assertThat(flags & Intent.FLAG_ACTIVITY_CLEAR_TOP).isEqualTo(
Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
@Test
public void refreshExistingShortcuts_shouldNotUpdateImmutableShortcut() {
final String id = "test_shortcut_id";
final ShortcutInfo info = new ShortcutInfo.Builder(mContext, id)
.setShortLabel("test123")
.setIntent(new Intent(Intent.ACTION_DEFAULT))
.build();
info.addFlags(ShortcutInfo.FLAG_IMMUTABLE);
mShortcutManager.addDynamicShortcuts(Collections.singletonList(info));
mShortcutManager.requestPinShortcut(info, null);
mSettingsInitialize.refreshExistingShortcuts(mContext);
final List<ShortcutInfo> updatedShortcuts = mShortcutManager.getPinnedShortcuts();
assertThat(updatedShortcuts).hasSize(1);
assertThat(updatedShortcuts.get(0)).isSameInstanceAs(info);
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2017 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;
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 android.app.Application;
import android.content.Intent;
import android.net.Uri;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.android.controller.ActivityController;
import java.io.File;
@RunWith(RobolectricTestRunner.class)
public class SettingsLicenseActivityTest {
private ActivityController<SettingsLicenseActivity> mActivityController;
private SettingsLicenseActivity mActivity;
private Application mApplication;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mApplication = RuntimeEnvironment.application;
mActivityController = Robolectric.buildActivity(SettingsLicenseActivity.class);
mActivity = spy(mActivityController.get());
}
private void assertEqualIntents(Intent actual, Intent expected) {
assertThat(actual.getAction()).isEqualTo(expected.getAction());
assertThat(actual.getDataString()).isEqualTo(expected.getDataString());
assertThat(actual.getType()).isEqualTo(expected.getType());
assertThat(actual.getCategories()).isEqualTo(expected.getCategories());
assertThat(actual.getPackage()).isEqualTo(expected.getPackage());
assertThat(actual.getFlags()).isEqualTo(expected.getFlags());
}
@Test
public void testOnCreateWithValidHtmlFile() {
doReturn(true).when(mActivity).isFileValid(any());
mActivity.onCreate(null);
final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file:///system/etc/NOTICE.html.gz"), "text/html");
intent.putExtra(Intent.EXTRA_TITLE, mActivity.getString(
R.string.settings_license_activity_title));
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setPackage("com.android.htmlviewer");
assertEqualIntents(Shadows.shadowOf(mApplication).getNextStartedActivity(), intent);
}
@Test
public void testOnCreateWithGeneratedHtmlFile() {
doReturn(Uri.parse("content://com.android.settings.files/my_cache/generated_test.html"))
.when(mActivity).getUriFromGeneratedHtmlFile(any());
mActivity.onCreate(null);
mActivity.onLoadFinished(null, new File("/generated_test.html"));
final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.parse("content://com.android.settings.files/my_cache/generated_test.html"),
"text/html");
intent.putExtra(Intent.EXTRA_TITLE, mActivity.getString(
R.string.settings_license_activity_title));
intent.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setPackage("com.android.htmlviewer");
assertEqualIntents(Shadows.shadowOf(mApplication).getNextStartedActivity(), intent);
}
}

View File

@@ -0,0 +1,294 @@
/*
* Copyright (C) 2017 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;
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.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 static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.FrameLayout;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.widget.WorkOnlyCategory;
import org.junit.After;
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.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class SettingsPreferenceFragmentTest {
private static final int ITEM_COUNT = 5;
@Mock
private FragmentActivity mActivity;
@Mock
private View mListContainer;
@Mock
private PreferenceScreen mPreferenceScreen;
private Context mContext;
private TestFragment mFragment;
private TestFragment2 mFragment2;
private View mEmptyView;
private int mInitDeviceProvisionedValue;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest();
mContext = RuntimeEnvironment.application;
mFragment = spy(new TestFragment());
mFragment2 = spy(new TestFragment2());
doReturn(mActivity).when(mFragment).getActivity();
when(mFragment.getContext()).thenReturn(mContext);
when(mFragment2.getContext()).thenReturn(mContext);
mEmptyView = new View(mContext);
ReflectionHelpers.setField(mFragment, "mEmptyView", mEmptyView);
doReturn(ITEM_COUNT).when(mPreferenceScreen).getPreferenceCount();
mInitDeviceProvisionedValue = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0);
}
@After
public void tearDown() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, mInitDeviceProvisionedValue);
}
@Test
public void removePreference_nested_shouldRemove() {
final String key = "test_key";
final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null));
when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
final PreferenceCategory nestedCategory = new ProgressCategory(mContext);
final Preference preference = new Preference(mContext);
preference.setKey(key);
preference.setPersistent(false);
mScreen.addPreference(nestedCategory);
nestedCategory.addPreference(preference);
assertThat(mFragment.removePreference(mScreen, key)).isTrue();
assertThat(nestedCategory.getPreferenceCount()).isEqualTo(0);
}
@Test
public void removePreference_flat_shouldRemove() {
final String key = "test_key";
final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null));
when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
final Preference preference = mock(Preference.class);
when(preference.getKey()).thenReturn(key);
mScreen.addPreference(preference);
assertThat(mFragment.removePreference(mScreen, key)).isTrue();
assertThat(mScreen.getPreferenceCount()).isEqualTo(0);
}
@Test
public void removePreference_doNotExist_shouldNotRemove() {
final String key = "test_key";
final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null));
when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
final Preference preference = mock(Preference.class);
when(preference.getKey()).thenReturn(key);
mScreen.addPreference(preference);
assertThat(mFragment.removePreference(mScreen, "not" + key)).isFalse();
assertThat(mScreen.getPreferenceCount()).isEqualTo(1);
}
@Test
public void testUpdateEmptyView_containerInvisible_emptyViewVisible() {
doReturn(View.INVISIBLE).when(mListContainer).getVisibility();
doReturn(mListContainer).when(mActivity).findViewById(android.R.id.list_container);
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
mFragment.updateEmptyView();
assertThat(mEmptyView.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
public void testUpdateEmptyView_containerNull_emptyViewGone() {
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
mFragment.updateEmptyView();
assertThat(mEmptyView.getVisibility()).isEqualTo(View.GONE);
}
@Test
public void onCreate_hasExtraFragmentKey_shouldExpandPreferences() {
doReturn(mContext.getTheme()).when(mActivity).getTheme();
doReturn(mContext.getResources()).when(mFragment).getResources();
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
final Bundle bundle = new Bundle();
bundle.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, "test_key");
when(mFragment.getArguments()).thenReturn(bundle);
mFragment.onCreate(null /* icicle */);
verify(mPreferenceScreen).setInitialExpandedChildrenCount(Integer.MAX_VALUE);
}
@Test
public void onCreate_noPreferenceScreen_shouldNotCrash() {
doReturn(mContext.getTheme()).when(mActivity).getTheme();
doReturn(mContext.getResources()).when(mFragment).getResources();
doReturn(null).when(mFragment).getPreferenceScreen();
final Bundle bundle = new Bundle();
bundle.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, "test_key");
when(mFragment.getArguments()).thenReturn(bundle);
mFragment.onCreate(null /* icicle */);
// no crash
}
@Test
public void checkAvailablePrefs_selfAvialbalePreferenceNotAvailable_shouldHidePreference() {
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
final WorkOnlyCategory workOnlyCategory = mock(WorkOnlyCategory.class);
when(mPreferenceScreen.getPreferenceCount()).thenReturn(1);
when(mPreferenceScreen.getPreference(0)).thenReturn(workOnlyCategory);
when(workOnlyCategory.isAvailable(any(Context.class))).thenReturn(false);
mFragment.checkAvailablePrefs(mPreferenceScreen);
verify(mPreferenceScreen, never()).removePreference(workOnlyCategory);
verify(workOnlyCategory).setVisible(false);
}
@Test
public void showPinnedHeader_shouldBeVisible() {
mFragment.mPinnedHeaderFrameLayout = new FrameLayout(mContext);
mFragment.showPinnedHeader(true);
assertThat(mFragment.mPinnedHeaderFrameLayout.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
public void hidePinnedHeader_shouldBeInvisible() {
mFragment.mPinnedHeaderFrameLayout = new FrameLayout(mContext);
mFragment.showPinnedHeader(false);
assertThat(mFragment.mPinnedHeaderFrameLayout.getVisibility()).isEqualTo(View.INVISIBLE);
}
@Test
public void onAttach_shouldNotSkipForSUWAndDeviceIsProvisioned_notCallFinish() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
mFragment.onAttach(mContext);
verify(mFragment, never()).finish();
}
@Test
public void onAttach_shouldNotSkipForSUWAndDeviceIsNotProvisioned_notCallFinish() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0);
mFragment.onAttach(mContext);
verify(mFragment, never()).finish();
}
@Test
public void onAttach_shouldSkipForSUWAndDeviceIsDeviceProvisioned_notCallFinish() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
mFragment2.onAttach(mContext);
verify(mFragment2, never()).finish();
}
@Test
public void onAttach_shouldSkipForSUWAndDeviceProvisioned_notCallFinish() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0);
mFragment2.onAttach(mContext);
verify(mFragment2, times(1)).finish();
}
public static class TestFragment extends SettingsPreferenceFragment {
@Override
protected boolean shouldSkipForInitialSUW() {
return false;
}
@Override
public int getMetricsCategory() {
return 0;
}
}
public static class TestFragment2 extends SettingsPreferenceFragment {
@Override
protected boolean shouldSkipForInitialSUW() {
return true;
}
@Override
public int getMetricsCategory() {
return 0;
}
}
}

View File

@@ -0,0 +1,277 @@
/*
* Copyright (C) 2016 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;
import static com.google.common.truth.Truth.assertThat;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.sysprop.SetupWizardProperties;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.core.app.ApplicationProvider;
import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.util.ThemeHelper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class SetupWizardUtilsTest {
private Context mContext;
@Before
public void setup() {
PartnerConfigHelper.resetInstance();
mContext = ApplicationProvider.getApplicationContext();
}
@Test
public void testCopySetupExtras() {
Intent fromIntent = new Intent();
final String theme = "TEST_THEME";
fromIntent.putExtra(WizardManagerHelper.EXTRA_THEME, theme);
fromIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true);
Intent toIntent = new Intent();
SetupWizardUtils.copySetupExtras(fromIntent, toIntent);
assertThat(theme).isEqualTo(toIntent.getStringExtra(WizardManagerHelper.EXTRA_THEME));
assertThat(toIntent.getBooleanExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, false))
.isTrue();
assertThat(toIntent.getBooleanExtra(WizardManagerHelper.EXTRA_IS_FIRST_RUN, true))
.isFalse();
}
@Test
public void testCopyLifecycleExtra() {
Intent fromIntent = new Intent();
final String theme = "TEST_THEME";
fromIntent.putExtra(WizardManagerHelper.EXTRA_THEME, theme);
fromIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true);
Bundle dstBundle = new Bundle();
dstBundle = SetupWizardUtils.copyLifecycleExtra(fromIntent.getExtras(), dstBundle);
assertThat(dstBundle).isNotNull();
assertThat(dstBundle.getString(WizardManagerHelper.EXTRA_THEME)).isNull();
assertThat(dstBundle.getBoolean(WizardManagerHelper.EXTRA_IS_SETUP_FLOW))
.isTrue();
assertThat(dstBundle.getBoolean(WizardManagerHelper.EXTRA_IS_FIRST_RUN))
.isFalse();
}
@Test
public void testGetTheme_withIntentExtra_shouldReturnTheme() {
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF);
Intent intent = createSetupWizardIntent();
intent.putExtra(WizardManagerHelper.EXTRA_THEME, ThemeHelper.THEME_GLIF_V2);
assertThat(SetupWizardUtils.getTheme(mContext, intent))
.isEqualTo(R.style.GlifV2Theme);
}
@Test
public void testGetTheme_withEmptyIntent_shouldReturnSystemProperty() {
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V2_LIGHT);
Intent intent = createSetupWizardIntent();
assertThat(SetupWizardUtils.getTheme(mContext, intent))
.isEqualTo(R.style.GlifV2Theme_Light);
}
@Test
public void testGetTheme_whenSuwDayNightEnabledAndWithIntentExtra_shouldReturnDayNightTheme() {
FakePartnerContentProvider provider =
Robolectric.setupContentProvider(
FakePartnerContentProvider.class, "com.google.android.setupwizard.partner");
provider.injectFakeDayNightEnabledResult(true);
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V2_LIGHT);
Intent intent = createSetupWizardIntent();
intent.putExtra(WizardManagerHelper.EXTRA_THEME, ThemeHelper.THEME_GLIF_V2);
assertThat(SetupWizardUtils.getTheme(mContext, intent))
.isEqualTo(R.style.GlifV2Theme_DayNight);
}
@Test
public void testGetTheme_glifV3Light_shouldReturnLightTheme() {
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V3_LIGHT);
Intent intent = createSetupWizardIntent();
assertThat(SetupWizardUtils.getTheme(mContext, intent))
.isEqualTo(R.style.GlifV3Theme_Light);
assertThat(SetupWizardUtils.getTransparentTheme(mContext, intent))
.isEqualTo(R.style.GlifV3Theme_Light_Transparent);
}
@Test
public void testGetTheme_glifV3_shouldReturnTheme() {
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V3);
Intent intent = createSetupWizardIntent();
assertThat(SetupWizardUtils.getTheme(mContext, intent))
.isEqualTo(R.style.GlifV3Theme);
assertThat(SetupWizardUtils.getTransparentTheme(mContext, intent))
.isEqualTo(R.style.GlifV3Theme_Transparent);
}
@Test
public void testGetTheme_whenSuwDayNightDisabledAndGlifV2_shouldReturnLightTheme() {
FakePartnerContentProvider provider =
Robolectric.setupContentProvider(
FakePartnerContentProvider.class, "com.google.android.setupwizard.partner");
provider.injectFakeDayNightEnabledResult(false);
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V2_LIGHT);
Intent intent = createSetupWizardIntent();
assertThat(SetupWizardUtils.getTheme(mContext, intent))
.isEqualTo(R.style.GlifV2Theme_Light);
}
@Test
public void testGetTheme_whenSuwDayNightEnabledAndGlifV2_shouldReturnDayNightTheme() {
FakePartnerContentProvider provider =
Robolectric.setupContentProvider(
FakePartnerContentProvider.class, "com.google.android.setupwizard.partner");
provider.injectFakeDayNightEnabledResult(true);
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V2_LIGHT);
Intent intent = createSetupWizardIntent();
assertThat(SetupWizardUtils.getTheme(mContext, intent))
.isEqualTo(R.style.GlifV2Theme_DayNight);
}
@Test
public void testGetTheme_whenSuwDayNightDisabledAndGlifV3_shouldReturnTheme() {
FakePartnerContentProvider provider =
Robolectric.setupContentProvider(
FakePartnerContentProvider.class, "com.google.android.setupwizard.partner");
provider.injectFakeDayNightEnabledResult(false);
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V3);
Intent intent = createSetupWizardIntent();
assertThat(SetupWizardUtils.getTheme(mContext, intent))
.isEqualTo(R.style.GlifV3Theme);
assertThat(SetupWizardUtils.getTransparentTheme(mContext, intent))
.isEqualTo(R.style.GlifV3Theme_Transparent);
}
@Test
public void testGetTheme_whenSuwDayNightEnabledAndGlifV3_shouldReturnDayNightTheme() {
FakePartnerContentProvider provider =
Robolectric.setupContentProvider(
FakePartnerContentProvider.class, "com.google.android.setupwizard.partner");
provider.injectFakeDayNightEnabledResult(true);
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V3);
Intent intent = createSetupWizardIntent();
assertThat(SetupWizardUtils.getTheme(mContext, intent))
.isEqualTo(R.style.GlifV3Theme_DayNight);
assertThat(SetupWizardUtils.getTransparentTheme(mContext, intent))
.isEqualTo(R.style.GlifV3Theme_DayNight_Transparent);
}
@Test
public void testGetTheme_nonSuw_shouldReturnTheme() {
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V3_LIGHT);
Intent intent = new Intent();
assertThat(SetupWizardUtils.getTheme(mContext, intent)).isEqualTo(R.style.GlifV3Theme);
assertThat(SetupWizardUtils.getTransparentTheme(mContext, intent))
.isEqualTo(R.style.GlifV3Theme_Transparent);
}
private Intent createSetupWizardIntent() {
return new Intent()
.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true)
.putExtra(WizardManagerHelper.EXTRA_IS_FIRST_RUN, true);
}
private static final class FakePartnerContentProvider extends ContentProvider {
private final Bundle mFakeProviderDayNightEnabledResultBundle = new Bundle();
@Override
public boolean onCreate() {
return true;
}
@Override
public Cursor query(
@NonNull Uri uri,
@Nullable String[] projection,
@Nullable String selection,
@Nullable String[] selectionArgs,
@Nullable String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
return null;
}
@Override
public int delete(
@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
@Override
public int update(
@NonNull Uri uri,
@Nullable ContentValues values,
@Nullable String selection,
@Nullable String[] selectionArgs) {
return 0;
}
@Override
public Bundle call(String method, String arg, Bundle extras) {
if (TextUtils.equals(method, "isSuwDayNightEnabled")) {
return mFakeProviderDayNightEnabledResultBundle;
}
return null;
}
public FakePartnerContentProvider injectFakeDayNightEnabledResult(boolean dayNightEnabled) {
mFakeProviderDayNightEnabledResultBundle.putBoolean(
"isSuwDayNightEnabled", dayNightEnabled);
return this;
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2016 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;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.preference.PreferenceViewHolder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class SummaryPreferenceTest {
private PreferenceViewHolder mHolder;
private SummaryPreference mPreference;
@Before
public void setUp() {
final Context context = RuntimeEnvironment.application;
mPreference = new SummaryPreference(context, null);
LayoutInflater inflater = LayoutInflater.from(context);
final View view =
inflater.inflate(mPreference.getLayoutResource(), new LinearLayout(context), false);
mHolder = PreferenceViewHolder.createInstanceForTests(view);
}
@Test
public void disableChart_shouldNotRender() {
mPreference.setChartEnabled(false);
mPreference.onBindViewHolder(mHolder);
final TextView textView1 = (TextView) mHolder.findViewById(android.R.id.text1);
assertThat(textView1.getText()).isEqualTo("");
final TextView textView2 = (TextView) mHolder.findViewById(android.R.id.text2);
assertThat(textView2.getText()).isEqualTo("");
}
@Test
public void enableChart_shouldRender() {
final String testLabel1 = "label1";
final String testLabel2 = "label2";
mPreference.setChartEnabled(true);
mPreference.setLabels(testLabel1, testLabel2);
mPreference.onBindViewHolder(mHolder);
final TextView textView1 = (TextView) mHolder.findViewById(android.R.id.text1);
assertThat(textView1.getText()).isEqualTo(testLabel1);
final TextView textView2 = (TextView) mHolder.findViewById(android.R.id.text2);
assertThat(textView2.getText()).isEqualTo(testLabel2);
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2017 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;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
/**
* Convenience methods and constants for testing.
*/
public class TestUtils {
public static final long KILOBYTE = 1024L; // TODO: Change to 1000 in O Robolectric.
public static final long MEGABYTE = KILOBYTE * KILOBYTE;
public static final long GIGABYTE = KILOBYTE * MEGABYTE;
public static void setScheduledLevel(Context context, int scheduledLevel) {
Settings.Global.putInt(context.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, scheduledLevel);
}
public static int getScheduledLevel(Context context) {
return Settings.Global.getInt(context.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, /*defaultValue*/ 0);
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2021 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;
import static com.google.common.truth.Truth.assertThat;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
@RunWith(RobolectricTestRunner.class)
public class TestingSettingsBroadcastReceiverTest {
private Context mContext;
private Application mApplication;
private TestingSettingsBroadcastReceiver mReceiver;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mApplication = RuntimeEnvironment.application;
mReceiver = new TestingSettingsBroadcastReceiver();
}
@Test
public void onReceive_nullIntent_shouldNotCrash() {
final Intent intent = new Intent();
mReceiver.onReceive(mContext, null);
mReceiver.onReceive(mContext, intent);
final Intent next = Shadows.shadowOf(mApplication).getNextStartedActivity();
assertThat(next).isNull();
}
@Test
public void onReceive_wrongIntent_shouldNotStartActivity() {
final Intent intent = new Intent();
intent.setAction("");
mReceiver.onReceive(mContext, intent);
final Intent next = Shadows.shadowOf(mApplication).getNextStartedActivity();
assertThat(next).isNull();
}
@Test
public void onReceive_correctIntent_shouldStartActivity() {
final Intent intent = new Intent();
intent.setAction(TelephonyManager.ACTION_SECRET_CODE);
mReceiver.onReceive(mContext, intent);
final Intent next = Shadows.shadowOf(mApplication).getNextStartedActivity();
assertThat(next).isNotNull();
final String dest = next.getComponent().getClassName();
assertThat(dest).isEqualTo(Settings.TestingSettingsActivity.class.getName());
}
}

View File

@@ -0,0 +1,441 @@
/*
* 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;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActionBar;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyResourcesManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.VectorDrawable;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.util.IconDrawableFactory;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
import androidx.core.graphics.drawable.IconCompat;
import androidx.fragment.app.FragmentActivity;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
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 org.robolectric.shadows.ShadowBinder;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowLockPatternUtils.class)
public class UtilsTest {
private static final String PACKAGE_NAME = "com.android.app";
private static final int USER_ID = 1;
@Mock
private WifiManager wifiManager;
@Mock
private Network network;
@Mock
private ConnectivityManager connectivityManager;
@Mock
private DevicePolicyManager mDevicePolicyManager;
@Mock
private DevicePolicyResourcesManager mDevicePolicyResourcesManager;
@Mock
private UserManager mMockUserManager;
@Mock
private PackageManager mPackageManager;
@Mock
private IconDrawableFactory mIconDrawableFactory;
@Mock
private ApplicationInfo mApplicationInfo;
private Context mContext;
private UserManager mUserManager;
private static final int FLAG_SYSTEM = 0x00000000;
private static final int FLAG_MAIN = 0x00004000;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
when(mContext.getSystemService(WifiManager.class)).thenReturn(wifiManager);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.thenReturn(connectivityManager);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
}
@After
public void tearDown() {
ShadowLockPatternUtils.reset();
}
@Test
public void getWifiIpAddresses_succeeds() throws Exception {
when(wifiManager.getCurrentNetwork()).thenReturn(network);
LinkAddress address = new LinkAddress(InetAddress.getByName("127.0.0.1"), 0);
LinkProperties lp = new LinkProperties();
lp.addLinkAddress(address);
when(connectivityManager.getLinkProperties(network)).thenReturn(lp);
assertThat(Utils.getWifiIpAddresses(mContext)).isEqualTo("127.0.0.1");
}
@Test
public void getWifiIpAddresses_nullLinkProperties() {
when(wifiManager.getCurrentNetwork()).thenReturn(network);
// Explicitly set the return value to null for readability sake.
when(connectivityManager.getLinkProperties(network)).thenReturn(null);
assertThat(Utils.getWifiIpAddresses(mContext)).isNull();
}
@Test
public void getWifiIpAddresses_nullNetwork() {
// Explicitly set the return value to null for readability sake.
when(wifiManager.getCurrentNetwork()).thenReturn(null);
assertThat(Utils.getWifiIpAddresses(mContext)).isNull();
}
@Test
public void initializeVolumeDoesntBreakOnNullVolume() {
VolumeInfo info = new VolumeInfo("id", 0, new DiskInfo("id", 0), "");
StorageManager storageManager = mock(StorageManager.class, RETURNS_DEEP_STUBS);
when(storageManager.findVolumeById(anyString())).thenReturn(info);
Utils.maybeInitializeVolume(storageManager, new Bundle());
}
@Test
public void isProfileOrDeviceOwner_deviceOwnerApp_returnTrue() {
when(mDevicePolicyManager.isDeviceOwnerAppOnAnyUser(PACKAGE_NAME)).thenReturn(true);
assertThat(
Utils.isProfileOrDeviceOwner(mMockUserManager, mDevicePolicyManager, PACKAGE_NAME))
.isTrue();
}
@Test
public void isProfileOrDeviceOwner_profileOwnerApp_returnTrue() {
final List<UserInfo> userInfos = new ArrayList<>();
userInfos.add(new UserInfo());
when(mMockUserManager.getUsers()).thenReturn(userInfos);
when(mDevicePolicyManager.getProfileOwnerAsUser(userInfos.get(0).id))
.thenReturn(new ComponentName(PACKAGE_NAME, ""));
assertThat(
Utils.isProfileOrDeviceOwner(mMockUserManager, mDevicePolicyManager, PACKAGE_NAME))
.isTrue();
}
@Test
public void setEditTextCursorPosition_shouldGetExpectedEditTextLenght() {
final EditText editText = new EditText(mContext);
final CharSequence text = "test";
editText.setText(text, TextView.BufferType.EDITABLE);
final int length = editText.getText().length();
Utils.setEditTextCursorPosition(editText);
assertThat(editText.getSelectionEnd()).isEqualTo(length);
}
@Test
public void createIconWithDrawable_BitmapDrawable() {
final Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
final BitmapDrawable drawable = new BitmapDrawable(mContext.getResources(), bitmap);
final IconCompat icon = Utils.createIconWithDrawable(drawable);
assertThat(icon.getBitmap()).isNotNull();
}
@Test
public void createIconWithDrawable_ColorDrawable() {
final ColorDrawable drawable = new ColorDrawable(Color.BLACK);
final IconCompat icon = Utils.createIconWithDrawable(drawable);
assertThat(icon.getBitmap()).isNotNull();
}
@Test
public void createIconWithDrawable_VectorDrawable() {
final VectorDrawable drawable = VectorDrawable.create(mContext.getResources(),
R.drawable.ic_settings_accent);
final IconCompat icon = Utils.createIconWithDrawable(drawable);
assertThat(icon.getBitmap()).isNotNull();
}
@Test
public void getBadgedIcon_usePackageNameAndUserId()
throws PackageManager.NameNotFoundException {
doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfoAsUser(
PACKAGE_NAME, PackageManager.GET_META_DATA, USER_ID);
Utils.getBadgedIcon(mIconDrawableFactory, mPackageManager, PACKAGE_NAME, USER_ID);
// Verify that it uses the correct user id
verify(mPackageManager).getApplicationInfoAsUser(eq(PACKAGE_NAME), anyInt(), eq(USER_ID));
verify(mIconDrawableFactory).getBadgedIcon(mApplicationInfo, USER_ID);
}
@Test
public void isPackageEnabled_appEnabled_returnTrue()
throws PackageManager.NameNotFoundException{
mApplicationInfo.enabled = true;
when(mPackageManager.getApplicationInfo(PACKAGE_NAME, 0)).thenReturn(mApplicationInfo);
assertThat(Utils.isPackageEnabled(mContext, PACKAGE_NAME)).isTrue();
}
@Test
public void isPackageEnabled_appDisabled_returnTrue()
throws PackageManager.NameNotFoundException{
mApplicationInfo.enabled = false;
when(mPackageManager.getApplicationInfo(PACKAGE_NAME, 0)).thenReturn(mApplicationInfo);
assertThat(Utils.isPackageEnabled(mContext, PACKAGE_NAME)).isFalse();
}
@Test
public void isPackageEnabled_noApp_returnFalse() {
assertThat(Utils.isPackageEnabled(mContext, PACKAGE_NAME)).isFalse();
}
@Test
public void setActionBarShadowAnimation_nullParameters_shouldNotCrash() {
// no crash here
Utils.setActionBarShadowAnimation(null, null, null);
}
@Test
public void setActionBarShadowAnimation_shouldSetElevationToZero() {
final FragmentActivity activity = Robolectric.setupActivity(FragmentActivity.class);
final ActionBar actionBar = activity.getActionBar();
Utils.setActionBarShadowAnimation(activity, activity.getLifecycle(),
new ScrollView(mContext));
assertThat(actionBar.getElevation()).isEqualTo(0.f);
}
@Test
public void isSettingsIntelligence_IsSI_returnTrue() {
final String siPackageName = mContext.getString(
R.string.config_settingsintelligence_package_name);
ShadowBinder.setCallingUid(USER_ID);
when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{siPackageName});
assertThat(Utils.isSettingsIntelligence(mContext)).isTrue();
}
@Test
public void isSettingsIntelligence_IsNotSI_returnFalse() {
ShadowBinder.setCallingUid(USER_ID);
when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{PACKAGE_NAME});
assertThat(Utils.isSettingsIntelligence(mContext)).isFalse();
}
@Test
public void canCurrentUserDream_isMainUser_returnTrue() {
Context mockContext = mock(Context.class);
UserManager mockUserManager = mock(UserManager.class);
when(mockContext.getSystemService(UserManager.class)).thenReturn(mockUserManager);
// mock MainUser
UserHandle mainUser = new UserHandle(10);
when(mockUserManager.getMainUser()).thenReturn(mainUser);
when(mockUserManager.isUserForeground()).thenReturn(true);
when(mockContext.createContextAsUser(mainUser, 0)).thenReturn(mockContext);
assertThat(Utils.canCurrentUserDream(mockContext)).isTrue();
}
@Test
public void canCurrentUserDream_nullMainUser_returnFalse() {
Context mockContext = mock(Context.class);
UserManager mockUserManager = mock(UserManager.class);
when(mockContext.getSystemService(UserManager.class)).thenReturn(mockUserManager);
when(mockUserManager.getMainUser()).thenReturn(null);
assertThat(Utils.canCurrentUserDream(mockContext)).isFalse();
}
@Test
public void canCurrentUserDream_notMainUser_returnFalse() {
Context mockContext = mock(Context.class);
UserManager mockUserManager = mock(UserManager.class);
when(mockContext.getSystemService(UserManager.class)).thenReturn(mockUserManager);
when(mockUserManager.isUserForeground()).thenReturn(false);
assertThat(Utils.canCurrentUserDream(mockContext)).isFalse();
}
@Test
public void checkUserOwnsFrpCredential_userOwnsFrpCredential_returnUserId() {
ShadowLockPatternUtils.setUserOwnsFrpCredential(true);
assertThat(Utils.checkUserOwnsFrpCredential(mContext, 123)).isEqualTo(123);
}
@Test
public void checkUserOwnsFrpCredential_userNotOwnsFrpCredential_returnUserId() {
ShadowLockPatternUtils.setUserOwnsFrpCredential(false);
assertThrows(
SecurityException.class,
() -> Utils.checkUserOwnsFrpCredential(mContext, 123));
}
@Test
public void getConfirmCredentialStringForUser_Pin_shouldReturnCorrectString() {
setUpForConfirmCredentialString(false /* isEffectiveUserManagedProfile */);
when(mContext.getString(R.string.lockpassword_confirm_your_pin_generic))
.thenReturn("PIN");
String confirmCredentialString = Utils.getConfirmCredentialStringForUser(mContext,
USER_ID, LockPatternUtils.CREDENTIAL_TYPE_PIN);
assertThat(confirmCredentialString).isEqualTo("PIN");
}
@Test
public void getConfirmCredentialStringForUser_Pattern_shouldReturnCorrectString() {
setUpForConfirmCredentialString(false /* isEffectiveUserManagedProfile */);
when(mContext.getString(R.string.lockpassword_confirm_your_pattern_generic))
.thenReturn("PATTERN");
String confirmCredentialString = Utils.getConfirmCredentialStringForUser(mContext,
USER_ID, LockPatternUtils.CREDENTIAL_TYPE_PATTERN);
assertThat(confirmCredentialString).isEqualTo("PATTERN");
}
@Test
public void getConfirmCredentialStringForUser_Password_shouldReturnCorrectString() {
setUpForConfirmCredentialString(false /* isEffectiveUserManagedProfile */);
when(mContext.getString(R.string.lockpassword_confirm_your_password_generic))
.thenReturn("PASSWORD");
String confirmCredentialString = Utils.getConfirmCredentialStringForUser(mContext,
USER_ID, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
assertThat(confirmCredentialString).isEqualTo("PASSWORD");
}
@Test
public void getConfirmCredentialStringForUser_workPin_shouldReturnNull() {
setUpForConfirmCredentialString(true /* isEffectiveUserManagedProfile */);
String confirmCredentialString = Utils.getConfirmCredentialStringForUser(mContext,
USER_ID, LockPatternUtils.CREDENTIAL_TYPE_PIN);
assertNull(confirmCredentialString);
}
@Test
public void getConfirmCredentialStringForUser_workPattern_shouldReturnNull() {
setUpForConfirmCredentialString(true /* isEffectiveUserManagedProfile */);
String confirmCredentialString = Utils.getConfirmCredentialStringForUser(mContext,
USER_ID, LockPatternUtils.CREDENTIAL_TYPE_PATTERN);
assertNull(confirmCredentialString);
}
@Test
public void getConfirmCredentialStringForUser_workPassword_shouldReturnNull() {
setUpForConfirmCredentialString(true /* isEffectiveUserManagedProfile */);
String confirmCredentialString = Utils.getConfirmCredentialStringForUser(mContext,
USER_ID, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
assertNull(confirmCredentialString);
}
@Test
public void getConfirmCredentialStringForUser_credentialTypeNone_shouldReturnNull() {
setUpForConfirmCredentialString(false /* isEffectiveUserManagedProfile */);
String confirmCredentialString = Utils.getConfirmCredentialStringForUser(mContext,
USER_ID, LockPatternUtils.CREDENTIAL_TYPE_NONE);
assertNull(confirmCredentialString);
}
private void setUpForConfirmCredentialString(boolean isEffectiveUserManagedProfile) {
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager);
when(mMockUserManager.getCredentialOwnerProfile(USER_ID)).thenReturn(USER_ID);
when(mMockUserManager.isManagedProfile(USER_ID)).thenReturn(isEffectiveUserManagedProfile);
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2021 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 android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.icu.text.MessageFormat;
import android.text.Html;
import androidx.preference.PreferenceScreen;
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.Mock;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AccessibilityButtonFooterPreferenceController}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityButtonFooterPreferenceControllerTest {
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
@Spy
private final Resources mResources = mContext.getResources();
@Mock
private PreferenceScreen mScreen;
private AccessibilityButtonFooterPreferenceController mController;
private AccessibilityFooterPreference mPreference;
@Before
public void setUp() {
mController = new AccessibilityButtonFooterPreferenceController(mContext, "test_key");
mPreference = new AccessibilityFooterPreference(mContext);
mPreference.setKey("test_key");
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
when(mContext.getResources()).thenReturn(mResources);
}
@Test
public void displayPreference_navigationGestureEnabled_setCorrectTitle() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
mController.displayPreference(mScreen);
assertThat(mPreference.getTitle().toString()).isEqualTo(
Html.fromHtml(
MessageFormat.format(mContext.getString(
R.string.accessibility_button_gesture_description), 1, 2, 3),
Html.FROM_HTML_MODE_COMPACT).toString());
}
@Test
public void displayPreference_navigationGestureDisabled_setCorrectTitle() {
when(mResources.getInteger(
com.android.internal.R.integer.config_navBarInteractionMode)).thenReturn(
NAV_BAR_MODE_2BUTTON);
mController.displayPreference(mScreen);
assertThat(mPreference.getTitle().toString()).isEqualTo(
Html.fromHtml(
MessageFormat.format(
mContext.getString(
R.string.accessibility_button_description), 1, 2, 3),
Html.FROM_HTML_MODE_COMPACT).toString());
}
}

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2021 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 android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.ShadowFragment;
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.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.List;
/** Tests for {@link AccessibilityButtonFragment}. */
@Config(shadows = ShadowFragment.class)
@RunWith(RobolectricTestRunner.class)
public class AccessibilityButtonFragmentTest {
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
@Spy
private Resources mResources = spy(mContext.getResources());
private AccessibilityButtonFragment mFragment;
@Before
public void setUp() {
mFragment = spy(new TestAccessibilityButtonFragment(mContext));
when(mContext.getResources()).thenReturn(mResources);
when(mFragment.getResources()).thenReturn(mResources);
when(mFragment.getActivity()).thenReturn(Robolectric.setupActivity(FragmentActivity.class));
}
@Test
public void getMetricsCategory_returnsCorrectCategory() {
assertThat(mFragment.getMetricsCategory()).isEqualTo(
SettingsEnums.ACCESSIBILITY_BUTTON_SETTINGS);
}
@Test
public void getLogTag_returnsCorrectTag() {
assertThat(mFragment.getLogTag()).isEqualTo("AccessibilityButtonFragment");
}
@Test
public void onCreate_navigationGestureEnabled_setCorrectTitle() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
mFragment.onAttach(mContext);
mFragment.onCreate(Bundle.EMPTY);
assertThat(mFragment.getActivity().getTitle().toString()).isEqualTo(
mContext.getString(R.string.accessibility_button_gesture_title));
}
@Test
public void onCreate_navigationGestureDisabled_setCorrectTitle() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_2BUTTON);
mFragment.onAttach(mContext);
mFragment.onCreate(Bundle.EMPTY);
assertThat(mFragment.getActivity().getTitle().toString()).isEqualTo(
mContext.getString(R.string.accessibility_button_title));
}
@Test
public void getNonIndexableKeys_existInXmlLayout() {
final List<String> niks = AccessibilityButtonFragment.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(mContext);
final List<String> keys =
XmlTestUtils.getKeysFromPreferenceXml(mContext,
R.xml.accessibility_button_settings);
assertThat(keys).containsAtLeastElementsIn(niks);
}
private static class TestAccessibilityButtonFragment extends AccessibilityButtonFragment {
private final Context mContext;
private final PreferenceManager mPreferenceManager;
TestAccessibilityButtonFragment(Context context) {
super();
mContext = context;
mPreferenceManager = new PreferenceManager(context);
mPreferenceManager.setPreferences(mPreferenceManager.createPreferenceScreen(context));
}
@Override
public int getPreferenceScreenResId() {
return R.xml.placeholder_prefs;
}
@Override
public PreferenceScreen getPreferenceScreen() {
return mPreferenceManager.getPreferenceScreen();
}
@Override
public PreferenceManager getPreferenceManager() {
return mPreferenceManager;
}
@Override
public Context getContext() {
return mContext;
}
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2021 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 android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
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.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.provider.Settings;
import androidx.preference.ListPreference;
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.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AccessibilityButtonGesturePreferenceController}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityButtonGesturePreferenceControllerTest {
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
@Spy
private final Resources mResources = mContext.getResources();
private final ContentResolver mContentResolver = mContext.getContentResolver();
private final ListPreference mListPreference = new ListPreference(mContext);
private AccessibilityButtonGesturePreferenceController mController;
@Before
public void setUp() {
mController = new AccessibilityButtonGesturePreferenceController(mContext,
"test_key");
when(mContext.getResources()).thenReturn(mResources);
}
@Test
public void getAvailabilityStatus_navigationGestureEnabled_returnAvailable() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_navigationGestureDisabled_returnConditionallyUnavailable() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_2BUTTON);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void updateState_a11yBtnModeGesture_navigationBarValue() {
Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
ACCESSIBILITY_BUTTON_MODE_GESTURE);
mController.updateState(mListPreference);
final String gestureValue = String.valueOf(ACCESSIBILITY_BUTTON_MODE_GESTURE);
assertThat(mListPreference.getValue()).isEqualTo(gestureValue);
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (C) 2021 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 android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
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.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.provider.Settings;
import androidx.preference.ListPreference;
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.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AccessibilityButtonLocationPreferenceController}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityButtonLocationPreferenceControllerTest {
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
@Spy
private final Resources mResources = mContext.getResources();
private final ContentResolver mContentResolver = mContext.getContentResolver();
private final ListPreference mListPreference = new ListPreference(mContext);
private AccessibilityButtonLocationPreferenceController mController;
@Before
public void setUp() {
mController = new AccessibilityButtonLocationPreferenceController(mContext,
"test_key");
when(mContext.getResources()).thenReturn(mResources);
}
@Test
public void getAvailabilityStatus_navigationGestureEnabled_returnConditionallyUnavailable() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_navigationGestureDisabled_returnAvailable() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_2BUTTON);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void updateState_a11yBtnModeNavigationBar_navigationBarValue() {
Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
mController.updateState(mListPreference);
final String navigationBarValue = String.valueOf(ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
assertThat(mListPreference.getValue()).isEqualTo(navigationBarValue);
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright (C) 2021 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 android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import androidx.preference.Preference;
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;
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 java.util.ArrayList;
import java.util.List;
/** Tests for {@link AccessibilityButtonPreferenceController}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityButtonPreferenceControllerTest {
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
@Spy
private final Resources mResources = mContext.getResources();
@Mock
private PreferenceScreen mScreen;
private Preference mPreference;
private AccessibilityButtonPreferenceController mController;
@Before
public void setUp() {
mController = new AccessibilityButtonPreferenceController(mContext, "test_key");
mPreference = new Preference(mContext);
mPreference.setKey("test_key");
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
when(mContext.getResources()).thenReturn(mResources);
}
@Test
public void displayPreference_navigationGestureEnabled_setCorrectTitle() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
mController.displayPreference(mScreen);
assertThat(mPreference.getTitle()).isEqualTo(
mContext.getText(R.string.accessibility_button_gesture_title));
}
@Test
public void displayPreference_navigationGestureDisabled_setCorrectTitle() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_2BUTTON);
mController.displayPreference(mScreen);
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));
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright (C) 2021 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 android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
import static com.android.settings.testutils.ImageTestUtils.drawableToBitmap;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settingslib.widget.IllustrationPreference;
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;
/** Tests for {@link AccessibilityButtonPreviewPreferenceController}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityButtonPreviewPreferenceControllerTest {
@Rule
public MockitoRule mocks = MockitoJUnit.rule();
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
@Mock
private ContentResolver mContentResolver;
private AccessibilityButtonPreviewPreferenceController mController;
@Before
public void setUp() {
when(mContext.getContentResolver()).thenReturn(mContentResolver);
mController = new AccessibilityButtonPreviewPreferenceController(mContext, "test_key");
mController.mIllustrationPreference = new IllustrationPreference(mContext);
}
@Test
public void onChange_a11yBtnModeNavigationBar_getNavigationBarDrawable() {
Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
mController.mContentObserver.onChange(false);
final Drawable navigationBarDrawable = mContext.getDrawable(
R.drawable.a11y_button_navigation);
assertThat(drawableToBitmap(mController.mIllustrationPreference.getImageDrawable()).sameAs(
drawableToBitmap(navigationBarDrawable))).isTrue();
}
@Test
public void onChange_updatePreviewPreferenceWithConfig_expectedPreviewDrawable() {
Settings.Secure.putInt(mContentResolver,
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
Settings.Secure.putInt(mContentResolver,
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE, /* small size */ 0);
Settings.Secure.putFloat(mContentResolver,
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, 0.1f);
mController.mContentObserver.onChange(false);
final Drawable smallFloatingMenuWithTenOpacityDrawable =
AccessibilityLayerDrawable.createLayerDrawable(mContext,
R.drawable.a11y_button_preview_small_floating_menu, 10);
assertThat(
mController.mIllustrationPreference.getImageDrawable().getConstantState())
.isEqualTo(smallFloatingMenuWithTenOpacityDrawable.getConstantState());
}
@Test
public void onResume_registerSpecificContentObserver() {
mController.onResume();
verify(mContentResolver).registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_MODE), false,
mController.mContentObserver);
verify(mContentResolver).registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE), false,
mController.mContentObserver);
verify(mContentResolver).registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY),
false,
mController.mContentObserver);
}
@Test
public void onPause_unregisterContentObserver() {
mController.onPause();
verify(mContentResolver).unregisterContentObserver(mController.mContentObserver);
}
}

View File

@@ -0,0 +1,82 @@
/*
* 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.accessibility;
import static com.google.common.truth.Truth.assertThat;
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.robolectric.RobolectricTestRunner;
import java.util.List;
/** Tests for {@link AccessibilityControlTimeoutPreferenceFragment}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityControlTimeoutPreferenceFragmentTest {
private final Context mContext = ApplicationProvider.getApplicationContext();
private AccessibilityControlTimeoutPreferenceFragment mFragment;
@Before
public void setUp() {
mFragment = new AccessibilityControlTimeoutPreferenceFragment();
}
@Test
public void getMetricsCategory_returnsCorrectCategory() {
assertThat(mFragment.getMetricsCategory()).isEqualTo(
SettingsEnums.ACCESSIBILITY_TIMEOUT);
}
@Test
public void getPreferenceScreenResId_returnsCorrectXml() {
assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(
R.xml.accessibility_control_timeout_settings);
}
@Test
public void getHelpResource_returnsCorrectHelpResource() {
assertThat(mFragment.getHelpResource()).isEqualTo(R.string.help_url_timeout);
}
@Test
public void getLogTag_returnsCorrectTag() {
assertThat(mFragment.getLogTag()).isEqualTo(
"AccessibilityControlTimeoutPreferenceFragment");
}
@Test
public void getNonIndexableKeys_existInXmlLayout() {
final List<String> niks =
AccessibilityControlTimeoutPreferenceFragment.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(mContext);
final List<String> keys =
XmlTestUtils.getKeysFromPreferenceXml(mContext,
R.xml.accessibility_control_timeout_settings);
assertThat(keys).containsAtLeastElementsIn(niks);
}
}

View File

@@ -0,0 +1,227 @@
/*
* Copyright (C) 2019 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.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_BUTTON_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
import static com.google.common.truth.Truth.assertThat;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Activity;
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.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.view.accessibility.AccessibilityManager;
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;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowAccessibilityManager;
import org.robolectric.shadows.androidx.fragment.FragmentController;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/** Tests for {@link AccessibilityDetailsSettingsFragment}. */
@Config(shadows = {
ShadowDevicePolicyManager.class,
ShadowRestrictedLockUtilsInternal.class
})
@RunWith(RobolectricTestRunner.class)
public class AccessibilityDetailsSettingsFragmentTest {
private static final String PACKAGE_NAME = "com.foo.bar";
private static final String CLASS_NAME = PACKAGE_NAME + ".fake_a11y_service";
private static final String COMPONENT_NAME = PACKAGE_NAME + "/" + CLASS_NAME;
private Context mContext;
private FragmentController<AccessibilityDetailsSettingsFragment> mFragmentController;
@Before
public void setUp() {
mContext = ApplicationProvider.getApplicationContext();
ShadowAccessibilityManager shadowAccessibilityManager = Shadow.extract(
AccessibilityManager.getInstance(mContext));
shadowAccessibilityManager.setInstalledAccessibilityServiceList(getMockServiceList());
}
@Test
public void onCreate_afterSuccessfullyLaunch_shouldBeFinished() {
final Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME);
AccessibilityDetailsSettingsFragment fragment = startFragment(intent);
assertThat(fragment.getActivity().isFinishing()).isTrue();
}
@Test
public void onCreate_hasValidExtraComponentName_launchExpectedFragment() {
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME);
AccessibilityDetailsSettingsFragment fragment = startFragment(intent);
assertStartActivityWithExpectedFragment(fragment.getActivity(),
ToggleAccessibilityServicePreferenceFragment.class.getName());
}
@Test
public void onCreate_hasInvalidExtraComponentName_launchAccessibilitySettings() {
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_COMPONENT_NAME, PACKAGE_NAME + "/.service");
AccessibilityDetailsSettingsFragment fragment = startFragment(intent);
assertStartActivityWithExpectedFragment(fragment.getActivity(),
AccessibilitySettings.class.getName());
}
@Test
public void onCreate_hasNoExtraComponentName_launchAccessibilitySettings() {
AccessibilityDetailsSettingsFragment fragment = startFragment(/* intent= */ null);
assertStartActivityWithExpectedFragment(fragment.getActivity(),
AccessibilitySettings.class.getName());
}
@Test
public void onCreate_extraComponentNameIsDisallowed_launchAccessibilitySettings() {
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME);
DevicePolicyManager dpm = mContext.getSystemService(
DevicePolicyManager.class);
((ShadowDevicePolicyManager) Shadows.shadowOf(dpm)).setPermittedAccessibilityServices(
ImmutableList.of());
AccessibilityDetailsSettingsFragment fragment = startFragment(intent);
assertStartActivityWithExpectedFragment(fragment.getActivity(),
AccessibilitySettings.class.getName());
}
@Test
public void onCreate_magnificationComponentName_launchMagnificationFragment() {
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_COMPONENT_NAME,
MAGNIFICATION_COMPONENT_NAME.flattenToString());
AccessibilityDetailsSettingsFragment fragment = startFragment(intent);
assertStartActivityWithExpectedFragment(fragment.getActivity(),
ToggleScreenMagnificationPreferenceFragment.class.getName());
}
@Test
public void onCreate_accessibilityButton_launchAccessibilityButtonFragment() {
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_COMPONENT_NAME,
ACCESSIBILITY_BUTTON_COMPONENT_NAME.flattenToString());
AccessibilityDetailsSettingsFragment fragment = startFragment(intent);
assertStartActivityWithExpectedFragment(fragment.getActivity(),
AccessibilityButtonFragment.class.getName());
}
@Test
public void onCreate_hearingAidsComponentName_launchAccessibilityHearingAidsFragment() {
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_COMPONENT_NAME,
ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.flattenToString());
AccessibilityDetailsSettingsFragment fragment = startFragment(intent);
assertStartActivityWithExpectedFragment(fragment.getActivity(),
AccessibilityHearingAidsFragment.class.getName());
}
@Test
public void getMetricsCategory_returnsCorrectCategory() {
AccessibilityDetailsSettingsFragment fragment = startFragment(/* intent= */ null);
assertThat(fragment.getMetricsCategory()).isEqualTo(
SettingsEnums.ACCESSIBILITY_DETAILS_SETTINGS);
}
private AccessibilityDetailsSettingsFragment startFragment(Intent intent) {
mFragmentController = FragmentController.of(
new AccessibilityDetailsSettingsFragment(), intent)
.create()
.visible();
return mFragmentController.get();
}
private AccessibilityServiceInfo getMockAccessibilityServiceInfo() {
final ApplicationInfo applicationInfo = new ApplicationInfo();
final ServiceInfo serviceInfo = new ServiceInfo();
applicationInfo.packageName = PACKAGE_NAME;
serviceInfo.packageName = PACKAGE_NAME;
serviceInfo.name = CLASS_NAME;
serviceInfo.applicationInfo = applicationInfo;
final ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.serviceInfo = serviceInfo;
try {
final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo,
mContext);
ComponentName componentName = ComponentName.unflattenFromString(COMPONENT_NAME);
info.setComponentName(componentName);
return info;
} catch (XmlPullParserException | IOException e) {
// Do nothing
}
return null;
}
private List<AccessibilityServiceInfo> getMockServiceList() {
final List<AccessibilityServiceInfo> infoList = new ArrayList<>();
infoList.add(getMockAccessibilityServiceInfo());
return infoList;
}
private void assertStartActivityWithExpectedFragment(Activity activity, String fragmentName) {
Intent intent = Shadows.shadowOf(activity).getNextStartedActivity();
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo(
fragmentName);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2021 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.app.Dialog;
import android.content.Context;
import androidx.appcompat.app.AlertDialog;
import androidx.test.core.app.ApplicationProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AccessibilityDialogUtils} */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityDialogUtilsTest {
private final Context mContext = ApplicationProvider.getApplicationContext();
@Before
public void setUp() {
mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
}
@Test
public void updateShortcutInDialog_correctDialogType_success() {
final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
mContext, AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC, "Title",
null);
assertThat(
AccessibilityDialogUtils.updateShortcutInDialog(mContext, dialog)).isTrue();
}
@Test
public void updateShortcutInDialog_useNotSupportedDialog_fail() {
final AlertDialog dialog = new AlertDialog.Builder(mContext).setTitle("Title").show();
assertThat(AccessibilityDialogUtils.updateShortcutInDialog(mContext,
dialog)).isFalse();
}
@Test
public void showDialog_createCustomDialog_isShowing() {
final Dialog dialog = AccessibilityDialogUtils.createCustomDialog(mContext,
"Title", /* customView= */ null, "positiveButton", /* positiveListener= */ null,
"negativeButton", /* negativeListener= */ null);
dialog.show();
assertThat(dialog.isShowing()).isTrue();
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (C) 2021 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.when;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import androidx.preference.PreferenceScreen;
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.Mock;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
/**
* Tests for {@link AccessibilityFooterPreferenceController}.
*/
@RunWith(RobolectricTestRunner.class)
public class AccessibilityFooterPreferenceControllerTest {
private static final String TEST_KEY = "test_pref_key";
private static final String TEST_TITLE = "test_title";
private static final String TEST_INTRODUCTION_TITLE = "test_introduction_title";
private static final String TEST_CONTENT_DESCRIPTION = "test_content_description";
private static final int TEST_HELP_ID = 12345;
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
@Mock
private PreferenceScreen mScreen;
private AccessibilityFooterPreferenceController mController;
private AccessibilityFooterPreference mPreference;
private PreferenceViewHolder mPreferenceViewHolder;
@Before
public void setUp() {
mController = new AccessibilityFooterPreferenceController(mContext, TEST_KEY);
mPreference = new AccessibilityFooterPreference(mContext);
mPreference.setKey(TEST_KEY);
mPreference.setTitle(TEST_TITLE);
final LayoutInflater inflater = LayoutInflater.from(mContext);
final View view = inflater.inflate(
com.android.settingslib.widget.preference.footer.R.layout.preference_footer, null);
mPreferenceViewHolder = PreferenceViewHolder.createInstanceForTests(view);
mPreference.onBindViewHolder(mPreferenceViewHolder);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
}
@Test
public void setIntroductionTitle_setCorrectIntroductionTitle() {
mController.setIntroductionTitle(TEST_INTRODUCTION_TITLE);
assertThat(mController.getIntroductionTitle()).isEqualTo(TEST_INTRODUCTION_TITLE);
}
@Test
public void onBindViewHolder_setIntroductionTitle_setCorrectIntroductionTitle() {
mController.setIntroductionTitle(TEST_INTRODUCTION_TITLE);
mController.displayPreference(mScreen);
mPreference.onBindViewHolder(mPreferenceViewHolder);
final TextView summaryView = (TextView) mPreferenceViewHolder
.findViewById(android.R.id.title);
assertThat(summaryView.getContentDescription().toString())
.contains(TEST_INTRODUCTION_TITLE);
}
@Test
public void setupHelpLink_setCorrectHelpLinkAndLearnMoreText() {
mController.setupHelpLink(TEST_HELP_ID, TEST_CONTENT_DESCRIPTION);
assertThat(mController.getHelpResource()).isEqualTo(TEST_HELP_ID);
assertThat(mController.getLearnMoreText())
.isEqualTo(TEST_CONTENT_DESCRIPTION);
}
@Test
public void onBindViewHolder_setHelpResource_emptyString_notVisible() {
mController.setupHelpLink(R.string.help_url_timeout, TEST_CONTENT_DESCRIPTION);
mController.displayPreference(mScreen);
mPreference.onBindViewHolder(mPreferenceViewHolder);
final TextView learnMoreView = (TextView) mPreferenceViewHolder
.findViewById(com.android.settingslib.widget.preference.footer.R.id.settingslib_learn_more);
assertThat(learnMoreView.getContentDescription()).isNull();
assertThat(learnMoreView.getVisibility()).isEqualTo(View.GONE);
assertThat(mPreference.isLinkEnabled()).isFalse();
}
@Test
public void onBindViewHolder_setHelpResource_expectSummaryViewIsNonFocusable() {
mController.setupHelpLink(R.string.help_url_timeout, TEST_CONTENT_DESCRIPTION);
mController.displayPreference(mScreen);
mPreference.onBindViewHolder(mPreferenceViewHolder);
final TextView summaryView = (TextView) mPreferenceViewHolder
.findViewById(android.R.id.title);
assertThat(summaryView.isFocusable()).isFalse();
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2019 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.text.method.MovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import androidx.preference.PreferenceViewHolder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
/** Tests for {@link AccessibilityFooterPreference} */
@RunWith(RobolectricTestRunner.class)
public final class AccessibilityFooterPreferenceTest {
private AccessibilityFooterPreference mAccessibilityFooterPreference;
private PreferenceViewHolder mPreferenceViewHolder;
@Before
public void setUp() {
final Context context = RuntimeEnvironment.application;
mAccessibilityFooterPreference = new AccessibilityFooterPreference(context);
final LayoutInflater inflater = LayoutInflater.from(context);
final View view =
inflater.inflate(com.android.settingslib.widget.preference.footer.R.layout.preference_footer, null);
mPreferenceViewHolder = PreferenceViewHolder.createInstanceForTests(view);
}
@Test
public void onBindViewHolder_LinkDisabledByDefault_notReturnLinkMovement() {
mAccessibilityFooterPreference.onBindViewHolder(mPreferenceViewHolder);
final TextView summaryView = (TextView) mPreferenceViewHolder.findViewById(
android.R.id.title);
assertThat(summaryView.getMovementMethod()).isNull();
}
@Test
public void onBindViewHolder_setLinkEnabled_returnLinkMovement() {
mAccessibilityFooterPreference.setLinkEnabled(true);
mAccessibilityFooterPreference.onBindViewHolder(mPreferenceViewHolder);
final TextView summaryView = (TextView) mPreferenceViewHolder.findViewById(
android.R.id.title);
assertThat(summaryView.getMovementMethod()).isInstanceOf(MovementMethod.class);
}
@Test
public void onBindViewHolder_setLinkEnabled_expectSummaryViewIsNonFocusable() {
mAccessibilityFooterPreference.setLinkEnabled(true);
mAccessibilityFooterPreference.onBindViewHolder(mPreferenceViewHolder);
final TextView summaryView = (TextView) mPreferenceViewHolder.findViewById(
android.R.id.title);
assertThat(summaryView.isFocusable()).isFalse();
}
}

View File

@@ -0,0 +1,237 @@
/*
* Copyright (C) 2020 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.AccessibilityGestureNavigationTutorial.createAccessibilityTutorialDialog;
import static com.android.settings.accessibility.AccessibilityGestureNavigationTutorial.createAccessibilityTutorialDialogForSetupWizard;
import static com.android.settings.accessibility.AccessibilityGestureNavigationTutorial.createShortcutTutorialPages;
import static com.android.settings.accessibility.AccessibilityGestureNavigationTutorial.showGestureNavigationTutorialDialog;
import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.robolectric.Shadows.shadowOf;
import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
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.test.core.app.ApplicationProvider;
import com.android.server.accessibility.Flags;
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
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.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.LooperMode;
/** Tests for {@link AccessibilityGestureNavigationTutorial}. */
@RunWith(RobolectricTestRunner.class)
@LooperMode(LooperMode.Mode.LEGACY)
public final class AccessibilityGestureNavigationTutorialTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@Mock
private DialogInterface.OnClickListener mOnClickListener;
@Mock
private DialogInterface.OnDismissListener mOnDismissListener;
private final Context mContext = ApplicationProvider.getApplicationContext();
private int mShortcutTypes;
@Before
public void setUp() {
mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
mShortcutTypes = /* initial */ 0;
}
@Test(expected = IllegalArgumentException.class)
public void createTutorialPages_shortcutListIsEmpty_throwsException() {
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
}
@Test
public void createTutorialPages_turnOnTripleTapShortcut_hasOnePage() {
mShortcutTypes |= UserShortcutType.TRIPLETAP;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
assertThat(createShortcutTutorialPages(mContext,
mShortcutTypes)).hasSize(/* expectedSize= */ 1);
assertThat(alertDialog).isNotNull();
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
public void createTutorialPages_turnOnTwoFingerTripleTapShortcut_hasOnePage() {
mShortcutTypes |= UserShortcutType.TWOFINGERTRIPLETAP;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
assertThat(createShortcutTutorialPages(mContext,
mShortcutTypes)).hasSize(/* expectedSize= */ 1);
assertThat(alertDialog).isNotNull();
}
@Test
public void createTutorialPages_turnOnSoftwareShortcut_hasOnePage() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
assertThat(createShortcutTutorialPages(mContext,
mShortcutTypes)).hasSize(/* expectedSize= */ 1);
assertThat(alertDialog).isNotNull();
}
@Test
public void createTutorialPages_turnOnSoftwareAndHardwareShortcuts_hasTwoPages() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
mShortcutTypes |= UserShortcutType.HARDWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
assertThat(createShortcutTutorialPages(mContext,
mShortcutTypes)).hasSize(/* expectedSize= */ 2);
assertThat(alertDialog).isNotNull();
}
@Test
public void createTutorialPages_turnOnSoftwareShortcut_linkButtonVisible() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
alertDialog.show();
assertThat(alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility())
.isEqualTo(View.VISIBLE);
}
@Test
public void createTutorialPages_turnOnSoftwareAndHardwareShortcut_linkButtonVisible() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
mShortcutTypes |= UserShortcutType.HARDWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
alertDialog.show();
assertThat(alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility())
.isEqualTo(View.VISIBLE);
}
@Test
public void createTutorialPages_turnOnHardwareShortcut_linkButtonGone() {
mShortcutTypes |= UserShortcutType.HARDWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
alertDialog.show();
assertThat(alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void createTutorialPages_turnOnSoftwareShortcut_showFromSuW_linkButtonGone() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialogForSetupWizard(mContext, mShortcutTypes);
alertDialog.show();
assertThat(alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void performClickOnPositiveButton_turnOnSoftwareShortcut_dismiss() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
alertDialog.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
assertThat(alertDialog.isShowing()).isFalse();
}
@Test
public void performClickOnPositiveButton_turnOnSoftwareShortcut_callOnClickListener() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes, mOnClickListener);
alertDialog.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
verify(mOnClickListener).onClick(alertDialog, DialogInterface.BUTTON_POSITIVE);
}
@Test
public void performClickOnNegativeButton_turnOnSoftwareShortcut_directToSettingsPage() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
Activity activity = Robolectric.buildActivity(Activity.class).create().get();
final AlertDialog alertDialog = createAccessibilityTutorialDialog(activity, mShortcutTypes);
alertDialog.show();
alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).performClick();
final Intent intent = shadowOf(activity).peekNextStartedActivity();
assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
.isEqualTo(AccessibilityButtonFragment.class.getName());
assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, -1))
.isEqualTo(SettingsEnums.SWITCH_SHORTCUT_DIALOG_ACCESSIBILITY_BUTTON_SETTINGS);
}
@Test
public void performClickOnPositiveButton_turnOnGestureShortcut_callOnDismissListener() {
final AlertDialog alertDialog =
showGestureNavigationTutorialDialog(mContext, mOnDismissListener);
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
assertThat(alertDialog.isShowing()).isFalse();
verify(mOnDismissListener).onDismiss(alertDialog);
}
}

View File

@@ -0,0 +1,320 @@
/*
* Copyright 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.accessibility;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
import android.app.Application;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHapClient;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.BluetoothEventManager;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.HapClientProfile;
import com.android.settingslib.bluetooth.HearingAidInfo;
import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import org.junit.After;
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;
import org.robolectric.shadows.ShadowApplication;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** Tests for {@link AccessibilityHearingAidPreferenceController}. */
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class})
public class AccessibilityHearingAidPreferenceControllerTest {
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
private static final String TEST_DEVICE_ADDRESS_2 = "00:A2:A2:A2:A2:A2";
private static final String TEST_DEVICE_NAME = "TEST_HEARING_AID_BT_DEVICE_NAME";
private static final String HEARING_AID_PREFERENCE = "hearing_aid_preference";
private BluetoothAdapter mBluetoothAdapter;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
private BluetoothDevice mBluetoothDevice;
private final Context mContext = ApplicationProvider.getApplicationContext();
private Preference mHearingAidPreference;
private AccessibilityHearingAidPreferenceController mPreferenceController;
private ShadowApplication mShadowApplication;
@Mock
private CachedBluetoothDevice mCachedBluetoothDevice;
@Mock
private CachedBluetoothDevice mCachedSubBluetoothDevice;
@Mock
private CachedBluetoothDeviceManager mCachedDeviceManager;
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
@Mock
private BluetoothEventManager mEventManager;
@Mock
private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
@Mock
private HearingAidProfile mHearingAidProfile;
@Mock
private HapClientProfile mHapClientProfile;
@Before
public void setUp() {
mShadowApplication = shadowOf((Application) ApplicationProvider.getApplicationContext());
setupEnvironment();
mHearingAidPreference = new Preference(mContext);
mHearingAidPreference.setKey(HEARING_AID_PREFERENCE);
mPreferenceController = new AccessibilityHearingAidPreferenceController(mContext,
HEARING_AID_PREFERENCE);
mPreferenceController.setPreference(mHearingAidPreference);
mHearingAidPreference.setSummary("");
}
@After
public void tearDown() {
ShadowBluetoothUtils.reset();
}
@Test
public void getSummary_connectedAshaHearingAidRightSide_connectedRightSideSummary() {
when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
HearingAidInfo.DeviceSide.SIDE_RIGHT);
when(mHearingAidProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList());
mPreferenceController.onStart();
Intent intent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHearingAid.STATE_CONNECTED);
sendIntent(intent);
assertThat(mHearingAidPreference.getSummary().toString().contentEquals(
"TEST_HEARING_AID_BT_DEVICE_NAME, right only")).isTrue();
}
@Test
public void getSummary_connectedAshaHearingAidBothSide_connectedBothSideSummary() {
when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
HearingAidInfo.DeviceSide.SIDE_LEFT);
when(mCachedSubBluetoothDevice.isConnected()).thenReturn(true);
when(mCachedBluetoothDevice.getSubDevice()).thenReturn(mCachedSubBluetoothDevice);
when(mHearingAidProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList());
mPreferenceController.onStart();
Intent intent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHearingAid.STATE_CONNECTED);
sendIntent(intent);
assertThat(mHearingAidPreference.getSummary().toString().contentEquals(
"TEST_HEARING_AID_BT_DEVICE_NAME, left and right")).isTrue();
}
@Test
public void getSummary_connectedLeAudioHearingAidLeftSide_connectedLeftSideSummary() {
when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
HearingAidInfo.DeviceSide.SIDE_LEFT);
when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(new HashSet<>());
when(mHapClientProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList());
mPreferenceController.onStart();
Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHapClient.STATE_CONNECTED);
sendIntent(intent);
assertThat(mHearingAidPreference.getSummary().toString().contentEquals(
"TEST_HEARING_AID_BT_DEVICE_NAME, left only")).isTrue();
}
@Test
public void getSummary_connectedLeAudioHearingAidRightSide_connectedRightSideSummary() {
when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
HearingAidInfo.DeviceSide.SIDE_RIGHT);
when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(new HashSet<>());
when(mHapClientProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList());
mPreferenceController.onStart();
Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHapClient.STATE_CONNECTED);
sendIntent(intent);
assertThat(mHearingAidPreference.getSummary().toString().contentEquals(
"TEST_HEARING_AID_BT_DEVICE_NAME, right only")).isTrue();
}
@Test
public void getSummary_connectedLeAudioHearingAidLeftAndRightSide_connectedSummary() {
when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
HearingAidInfo.DeviceSide.SIDE_LEFT_AND_RIGHT);
when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(new HashSet<>());
when(mHapClientProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList());
mPreferenceController.onStart();
Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHapClient.STATE_CONNECTED);
sendIntent(intent);
assertThat(mHearingAidPreference.getSummary().toString().contentEquals(
"TEST_HEARING_AID_BT_DEVICE_NAME, left and right")).isTrue();
}
@Test
public void getSummary_connectedLeAudioHearingAidBothSide_connectedBothSideSummary() {
when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(generateMemberDevices());
when(mCachedSubBluetoothDevice.isConnected()).thenReturn(true);
when(mHapClientProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList());
mPreferenceController.onStart();
Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHapClient.STATE_CONNECTED);
sendIntent(intent);
assertThat(mHearingAidPreference.getSummary().toString()).isEqualTo(
"TEST_HEARING_AID_BT_DEVICE_NAME, left and right");
}
@Test
public void getSummary_connectedMultipleHearingAids_connectedMultipleDevicesSummary() {
when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
HearingAidInfo.DeviceSide.SIDE_LEFT);
when(mHearingAidProfile.getConnectedDevices()).thenReturn(
generateMultipleHearingAidDeviceList());
mPreferenceController.onStart();
Intent intent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHearingAid.STATE_CONNECTED);
sendIntent(intent);
assertThat(mHearingAidPreference.getSummary().toString().contentEquals(
"TEST_HEARING_AID_BT_DEVICE_NAME +1 more")).isTrue();
}
@Test
public void getSummary_bluetoothOff_disconnectedSummary() {
mPreferenceController.onStart();
Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
sendIntent(intent);
assertThat(mHearingAidPreference.getSummary()).isEqualTo(
mContext.getText(R.string.accessibility_hearingaid_not_connected_summary));
}
@Test
public void onServiceConnected_onHearingAidProfileConnected_updateSummary() {
when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
HearingAidInfo.DeviceSide.SIDE_LEFT);
when(mHearingAidProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList());
mPreferenceController.onStart();
mPreferenceController.onServiceConnected();
assertThat(mHearingAidPreference.getSummary().toString()).isEqualTo(
"TEST_HEARING_AID_BT_DEVICE_NAME, left only");
}
@Test
public void onServiceConnected_onHapClientProfileConnected_updateSummary() {
when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
HearingAidInfo.DeviceSide.SIDE_RIGHT);
when(mHapClientProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList());
mPreferenceController.onStart();
mPreferenceController.onServiceConnected();
assertThat(mHearingAidPreference.getSummary().toString()).isEqualTo(
"TEST_HEARING_AID_BT_DEVICE_NAME, right only");
}
private void setupEnvironment() {
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mShadowBluetoothAdapter = Shadow.extract(mBluetoothAdapter);
mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HEARING_AID);
mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HAP_CLIENT);
mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS);
mBluetoothAdapter.enable();
doReturn(mEventManager).when(mLocalBluetoothManager).getEventManager();
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
when(mLocalBluetoothProfileManager.getHapClientProfile()).thenReturn(mHapClientProfile);
when(mHearingAidProfile.isProfileReady()).thenReturn(true);
when(mHapClientProfile.isProfileReady()).thenReturn(true);
when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice);
when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS);
when(mCachedBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME);
}
private void sendIntent(Intent intent) {
for (BroadcastReceiver receiver : mShadowApplication.getReceiversForIntent(intent)) {
receiver.onReceive(mContext, intent);
}
}
private List<BluetoothDevice> generateHearingAidDeviceList() {
final List<BluetoothDevice> deviceList = new ArrayList<>(1);
deviceList.add(mBluetoothDevice);
return deviceList;
}
private List<BluetoothDevice> generateMultipleHearingAidDeviceList() {
// Generates different Bluetooth devices for testing multiple devices
final List<BluetoothDevice> deviceList = new ArrayList<>(2);
deviceList.add(mBluetoothDevice);
deviceList.add(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2));
return deviceList;
}
private Set<CachedBluetoothDevice> generateMemberDevices() {
final Set<CachedBluetoothDevice> memberDevices = new HashSet<>();
memberDevices.add(mCachedSubBluetoothDevice);
return memberDevices;
}
}

View File

@@ -0,0 +1,70 @@
/*
* 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.accessibility;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.telephony.TelephonyManager;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.XmlTestUtils;
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;
import java.util.List;
/** Tests for {@link AccessibilityHearingAidsFragment}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityHearingAidsFragmentTest {
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
private TelephonyManager mTelephonyManager;
@Before
public void setUp() {
mTelephonyManager = spy(mContext.getSystemService(TelephonyManager.class));
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
doReturn(true).when(mTelephonyManager).isHearingAidCompatibilitySupported();
}
@Test
public void getNonIndexableKeys_existInXmlLayout() {
final List<String> niks = AccessibilityHearingAidsFragment.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(mContext);
final List<String> keys =
XmlTestUtils.getKeysFromPreferenceXml(mContext, R.xml.accessibility_hearing_aids);
assertThat(keys).containsAtLeastElementsIn(niks);
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2021 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.graphics.drawable.Drawable;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.ImageTestUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AccessibilityLayerDrawable}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityLayerDrawableTest {
private static final int TEST_RES_ID =
com.android.internal.R.drawable.ic_accessibility_magnification;
private static final int TEST_RES_ID_2 =
com.android.internal.R.drawable.ic_accessibility_color_inversion;
private final Context mContext = ApplicationProvider.getApplicationContext();
@Test
public void createLayerDrawable_configCorrect() {
final Drawable expected1stDrawable = mContext.getDrawable(
R.drawable.a11y_button_preview_base);
final Drawable expected2ndDrawable = mContext.getDrawable(TEST_RES_ID);
final AccessibilityLayerDrawable actualDrawable =
AccessibilityLayerDrawable.createLayerDrawable(mContext, TEST_RES_ID,
/* opacity= */ 27);
final Drawable actual1stDrawable = actualDrawable.getDrawable(0);
final Drawable actual2ndDrawable = actualDrawable.getDrawable(1);
assertThat(ImageTestUtils.drawableToBitmap(actual1stDrawable).sameAs(
ImageTestUtils.drawableToBitmap(expected1stDrawable))).isTrue();
assertThat(ImageTestUtils.drawableToBitmap(actual2ndDrawable).sameAs(
ImageTestUtils.drawableToBitmap(expected2ndDrawable))).isTrue();
}
@Test
public void updateLayerDrawable_expectedFloatingMenuLayerDrawableState() {
final AccessibilityLayerDrawable originalDrawable =
AccessibilityLayerDrawable.createLayerDrawable(mContext, TEST_RES_ID, /* opacity= */
72);
originalDrawable.updateLayerDrawable(mContext, TEST_RES_ID_2, /* opacity= */ 27);
assertThat(originalDrawable.getConstantState()).isEqualTo(
new AccessibilityLayerDrawable.AccessibilityLayerDrawableState(mContext,
TEST_RES_ID_2, /* opacity= */ 27));
}
}

View File

@@ -0,0 +1,63 @@
/*
* 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.accessibility;
import static com.google.common.truth.Truth.assertThat;
import android.content.ComponentName;
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AccessibilityQuickSettingUtils}. */
@RunWith(RobolectricTestRunner.class)
public final class AccessibilityQuickSettingUtilsTest {
private static final String DUMMY_PACKAGE_NAME = "com.mock.example";
private static final String DUMMY_CLASS_NAME = DUMMY_PACKAGE_NAME + ".mock_a11y_service";
private static final String DUMMY_CLASS_NAME2 = DUMMY_PACKAGE_NAME + ".mock_a11y_service2";
private static final ComponentName DUMMY_COMPONENT_NAME = new ComponentName(DUMMY_PACKAGE_NAME,
DUMMY_CLASS_NAME);
private static final ComponentName DUMMY_COMPONENT_NAME2 = new ComponentName(DUMMY_PACKAGE_NAME,
DUMMY_CLASS_NAME2);
private final Context mContext = ApplicationProvider.getApplicationContext();
@Test
public void optInValueToSharedPreferences_optInValue_haveMatchString() {
AccessibilityQuickSettingUtils.optInValueToSharedPreferences(mContext,
DUMMY_COMPONENT_NAME);
assertThat(AccessibilityQuickSettingUtils.hasValueInSharedPreferences(mContext,
DUMMY_COMPONENT_NAME)).isTrue();
}
@Test
public void optInValueToSharedPreferences_optInTwoValues_haveMatchString() {
AccessibilityQuickSettingUtils.optInValueToSharedPreferences(mContext,
DUMMY_COMPONENT_NAME);
AccessibilityQuickSettingUtils.optInValueToSharedPreferences(mContext,
DUMMY_COMPONENT_NAME2);
assertThat(AccessibilityQuickSettingUtils.hasValueInSharedPreferences(mContext,
DUMMY_COMPONENT_NAME)).isTrue();
assertThat(AccessibilityQuickSettingUtils.hasValueInSharedPreferences(mContext,
DUMMY_COMPONENT_NAME2)).isTrue();
}
}

View File

@@ -0,0 +1,198 @@
/*
* 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.accessibility;
import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_SAVED_QS_TOOLTIP_RESHOW;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settingslib.PrimarySwitchPreference;
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.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.LooperMode;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowApplication;
/**
* Tests for {@link AccessibilityQuickSettingsPrimarySwitchPreferenceController}.
*/
@RunWith(RobolectricTestRunner.class)
@LooperMode(LooperMode.Mode.LEGACY)
public class AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest {
private static final String PLACEHOLDER_PACKAGE_NAME = "com.placeholder.example";
private static final String PLACEHOLDER_TILE_CLASS_NAME =
PLACEHOLDER_PACKAGE_NAME + "tile.placeholder";
private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName(
PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME);
private static final CharSequence PLACEHOLDER_TILE_CONTENT =
PLACEHOLDER_TILE_CLASS_NAME + ".tile.content";
private static final String TEST_KEY = "test_pref_key";
private static final String TEST_TITLE = "test_title";
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
private TestAccessibilityQuickSettingsPrimarySwitchPreferenceController mController;
private PrimarySwitchPreference mPreference;
private TestFragment mFragment;
private PreferenceScreen mScreen;
private PreferenceViewHolder mHolder;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceManager mPreferenceManager;
private static PopupWindow getLatestPopupWindow() {
final ShadowApplication shadowApplication =
Shadow.extract(ApplicationProvider.getApplicationContext());
return shadowApplication.getLatestPopupWindow();
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
mFragment = spy(new TestFragment());
when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
when(mFragment.getContext()).thenReturn(mContext);
mScreen = spy(new PreferenceScreen(mContext, /* attrs= */ null));
when(mScreen.getPreferenceManager()).thenReturn(mPreferenceManager);
doReturn(mScreen).when(mFragment).getPreferenceScreen();
mPreference = new PrimarySwitchPreference(mContext);
mPreference.setKey(TEST_KEY);
mPreference.setTitle(TEST_TITLE);
LayoutInflater inflater = LayoutInflater.from(mContext);
mHolder = PreferenceViewHolder.createInstanceForTests(inflater.inflate(
com.android.settingslib.widget.preference.twotarget.R.layout.preference_two_target, null));
LinearLayout mWidgetView = mHolder.itemView.findViewById(android.R.id.widget_frame);
inflater.inflate(R.layout.preference_widget_primary_switch, mWidgetView, true);
mPreference.onBindViewHolder(mHolder);
mController = new TestAccessibilityQuickSettingsPrimarySwitchPreferenceController(mContext,
TEST_KEY);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
}
@Test
public void setChecked_showTooltipView() {
mController.displayPreference(mScreen);
mController.setChecked(true);
assertThat(getLatestPopupWindow().isShowing()).isTrue();
}
@Test
public void setChecked_notCallDisplayPreference_notShowTooltipView() {
// Simulates the slice highlight menu that does not call {@link #displayPreference} before
// {@link #setChecked} called.
mController.setChecked(true);
assertThat(getLatestPopupWindow()).isNull();
}
@Test
public void setChecked_tooltipViewShown_notShowTooltipView() {
mController.displayPreference(mScreen);
mController.setChecked(true);
getLatestPopupWindow().dismiss();
mController.setChecked(false);
mController.setChecked(true);
assertThat(getLatestPopupWindow().isShowing()).isFalse();
}
@Test
@Config(shadows = ShadowFragment.class)
public void restoreValueFromSavedInstanceState_showTooltipView() {
final Bundle savedInstanceState = new Bundle();
savedInstanceState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true);
mController.onCreate(savedInstanceState);
mController.displayPreference(mScreen);
assertThat(getLatestPopupWindow().isShowing()).isTrue();
}
public static class TestAccessibilityQuickSettingsPrimarySwitchPreferenceController
extends AccessibilityQuickSettingsPrimarySwitchPreferenceController {
public TestAccessibilityQuickSettingsPrimarySwitchPreferenceController(Context context,
String preferenceKey) {
super(context, preferenceKey);
}
@Override
ComponentName getTileComponentName() {
return PLACEHOLDER_TILE_COMPONENT_NAME;
}
@Override
CharSequence getTileTooltipContent() {
return PLACEHOLDER_TILE_CONTENT;
}
}
private static class TestFragment extends SettingsPreferenceFragment {
@Override
protected boolean shouldSkipForInitialSUW() {
return false;
}
@Override
public int getMetricsCategory() {
return 0;
}
}
}

View File

@@ -0,0 +1,132 @@
/*
* 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.accessibility;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.robolectric.Shadows.shadowOf;
import android.app.Application;
import android.content.Context;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.PopupWindow;
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.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowLooper;
/** Tests for {@link AccessibilityQuickSettingsTooltipWindow}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityQuickSettingsTooltipWindowTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock
private PopupWindow.OnDismissListener mMockOnDismissListener;
private static final String TEST_PACKAGE_NAME = "com.test.package";
private static final int TEST_RES_ID = 1234;
private final Context mContext = ApplicationProvider.getApplicationContext();
private AccessibilityQuickSettingsTooltipWindow mTooltipView;
private View mView;
@Before
public void setUp() {
mTooltipView = new AccessibilityQuickSettingsTooltipWindow(mContext);
mView = new View(mContext);
}
@Test
public void initTooltipView_atMostAvailableTextWidth() {
final String quickSettingsTooltipsContent = mContext.getString(
R.string.accessibility_service_qs_tooltip_content, TEST_PACKAGE_NAME);
mTooltipView.setup(quickSettingsTooltipsContent, TEST_RES_ID);
final int getMaxWidth = mTooltipView.getAvailableWindowWidth();
assertThat(mTooltipView.getWidth()).isAtMost(getMaxWidth);
}
@Test
public void showTooltipView_success() {
mTooltipView.setup(TEST_PACKAGE_NAME, TEST_RES_ID);
assertThat(getLatestPopupWindow()).isNull();
mTooltipView.showAtTopCenter(mView);
assertThat(getLatestPopupWindow()).isSameInstanceAs(mTooltipView);
}
@Test
public void accessibilityClickActionOnTooltipViewShown_shouldInvokeCallbackAndNotShowing() {
mTooltipView.setup(TEST_PACKAGE_NAME, TEST_RES_ID);
mTooltipView.setOnDismissListener(mMockOnDismissListener);
mTooltipView.showAtTopCenter(mView);
final boolean isActionPerformed =
mTooltipView.getContentView().performAccessibilityAction(
AccessibilityNodeInfo.ACTION_CLICK,
/* arguments= */ null);
assertThat(isActionPerformed).isTrue();
verify(mMockOnDismissListener).onDismiss();
assertThat(getLatestPopupWindow().isShowing()).isFalse();
}
@Test
public void dismiss_tooltipViewShown_shouldInvokeCallbackAndNotShowing() {
mTooltipView.setup(TEST_PACKAGE_NAME, TEST_RES_ID);
mTooltipView.setOnDismissListener(mMockOnDismissListener);
mTooltipView.showAtTopCenter(mView);
mTooltipView.dismiss();
verify(mMockOnDismissListener).onDismiss();
assertThat(getLatestPopupWindow().isShowing()).isFalse();
}
@Test
public void waitAutoCloseDelayTime_tooltipViewShown_shouldInvokeCallbackAndNotShowing() {
mTooltipView.setup(TEST_PACKAGE_NAME, TEST_RES_ID, /* closeDelayTimeMillis= */ 1);
mTooltipView.setOnDismissListener(mMockOnDismissListener);
mTooltipView.showAtTopCenter(mView);
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
verify(mMockOnDismissListener).onDismiss();
assertThat(getLatestPopupWindow().isShowing()).isFalse();
}
private static PopupWindow getLatestPopupWindow() {
final ShadowApplication shadowApplication = shadowOf(
(Application) ApplicationProvider.getApplicationContext());
return shadowApplication.getLatestPopupWindow();
}
}

View File

@@ -0,0 +1,160 @@
/*
* 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.accessibility;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowContentResolver;
import java.util.Collection;
import java.util.List;
/** Test for {@link AccessibilitySettingsContentObserver}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilitySettingsContentObserverTest {
private static final String SPECIFIC_KEY_A_1 = "SPECIFIC_KEY_A_1";
private static final String SPECIFIC_KEY_A_2 = "SPECIFIC_KEY_A_2";
private static final String SPECIFIC_KEY_B_1 = "SPECIFIC_KEY_B_1";
private final Context mContext = ApplicationProvider.getApplicationContext();
private final AccessibilitySettingsContentObserver mObserver =
new AccessibilitySettingsContentObserver(new Handler());
private final AccessibilitySettingsContentObserver.ContentObserverCallback mObserverCallbackA =
spy(new TestableContentObserverCallback());
private final AccessibilitySettingsContentObserver.ContentObserverCallback mObserverCallbackB =
spy(new TestableContentObserverCallback());
private final ContentResolver mContentResolver = mContext.getContentResolver();
@Test
public void register_shouldRegisterContentObserverForDefaultKeys() {
mObserver.register(mContentResolver);
ShadowContentResolver shadowContentResolver = Shadow.extract(mContentResolver);
assertObserverToUri(shadowContentResolver,
Settings.Secure.ACCESSIBILITY_ENABLED, mObserver);
assertObserverToUri(shadowContentResolver,
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, mObserver);
}
@Test
public void unregister_shouldUnregisterContentObserver() {
mObserver.register(mContentResolver);
mObserver.unregister(mContentResolver);
ShadowContentResolver shadowContentResolver = Shadow.extract(mContentResolver);
assertNotObserverToUri(shadowContentResolver, Settings.Secure.ACCESSIBILITY_ENABLED);
assertNotObserverToUri(shadowContentResolver,
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
}
@Test
public void register_addSpecificKeys_shouldRegisterContentObserverForSpecificAndDefaultKeys() {
mObserver.registerKeysToObserverCallback(List.of(SPECIFIC_KEY_A_1), mObserverCallbackA);
mObserver.register(mContentResolver);
ShadowContentResolver shadowContentResolver = Shadow.extract(mContentResolver);
assertObserverToUri(shadowContentResolver,
Settings.Secure.ACCESSIBILITY_ENABLED, mObserver);
assertObserverToUri(shadowContentResolver,
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, mObserver);
assertObserverToUri(shadowContentResolver, SPECIFIC_KEY_A_1, mObserver);
}
@Test
public void onChange_shouldTriggerCallbackOnDefaultKey() {
mObserver.registerObserverCallback(mObserverCallbackA);
mObserver.register(mContentResolver);
mObserver.onChange(/* selfChange= */ false,
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_ENABLED));
verify(mObserverCallbackA).onChange(Settings.Secure.ACCESSIBILITY_ENABLED);
}
@Test
public void onChange_registerSpecificKeys_shouldTriggerSpecificCallback() {
mObserver.registerKeysToObserverCallback(
List.of(SPECIFIC_KEY_A_1, SPECIFIC_KEY_A_2), mObserverCallbackA);
mObserver.register(mContentResolver);
mObserver.onChange(/* selfChange= */ false,
Settings.Secure.getUriFor(SPECIFIC_KEY_A_2));
verify(mObserverCallbackA).onChange(SPECIFIC_KEY_A_2);
}
@Test
public void onChange_registerSpecificKeys_withoutTriggerOtherCallback() {
mObserver.registerKeysToObserverCallback(
List.of(SPECIFIC_KEY_A_1, SPECIFIC_KEY_A_2), mObserverCallbackA);
mObserver.registerKeysToObserverCallback(
List.of(SPECIFIC_KEY_B_1), mObserverCallbackB);
mObserver.register(mContentResolver);
mObserver.onChange(/* selfChange= */ false,
Settings.Secure.getUriFor(SPECIFIC_KEY_B_1));
verify(mObserverCallbackA, never()).onChange(SPECIFIC_KEY_A_1);
verify(mObserverCallbackA, never()).onChange(SPECIFIC_KEY_A_2);
verify(mObserverCallbackA, never()).onChange(SPECIFIC_KEY_B_1);
verify(mObserverCallbackB).onChange(SPECIFIC_KEY_B_1);
}
@After
public void tearDown() {
mObserver.unregister(mContentResolver);
}
private void assertNotObserverToUri(ShadowContentResolver resolver, String key) {
assertThat(resolver.getContentObservers(Settings.Secure.getUriFor(key))).isEmpty();
}
private void assertObserverToUri(ShadowContentResolver resolver,
String key, ContentObserver observer) {
Collection<ContentObserver> observers =
resolver.getContentObservers(Settings.Secure.getUriFor(key));
assertThat(observers).contains(observer);
}
private static class TestableContentObserverCallback implements
AccessibilitySettingsContentObserver.ContentObserverCallback {
@Override
public void onChange(String key) {
// do nothing
}
}
}

View File

@@ -0,0 +1,204 @@
/*
* 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.accessibility;
import static com.android.settings.accessibility.AccessibilitySettingsForSetupWizard.SCREEN_READER_PACKAGE_NAME;
import static com.android.settings.accessibility.AccessibilitySettingsForSetupWizard.SCREEN_READER_SERVICE_NAME;
import static com.android.settings.accessibility.AccessibilitySettingsForSetupWizard.SELECT_TO_SPEAK_PACKAGE_NAME;
import static com.android.settings.accessibility.AccessibilitySettingsForSetupWizard.SELECT_TO_SPEAK_SERVICE_NAME;
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.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.view.accessibility.AccessibilityManager;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.LifecycleOwner;
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.settingslib.RestrictedPreference;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupdesign.GlifPreferenceLayout;
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 java.util.ArrayList;
import java.util.List;
/**
* Tests for {@link AccessibilitySettingsForSetupWizard}.
*/
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class AccessibilitySettingsForSetupWizardTest {
private static final ComponentName TEST_SCREEN_READER_COMPONENT_NAME = new ComponentName(
SCREEN_READER_PACKAGE_NAME, SCREEN_READER_SERVICE_NAME);
private static final ComponentName TEST_SELECT_TO_SPEAK_COMPONENT_NAME = new ComponentName(
SELECT_TO_SPEAK_PACKAGE_NAME, SELECT_TO_SPEAK_SERVICE_NAME);
private final Context mContext = ApplicationProvider.getApplicationContext();
private final List<AccessibilityServiceInfo> mAccessibilityServices = new ArrayList<>();
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock
private AccessibilityManager mAccessibilityManager;
@Mock
private FragmentActivity mActivity;
@Mock
private GlifPreferenceLayout mGlifLayoutView;
@Mock
private FooterBarMixin mFooterBarMixin;
private AccessibilitySettingsForSetupWizard mFragment;
@Before
public void setUp() {
mFragment = spy(new TestAccessibilitySettingsForSetupWizard(mContext));
doReturn(mAccessibilityManager).when(mActivity).getSystemService(
AccessibilityManager.class);
when(mAccessibilityManager.getInstalledAccessibilityServiceList()).thenReturn(
mAccessibilityServices);
doReturn(mActivity).when(mFragment).getActivity();
doReturn(mock(LifecycleOwner.class)).when(mFragment).getViewLifecycleOwner();
doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class);
}
@Test
public void onViewCreated_verifyAction() {
mFragment.onViewCreated(mGlifLayoutView, null);
verify(mGlifLayoutView).setHeaderText(
mContext.getString(R.string.vision_settings_title));
verify(mGlifLayoutView).setDescriptionText(
mContext.getString(R.string.vision_settings_description));
verify(mFooterBarMixin).setPrimaryButton(any());
}
@Test
public void onResume_accessibilityServiceListInstalled_returnExpectedValue() {
addEnabledServiceInfo(TEST_SCREEN_READER_COMPONENT_NAME, true);
addEnabledServiceInfo(TEST_SELECT_TO_SPEAK_COMPONENT_NAME, true);
mFragment.onAttach(mContext);
mFragment.onViewCreated(mGlifLayoutView, null);
mFragment.onResume();
assertRestrictedPreferenceMatch(mFragment.mScreenReaderPreference,
TEST_SCREEN_READER_COMPONENT_NAME.getPackageName(),
TEST_SCREEN_READER_COMPONENT_NAME.flattenToString());
assertRestrictedPreferenceMatch(mFragment.mSelectToSpeakPreference,
TEST_SELECT_TO_SPEAK_COMPONENT_NAME.getPackageName(),
TEST_SELECT_TO_SPEAK_COMPONENT_NAME.flattenToString());
}
@Test
public void onResume_accessibilityServiceListNotInstalled_returnNull() {
mFragment.onAttach(mContext);
mFragment.onViewCreated(mGlifLayoutView, null);
mFragment.onResume();
assertThat(mFragment.mScreenReaderPreference.getKey()).isNull();
assertThat(mFragment.mSelectToSpeakPreference.getKey()).isNull();
}
private void addEnabledServiceInfo(ComponentName componentName, boolean isAccessibilityTool) {
final AccessibilityServiceInfo a11yServiceInfo = mock(AccessibilityServiceInfo.class);
when(a11yServiceInfo.getComponentName()).thenReturn(componentName);
when(a11yServiceInfo.isAccessibilityTool()).thenReturn(isAccessibilityTool);
final ResolveInfo resolveInfo = mock(ResolveInfo.class);
when(a11yServiceInfo.getResolveInfo()).thenReturn(resolveInfo);
resolveInfo.serviceInfo = mock(ServiceInfo.class);
resolveInfo.serviceInfo.packageName = componentName.getPackageName();
resolveInfo.serviceInfo.name = componentName.getClassName();
when(resolveInfo.loadLabel(mActivity.getPackageManager())).thenReturn(
componentName.getPackageName());
mAccessibilityServices.add(a11yServiceInfo);
}
private void assertRestrictedPreferenceMatch(RestrictedPreference preference, String title,
String key) {
assertThat(preference.getTitle().toString()).isEqualTo(title);
assertThat(preference.getKey()).isEqualTo(key);
assertThat(preference.getExtras().getString(AccessibilitySettings.EXTRA_TITLE))
.isEqualTo(title);
assertThat(preference.getExtras().getString(AccessibilitySettings.EXTRA_PREFERENCE_KEY))
.isEqualTo(key);
}
private static class TestAccessibilitySettingsForSetupWizard
extends AccessibilitySettingsForSetupWizard {
private final Context mContext;
private final PreferenceManager mPreferenceManager;
TestAccessibilitySettingsForSetupWizard(Context context) {
super();
mContext = context;
mPreferenceManager = new PreferenceManager(context);
mPreferenceManager.setPreferences(mPreferenceManager.createPreferenceScreen(context));
mDisplayMagnificationPreference = new Preference(context);
mScreenReaderPreference = new RestrictedPreference(context);
mSelectToSpeakPreference = new RestrictedPreference(context);
}
@Override
public int getPreferenceScreenResId() {
return R.xml.placeholder_prefs;
}
@Override
public PreferenceScreen getPreferenceScreen() {
return mPreferenceManager.getPreferenceScreen();
}
@Override
public PreferenceManager getPreferenceManager() {
return mPreferenceManager;
}
@Override
public Context getContext() {
return mContext;
}
}
}

View File

@@ -0,0 +1,494 @@
/*
* Copyright (C) 2017 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.Mockito.doReturn;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
import static java.util.Collections.singletonList;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityShortcutInfo;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.database.ContentObserver;
import android.os.Build;
import android.provider.Settings;
import android.view.accessibility.AccessibilityManager;
import androidx.fragment.app.Fragment;
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.accessibility.util.AccessibilityUtils;
import com.android.internal.content.PackageMonitor;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
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;
import com.android.settingslib.search.SearchIndexableRaw;
import com.android.settingslib.testutils.shadow.ShadowColorDisplayManager;
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;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowAccessibilityManager;
import org.robolectric.shadows.ShadowContentResolver;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/** Test for {@link AccessibilitySettings}. */
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowBluetoothAdapter.class,
ShadowUserManager.class,
ShadowColorDisplayManager.class,
ShadowApplicationPackageManager.class,
ShadowRestrictedLockUtilsInternal.class,
})
public class AccessibilitySettingsTest {
private static final String PACKAGE_NAME = "com.android.test";
private static final String CLASS_NAME = PACKAGE_NAME + ".test_a11y_service";
private static final ComponentName COMPONENT_NAME = new ComponentName(PACKAGE_NAME, CLASS_NAME);
private static final String EMPTY_STRING = "";
private static final String DEFAULT_SUMMARY = "default summary";
private static final String DEFAULT_DESCRIPTION = "default description";
private static final String DEFAULT_LABEL = "default label";
private static final Boolean SERVICE_ENABLED = true;
private static final Boolean SERVICE_DISABLED = false;
@Rule
public final MockitoRule mocks = MockitoJUnit.rule();
private final Context mContext = ApplicationProvider.getApplicationContext();
@Spy
private final AccessibilityServiceInfo mServiceInfo = getMockAccessibilityServiceInfo(
PACKAGE_NAME, CLASS_NAME);
@Mock
private AccessibilityShortcutInfo mShortcutInfo;
private ShadowAccessibilityManager mShadowAccessibilityManager;
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
private ActivityController<SettingsActivity> mActivityController;
private AccessibilitySettings mFragment;
@Before
public void setup() {
mShadowAccessibilityManager = Shadow.extract(AccessibilityManager.getInstance(mContext));
mShadowAccessibilityManager.setInstalledAccessibilityServiceList(new ArrayList<>());
mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
setMockAccessibilityShortcutInfo(mShortcutInfo);
Intent intent = new Intent();
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT,
AccessibilitySettings.class.getName());
mActivityController = ActivityController.of(new SettingsActivity(), intent);
}
@Test
public void getNonIndexableKeys_existInXmlLayout() {
final List<String> niks = AccessibilitySettings.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(mContext);
final List<String> keys =
XmlTestUtils.getKeysFromPreferenceXml(mContext, R.xml.accessibility_settings);
assertThat(keys).containsAtLeastElementsIn(niks);
}
@Test
public void getRawDataToIndex_isNull() {
final List<SearchIndexableRaw> indexableRawList =
AccessibilitySettings.SEARCH_INDEX_DATA_PROVIDER
.getRawDataToIndex(mContext, true);
assertThat(indexableRawList).isNull();
}
@Test
public void getServiceSummary_serviceCrash_showsStopped() {
mServiceInfo.crashed = true;
final CharSequence summary = AccessibilitySettings.getServiceSummary(mContext,
mServiceInfo, SERVICE_ENABLED);
assertThat(summary).isEqualTo(
mContext.getString(R.string.accessibility_summary_state_stopped));
}
@Test
public void getServiceSummary_invisibleToggle_shortcutEnabled_showsOnSummary() {
setInvisibleToggleFragmentType(mServiceInfo);
doReturn(DEFAULT_SUMMARY).when(mServiceInfo).loadSummary(any());
setShortcutEnabled(mServiceInfo.getComponentName(), true);
final CharSequence summary = AccessibilitySettings.getServiceSummary(mContext,
mServiceInfo, SERVICE_ENABLED);
assertThat(summary).isEqualTo(
mContext.getString(R.string.preference_summary_default_combination,
mContext.getString(R.string.accessibility_summary_shortcut_enabled),
DEFAULT_SUMMARY));
}
@Test
public void getServiceSummary_invisibleToggle_shortcutDisabled_showsOffSummary() {
setInvisibleToggleFragmentType(mServiceInfo);
setShortcutEnabled(mServiceInfo.getComponentName(), false);
doReturn(DEFAULT_SUMMARY).when(mServiceInfo).loadSummary(any());
final CharSequence summary = AccessibilitySettings.getServiceSummary(mContext,
mServiceInfo, SERVICE_ENABLED);
assertThat(summary).isEqualTo(
mContext.getString(R.string.preference_summary_default_combination,
mContext.getString(R.string.generic_accessibility_feature_shortcut_off),
DEFAULT_SUMMARY));
}
@Test
public void getServiceSummary_enableServiceShortcutOn_showsServiceEnabledShortcutOn() {
doReturn(EMPTY_STRING).when(mServiceInfo).loadSummary(any());
setShortcutEnabled(mServiceInfo.getComponentName(), true);
String summary = AccessibilitySettings.getServiceSummary(mContext,
mServiceInfo, SERVICE_ENABLED).toString();
assertThat(summary).isEqualTo(
mContext.getString(R.string.generic_accessibility_service_on));
}
@Test
public void getServiceSummary_enableServiceShortcutOff_showsServiceEnabledShortcutOff() {
doReturn(EMPTY_STRING).when(mServiceInfo).loadSummary(any());
setShortcutEnabled(mServiceInfo.getComponentName(), false);
String summary = AccessibilitySettings.getServiceSummary(
mContext, mServiceInfo, SERVICE_ENABLED).toString();
assertThat(summary).isEqualTo(
mContext.getString(R.string.generic_accessibility_service_on));
}
@Test
public void getServiceSummary_disableServiceShortcutOff_showsDisabledShortcutOff() {
doReturn(EMPTY_STRING).when(mServiceInfo).loadSummary(any());
setShortcutEnabled(mServiceInfo.getComponentName(), false);
String summary = AccessibilitySettings.getServiceSummary(mContext,
mServiceInfo, SERVICE_DISABLED).toString();
assertThat(summary).isEqualTo(
mContext.getString(R.string.generic_accessibility_service_off));
}
@Test
public void getServiceSummary_disableServiceShortcutOn_showsDisabledShortcutOn() {
doReturn(EMPTY_STRING).when(mServiceInfo).loadSummary(any());
setShortcutEnabled(mServiceInfo.getComponentName(), true);
String summary = AccessibilitySettings.getServiceSummary(mContext,
mServiceInfo, SERVICE_DISABLED).toString();
assertThat(summary).isEqualTo(
mContext.getString(R.string.generic_accessibility_service_off));
}
@Test
public void getServiceSummary_enableServiceShortcutOffAndHasSummary_showsEnabledSummary() {
setShortcutEnabled(mServiceInfo.getComponentName(), false);
doReturn(DEFAULT_SUMMARY).when(mServiceInfo).loadSummary(any());
String summary = AccessibilitySettings.getServiceSummary(mContext,
mServiceInfo, SERVICE_ENABLED).toString();
assertThat(summary).isEqualTo(
mContext.getString(R.string.preference_summary_default_combination,
mContext.getString(R.string.generic_accessibility_service_on),
DEFAULT_SUMMARY));
}
@Test
public void getServiceSummary_enableServiceShortcutOnAndHasSummary_showsEnabledSummary() {
doReturn(DEFAULT_SUMMARY).when(mServiceInfo).loadSummary(any());
setShortcutEnabled(mServiceInfo.getComponentName(), true);
String summary = AccessibilitySettings.getServiceSummary(mContext,
mServiceInfo, SERVICE_ENABLED).toString();
assertThat(summary).isEqualTo(
mContext.getString(R.string.preference_summary_default_combination,
mContext.getString(R.string.generic_accessibility_service_on),
DEFAULT_SUMMARY));
}
@Test
public void getServiceSummary_disableServiceShortcutOnAndHasSummary_showsDisabledSummary() {
doReturn(DEFAULT_SUMMARY).when(mServiceInfo).loadSummary(any());
setShortcutEnabled(mServiceInfo.getComponentName(), true);
String summary = AccessibilitySettings.getServiceSummary(mContext,
mServiceInfo, SERVICE_DISABLED).toString();
assertThat(summary).isEqualTo(
mContext.getString(R.string.preference_summary_default_combination,
mContext.getString(R.string.generic_accessibility_service_off),
DEFAULT_SUMMARY));
}
@Test
public void getServiceSummary_disableServiceShortcutOffAndHasSummary_showsDisabledSummary() {
setShortcutEnabled(mServiceInfo.getComponentName(), false);
doReturn(DEFAULT_SUMMARY).when(mServiceInfo).loadSummary(any());
String summary = AccessibilitySettings.getServiceSummary(mContext,
mServiceInfo, SERVICE_DISABLED).toString();
assertThat(summary).isEqualTo(
mContext.getString(R.string.preference_summary_default_combination,
mContext.getString(R.string.generic_accessibility_service_off),
DEFAULT_SUMMARY));
}
@Test
public void getServiceDescription_serviceCrash_showsStopped() {
mServiceInfo.crashed = true;
String description = AccessibilitySettings.getServiceDescription(mContext,
mServiceInfo, SERVICE_ENABLED).toString();
assertThat(description).isEqualTo(
mContext.getString(R.string.accessibility_description_state_stopped));
}
@Test
public void getServiceDescription_haveDescription_showsDescription() {
doReturn(DEFAULT_DESCRIPTION).when(mServiceInfo).loadDescription(any());
String description = AccessibilitySettings.getServiceDescription(mContext,
mServiceInfo, SERVICE_ENABLED).toString();
assertThat(description).isEqualTo(DEFAULT_DESCRIPTION);
}
@Test
public void onCreate_haveRegisterToSpecificUrisAndActions() {
setupFragment();
ShadowContentResolver shadowContentResolver = shadowOf(mContext.getContentResolver());
Collection<ContentObserver> a11yButtonTargetsObservers =
shadowContentResolver.getContentObservers(
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS));
Collection<ContentObserver> a11yShortcutTargetServiceObservers =
shadowContentResolver.getContentObservers(Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE));
List<BroadcastReceiver> broadcastReceivers =
shadowOf((Application) ApplicationProvider.getApplicationContext())
.getRegisteredReceivers()
.stream().map(wrapper -> wrapper.broadcastReceiver).toList();
assertThat(
a11yButtonTargetsObservers.stream()
.anyMatch(contentObserver ->
contentObserver instanceof AccessibilitySettingsContentObserver))
.isTrue();
assertThat(
a11yShortcutTargetServiceObservers.stream()
.anyMatch(contentObserver ->
contentObserver instanceof AccessibilitySettingsContentObserver))
.isTrue();
assertThat(broadcastReceivers.stream().anyMatch(
broadcastReceiver -> broadcastReceiver instanceof PackageMonitor)).isTrue();
}
@Test
public void onDestroy_unregisterObserverAndReceiver() {
setupFragment();
mActivityController.pause().stop().destroy();
ShadowContentResolver shadowContentResolver = shadowOf(mContext.getContentResolver());
Collection<ContentObserver> a11yButtonTargetsObservers =
shadowContentResolver.getContentObservers(
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS));
Collection<ContentObserver> a11yShortcutTargetServiceObservers =
shadowContentResolver.getContentObservers(Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE));
List<BroadcastReceiver> broadcastReceivers =
shadowOf((Application) ApplicationProvider.getApplicationContext())
.getRegisteredReceivers()
.stream().map(wrapper -> wrapper.broadcastReceiver).toList();
assertThat(
a11yButtonTargetsObservers.stream()
.anyMatch(contentObserver ->
contentObserver instanceof AccessibilitySettingsContentObserver))
.isFalse();
assertThat(
a11yShortcutTargetServiceObservers.stream()
.anyMatch(contentObserver ->
contentObserver instanceof AccessibilitySettingsContentObserver))
.isFalse();
assertThat(broadcastReceivers.stream().anyMatch(
broadcastReceiver -> broadcastReceiver instanceof PackageMonitor)).isFalse();
}
@Test
public void onContentChanged_updatePreferenceInForeground_preferenceUpdated() {
setupFragment();
mShadowAccessibilityManager.setInstalledAccessibilityServiceList(
singletonList(mServiceInfo));
mFragment.onContentChanged();
RestrictedPreference preference = mFragment.getPreferenceScreen().findPreference(
COMPONENT_NAME.flattenToString());
assertThat(preference).isNotNull();
}
@Test
public void onContentChanged_updatePreferenceInBackground_preferenceUpdated() {
setupFragment();
mFragment.onPause();
mFragment.onStop();
mShadowAccessibilityManager.setInstalledAccessibilityServiceList(
singletonList(mServiceInfo));
mFragment.onContentChanged();
mFragment.onStart();
RestrictedPreference preference = mFragment.getPreferenceScreen().findPreference(
COMPONENT_NAME.flattenToString());
assertThat(preference).isNotNull();
}
@Test
public void testAccessibilityMenuInSystem_IncludedInInteractionControl() {
mShadowAccessibilityManager.setInstalledAccessibilityServiceList(
List.of(getMockAccessibilityServiceInfo(
AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM)));
setupFragment();
final RestrictedPreference pref = mFragment.getPreferenceScreen().findPreference(
AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM.flattenToString());
final String prefCategory = mFragment.mServicePreferenceToPreferenceCategoryMap.get(
pref).getKey();
assertThat(prefCategory).isEqualTo(AccessibilitySettings.CATEGORY_INTERACTION_CONTROL);
}
@Test
public void testAccessibilityMenuInSystem_NoPrefWhenNotInstalled() {
mShadowAccessibilityManager.setInstalledAccessibilityServiceList(List.of());
setupFragment();
final RestrictedPreference pref = mFragment.getPreferenceScreen().findPreference(
AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM.flattenToString());
assertThat(pref).isNull();
}
private AccessibilityServiceInfo getMockAccessibilityServiceInfo(String packageName,
String className) {
return getMockAccessibilityServiceInfo(new ComponentName(packageName, className));
}
private AccessibilityServiceInfo getMockAccessibilityServiceInfo(ComponentName componentName) {
final ApplicationInfo applicationInfo = new ApplicationInfo();
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);
return info;
} catch (XmlPullParserException | IOException e) {
// Do nothing
}
return null;
}
private void setMockAccessibilityShortcutInfo(AccessibilityShortcutInfo mockInfo) {
final ActivityInfo activityInfo = Mockito.mock(ActivityInfo.class);
activityInfo.applicationInfo = new ApplicationInfo();
when(mockInfo.getActivityInfo()).thenReturn(activityInfo);
when(activityInfo.loadLabel(any())).thenReturn(DEFAULT_LABEL);
when(mockInfo.loadSummary(any())).thenReturn(DEFAULT_SUMMARY);
when(mockInfo.loadDescription(any())).thenReturn(DEFAULT_DESCRIPTION);
when(mockInfo.getComponentName()).thenReturn(COMPONENT_NAME);
}
private void setInvisibleToggleFragmentType(AccessibilityServiceInfo info) {
info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
}
private void setupFragment() {
mActivityController.create().start().resume();
Fragment fragment = mActivityController.get().getSupportFragmentManager().findFragmentById(
R.id.main_content);
assertThat(fragment).isNotNull();
assertThat(fragment).isInstanceOf(AccessibilitySettings.class);
mFragment = (AccessibilitySettings) fragment;
}
private void setShortcutEnabled(ComponentName componentName, boolean enabled) {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
enabled ? componentName.flattenToString() : "");
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2021 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.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.graphics.drawable.Drawable;
import androidx.test.core.app.ApplicationProvider;
import com.google.android.setupdesign.GlifPreferenceLayout;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AccessibilitySetupWizardUtils} */
@RunWith(RobolectricTestRunner.class)
public class AccessibilitySetupWizardUtilsTest {
private final Context mContext = ApplicationProvider.getApplicationContext();
@Test
public void setupGlifPreferenceLayout_assignValueToVariable() {
final String title = "title";
final String description = "description";
final Drawable icon = mock(Drawable.class);
GlifPreferenceLayout layout = mock(GlifPreferenceLayout.class);
AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(mContext, layout, title,
description, icon);
verify(layout).setHeaderText(title);
verify(layout).setDescriptionText(description);
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());
}
}

View File

@@ -0,0 +1,332 @@
/*
* Copyright (C) 2021 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.AccessibilityShortcutPreferenceFragment.KEY_SAVED_QS_TOOLTIP_RESHOW;
import static com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment.KEY_SAVED_USER_SHORTCUT_TYPE;
import static com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
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;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupWindow;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.testutils.shadow.ShadowFragment;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowApplication;
/** Tests for {@link AccessibilityShortcutPreferenceFragment} */
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class AccessibilityShortcutPreferenceFragmentTest {
private static final String PLACEHOLDER_PACKAGE_NAME = "com.placeholder.example";
private static final String PLACEHOLDER_CLASS_NAME = PLACEHOLDER_PACKAGE_NAME + ".placeholder";
private static final String PLACEHOLDER_TILE_CLASS_NAME =
PLACEHOLDER_PACKAGE_NAME + "tile.placeholder";
private static final ComponentName PLACEHOLDER_COMPONENT_NAME = new ComponentName(
PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CLASS_NAME);
private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName(
PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME);
private static final String PLACEHOLDER_TILE_TOOLTIP_CONTENT =
PLACEHOLDER_PACKAGE_NAME + "tooltip_content";
private static final String PLACEHOLDER_DIALOG_TITLE = "title";
private static final String SOFTWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
private static final String HARDWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
private TestAccessibilityShortcutPreferenceFragment mFragment;
private PreferenceScreen mScreen;
private Context mContext = ApplicationProvider.getApplicationContext();
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceManager mPreferenceManager;
@Before
public void setUpTestFragment() {
MockitoAnnotations.initMocks(this);
mFragment = spy(new TestAccessibilityShortcutPreferenceFragment(null));
when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
when(mFragment.getContext()).thenReturn(mContext);
when(mFragment.getActivity()).thenReturn(Robolectric.setupActivity(FragmentActivity.class));
mScreen = spy(new PreferenceScreen(mContext, null));
when(mScreen.getPreferenceManager()).thenReturn(mPreferenceManager);
doReturn(mScreen).when(mFragment).getPreferenceScreen();
}
@Test
public void updateShortcutPreferenceData_assignDefaultValueToVariable() {
mFragment.updateShortcutPreferenceData();
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
mFragment.getComponentName().flattenToString());
// Compare to default UserShortcutType
assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE);
}
@Test
public void updateShortcutPreferenceData_hasValueInSettings_assignToVariable() {
putStringIntoSettings(SOFTWARE_SHORTCUT_KEY, PLACEHOLDER_COMPONENT_NAME.flattenToString());
putStringIntoSettings(HARDWARE_SHORTCUT_KEY, PLACEHOLDER_COMPONENT_NAME.flattenToString());
mFragment.updateShortcutPreferenceData();
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
mFragment.getComponentName().flattenToString());
assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE);
}
@Test
public void updateShortcutPreferenceData_hasValueInSharedPreference_assignToVariable() {
final PreferredShortcut hardwareShortcut = new PreferredShortcut(
PLACEHOLDER_COMPONENT_NAME.flattenToString(), UserShortcutType.HARDWARE);
putUserShortcutTypeIntoSharedPreference(mContext, hardwareShortcut);
mFragment.updateShortcutPreferenceData();
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
mFragment.getComponentName().flattenToString());
assertThat(expectedType).isEqualTo(UserShortcutType.HARDWARE);
}
@Test
public void setupEditShortcutDialog_shortcutPreferenceOff_checkboxIsEmptyValue() {
mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
mContext, AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC,
PLACEHOLDER_DIALOG_TITLE,
this::callEmptyOnClicked);
final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
null);
mFragment.mShortcutPreference = shortcutPreference;
mFragment.mShortcutPreference.setChecked(false);
mFragment.setupEditShortcutDialog(dialog);
final int checkboxValue = mFragment.getShortcutTypeCheckBoxValue();
assertThat(checkboxValue).isEqualTo(UserShortcutType.EMPTY);
}
@Test
public void setupEditShortcutDialog_shortcutPreferenceOn_checkboxIsSavedValue() {
mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
mContext, AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC,
PLACEHOLDER_DIALOG_TITLE,
this::callEmptyOnClicked);
final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
null);
final PreferredShortcut hardwareShortcut = new PreferredShortcut(
PLACEHOLDER_COMPONENT_NAME.flattenToString(), UserShortcutType.HARDWARE);
mFragment.mShortcutPreference = shortcutPreference;
PreferredShortcuts.saveUserShortcutType(mContext, hardwareShortcut);
mFragment.mShortcutPreference.setChecked(true);
mFragment.setupEditShortcutDialog(dialog);
final int checkboxValue = mFragment.getShortcutTypeCheckBoxValue();
assertThat(checkboxValue).isEqualTo(UserShortcutType.HARDWARE);
}
@Test
@Config(shadows = ShadowFragment.class)
public void restoreValueFromSavedInstanceState_assignShortcutTypeToVariable() {
mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
mContext, AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC,
PLACEHOLDER_DIALOG_TITLE,
this::callEmptyOnClicked);
final Bundle savedInstanceState = new Bundle();
final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
null);
mFragment.mShortcutPreference = shortcutPreference;
savedInstanceState.putInt(KEY_SAVED_USER_SHORTCUT_TYPE,
UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE);
mFragment.onAttach(mContext);
mFragment.onCreate(savedInstanceState);
mFragment.setupEditShortcutDialog(dialog);
final int value = mFragment.getShortcutTypeCheckBoxValue();
mFragment.saveNonEmptyUserShortcutType(value);
final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
mFragment.getComponentName().flattenToString());
assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE);
}
@Test
@Config(shadows = ShadowFragment.class)
public void restoreValueFromSavedInstanceState_showTooltipView() {
mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
mFragment.showQuickSettingsTooltipIfNeeded(QuickSettingsTooltipType.GUIDE_TO_EDIT);
assertThat(getLatestPopupWindow().isShowing()).isTrue();
final Bundle savedInstanceState = new Bundle();
savedInstanceState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true);
mFragment.onAttach(mContext);
mFragment.onCreate(savedInstanceState);
mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
mFragment.onViewCreated(mFragment.getView(), savedInstanceState);
assertThat(getLatestPopupWindow().isShowing()).isTrue();
}
@Test
@Config(shadows = ShadowFragment.class)
public void showGeneralCategory_shouldInitCategory() {
final Bundle savedInstanceState = new Bundle();
when(mFragment.showGeneralCategory()).thenReturn(true);
mFragment.onAttach(mContext);
mFragment.onCreate(savedInstanceState);
verify(mFragment).initGeneralCategory();
}
@Test
public void showGeneralCategory_shouldSetDefaultDescription() {
assertThat(mFragment.getGeneralCategoryDescription(null)).isNotNull();
}
private void callEmptyOnClicked(DialogInterface dialog, int which) {}
private void putStringIntoSettings(String key, String componentName) {
Settings.Secure.putString(mContext.getContentResolver(), key, componentName);
}
private void putUserShortcutTypeIntoSharedPreference(Context context,
PreferredShortcut shortcut) {
PreferredShortcuts.saveUserShortcutType(context, shortcut);
}
private static PopupWindow getLatestPopupWindow() {
final ShadowApplication shadowApplication =
Shadow.extract(ApplicationProvider.getApplicationContext());
return shadowApplication.getLatestPopupWindow();
}
public static class TestAccessibilityShortcutPreferenceFragment
extends AccessibilityShortcutPreferenceFragment {
public TestAccessibilityShortcutPreferenceFragment(String restrictionKey) {
super(restrictionKey);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return mock(View.class);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// do nothing
}
@Override
protected ComponentName getComponentName() {
return PLACEHOLDER_COMPONENT_NAME;
}
@Override
protected CharSequence getLabelName() {
return PLACEHOLDER_PACKAGE_NAME;
}
@Override
protected ComponentName getTileComponentName() {
return PLACEHOLDER_TILE_COMPONENT_NAME;
}
@Override
protected CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
return PLACEHOLDER_TILE_TOOLTIP_CONTENT;
}
@Override
public int getUserShortcutTypes() {
return 0;
}
@Override
protected CharSequence getGeneralCategoryDescription(@Nullable CharSequence title) {
return super.getGeneralCategoryDescription(null);
}
@Override
protected boolean showGeneralCategory() {
// For showGeneralCategory_shouldInitCategory()
return true;
}
@Override
public int getMetricsCategory() {
return 0;
}
@Override
protected int getPreferenceScreenResId() {
return 0;
}
@Override
protected String getLogTag() {
return null;
}
@Override
public View getView() {
return mock(View.class);
}
};
}

View File

@@ -0,0 +1,156 @@
/*
* 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.accessibility;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.provider.Settings;
import android.view.accessibility.AccessibilityManager;
import com.android.settingslib.accessibility.AccessibilityUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowAccessibilityManager;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class AccessibilitySlicePreferenceControllerTest {
private final String PACKAGE_NAME = "com.android.settings.fake";
private final String CLASS_NAME = "com.android.settings.fake.classname";
private final String SERVICE_NAME = PACKAGE_NAME + "/" + CLASS_NAME;
private Context mContext;
private AccessibilitySlicePreferenceController mController;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Secure.putInt(contentResolver, Settings.Secure.ACCESSIBILITY_ENABLED, 1 /* on */);
Settings.Secure.putString(contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
SERVICE_NAME);
// Register the fake a11y Service
ShadowAccessibilityManager shadowAccessibilityManager = Shadow.extract(
RuntimeEnvironment.application.getSystemService(AccessibilityManager.class));
shadowAccessibilityManager.setInstalledAccessibilityServiceList(getFakeServiceList());
mController = new AccessibilitySlicePreferenceController(mContext, SERVICE_NAME);
}
@Test
public void getAvailability_availableService_returnsAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailability_unknownService_returnsUnsupported() {
AccessibilitySlicePreferenceController controller =
new AccessibilitySlicePreferenceController(mContext, "fake_service/name");
assertThat(controller.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void setChecked_availableService_serviceIsEnabled() {
mController.setChecked(true);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void setNotChecked_availableService_serviceIsDisabled() {
mController.setChecked(false);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void isChecked_serviceEnabled_returnsTrue() {
AccessibilityUtils.setAccessibilityServiceState(mContext,
ComponentName.unflattenFromString(mController.getPreferenceKey()), true);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void isChecked_serviceNotEnabled_returnsFalse() {
AccessibilitySlicePreferenceController controller =
new AccessibilitySlicePreferenceController(mContext, "fake_service/name");
assertThat(controller.isChecked()).isFalse();
}
@Test(expected = IllegalArgumentException.class)
public void illegalServiceName_exceptionThrown() {
new AccessibilitySlicePreferenceController(mContext, "not_split_by_slash");
}
@Test
public void isSliceable_returnTrue() {
assertThat(mController.isSliceable()).isTrue();
}
@Test
public void isPublicSlice_returnTrue() {
assertThat(mController.isPublicSlice()).isTrue();
}
private List<AccessibilityServiceInfo> getFakeServiceList() {
final List<AccessibilityServiceInfo> infoList = new ArrayList<>();
final ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.packageName = PACKAGE_NAME;
serviceInfo.name = CLASS_NAME;
final ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.serviceInfo = serviceInfo;
try {
final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo,
mContext);
ComponentName componentName = new ComponentName(PACKAGE_NAME, CLASS_NAME);
info.setComponentName(componentName);
infoList.add(info);
} catch (XmlPullParserException | IOException e) {
}
return infoList;
}
}

View File

@@ -0,0 +1,128 @@
/*
* 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.accessibility;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.provider.Settings;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
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;
/** Tests for {@link AccessibilityTimeoutController}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityTimeoutControllerTest {
private static final String PREF_KEY = "accessibility_control_timeout_30secs";
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock
private SelectorWithWidgetPreference mMockPref;
@Mock
private PreferenceScreen mScreen;
@Mock
private AccessibilitySettingsContentObserver mAccessibilitySettingsContentObserver;
private Context mContext = ApplicationProvider.getApplicationContext();
private ContentResolver mContentResolver;
private AccessibilityTimeoutController mController;
@Before
public void setup() {
mContentResolver = mContext.getContentResolver();
mController = new AccessibilityTimeoutController(mContext, PREF_KEY,
mAccessibilitySettingsContentObserver);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mMockPref);
when(mMockPref.getKey()).thenReturn(PREF_KEY);
final String prefTitle =
mContext.getResources().getString(R.string.accessibility_timeout_30secs);
when(mMockPref.getTitle()).thenReturn(prefTitle);
mController.displayPreference(mScreen);
}
@Test
public void getAvailabilityStatus_shouldReturnAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void updateState_notChecked() {
Settings.Secure.putString(mContentResolver,
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, "0");
mController.updateState(mMockPref);
// the first checked state is set to false by control
verify(mMockPref).setChecked(false);
verify(mMockPref).setChecked(false);
}
@Test
public void updateState_checked() {
Settings.Secure.putString(mContentResolver,
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, "30000");
mController.updateState(mMockPref);
// the first checked state is set to false by control
verify(mMockPref).setChecked(false);
verify(mMockPref).setChecked(true);
}
@Test
public void onRadioButtonClick() {
mController.onRadioButtonClicked(mMockPref);
String accessibilityUiTimeoutValue = Settings.Secure.getString(mContentResolver,
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS);
assertThat(accessibilityUiTimeoutValue).isEqualTo("30000");
}
@Test
public void onStart_registerSpecificContentObserverForSpecificKeys() {
mController.onStart();
verify(mAccessibilitySettingsContentObserver).register(mContentResolver);
}
@Test
public void onStop_unregisterContentObserver() {
mController.onStop();
verify(mAccessibilitySettingsContentObserver).unregister(mContentResolver);
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2019 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.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AccessibilityTimeoutPreferenceController}. */
@RunWith(RobolectricTestRunner.class)
public class AccessibilityTimeoutPreferenceControllerTest {
private Context mContext = ApplicationProvider.getApplicationContext();
private AccessibilityTimeoutPreferenceController mController;
@Before
public void setUp() {
mController = new AccessibilityTimeoutPreferenceController(mContext, "control_timeout");
}
@Test
public void getAvailabilityStatus_shouldReturnAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getSummary_byDefault_shouldReturnDefaultSummary() {
final String[] timeoutSummaries = mContext.getResources().getStringArray(
R.array.accessibility_timeout_summaries);
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, "0");
assertThat(mController.getSummary().toString()).isEqualTo(timeoutSummaries[0]);
}
@Test
public void getSummary_invalidTimeout_shouldReturnDefaultSummary() {
final String[] timeoutSummaries = mContext.getResources().getStringArray(
R.array.accessibility_timeout_summaries);
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, "invalid_timeout");
assertThat(mController.getSummary().toString()).isEqualTo(timeoutSummaries[0]);
}
@Test
public void getSummary_validTimeout_shouldReturnValidSummary() {
final String[] timeoutSummaries = mContext.getResources().getStringArray(
R.array.accessibility_timeout_summaries);
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, "60000");
assertThat(mController.getSummary().toString()).isEqualTo(timeoutSummaries[3]);
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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.accessibility;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AccessibilityTimeoutUtils}. */
@RunWith(RobolectricTestRunner.class)
public final class AccessibilityTimeoutUtilsTest {
private final Context mContext = ApplicationProvider.getApplicationContext();
@Test
public void getSecureAccessibilityTimeoutValue_byDefault_shouldReturnDefaultValue() {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, "0");
final int timeOutValue = AccessibilityTimeoutUtils.getSecureAccessibilityTimeoutValue(
mContext.getContentResolver());
assertThat(timeOutValue).isEqualTo(0);
}
@Test
public void getSecureAccessibilityTimeoutValue_invalidTimeout_shouldReturnDefaultValue() {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, "invalid_timeout");
final int timeOutValue = AccessibilityTimeoutUtils.getSecureAccessibilityTimeoutValue(
mContext.getContentResolver());
assertThat(timeOutValue).isEqualTo(0);
}
@Test
public void getSecureAccessibilityTimeoutValue_validTimeout_shouldReturnValidValue() {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, "60000");
final int timeOutValue = AccessibilityTimeoutUtils.getSecureAccessibilityTimeoutValue(
mContext.getContentResolver());
assertThat(timeOutValue).isEqualTo(60000);
}
}

View File

@@ -0,0 +1,298 @@
/*
* Copyright (C) 2019 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.accessibilityservice.AccessibilityServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Build;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.StringJoiner;
@RunWith(RobolectricTestRunner.class)
public final class AccessibilityUtilTest {
private static final String SECURE_TEST_KEY = "secure_test_key";
private static final String MOCK_PACKAGE_NAME = "com.mock.example";
private static final String MOCK_CLASS_NAME = MOCK_PACKAGE_NAME + ".mock_a11y_service";
private static final String MOCK_CLASS_NAME2 = MOCK_PACKAGE_NAME + ".mock_a11y_service2";
private static final ComponentName MOCK_COMPONENT_NAME = new ComponentName(MOCK_PACKAGE_NAME,
MOCK_CLASS_NAME);
private static final ComponentName MOCK_COMPONENT_NAME2 = new ComponentName(MOCK_PACKAGE_NAME,
MOCK_CLASS_NAME2);
private static final String SOFTWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
private static final String HARDWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
private static final String PLACEHOLDER_SETTING_FEATURE = "placeholderSettingFeature";
private Context mContext;
@Before
public void setUp() {
mContext = ApplicationProvider.getApplicationContext();
}
@Test
public void capitalize_shouldReturnCapitalizedString() {
assertThat(AccessibilityUtil.capitalize(null)).isNull();
assertThat(AccessibilityUtil.capitalize("")).isEmpty();
assertThat(AccessibilityUtil.capitalize("Hans")).isEqualTo("Hans");
assertThat(AccessibilityUtil.capitalize("hans")).isEqualTo("Hans");
assertThat(AccessibilityUtil.capitalize(",hans")).isEqualTo(",hans");
assertThat(AccessibilityUtil.capitalize("Hans, Hans")).isEqualTo("Hans, hans");
}
@Test
public void getSummary_hasValueAndEqualsToOne_shouldReturnOnString() {
setSettingsFeatureEnabled(SECURE_TEST_KEY, true);
final CharSequence result = AccessibilityUtil.getSummary(mContext, SECURE_TEST_KEY,
R.string.switch_on_text, R.string.switch_off_text);
assertThat(result)
.isEqualTo(mContext.getText(R.string.switch_on_text));
}
@Test
public void getSummary_hasValueAndEqualsToZero_shouldReturnOffString() {
setSettingsFeatureEnabled(SECURE_TEST_KEY, false);
final CharSequence result = AccessibilityUtil.getSummary(mContext, SECURE_TEST_KEY,
R.string.switch_on_text, R.string.switch_off_text);
assertThat(result)
.isEqualTo(mContext.getText(R.string.switch_off_text));
}
@Test
public void getSummary_noValue_shouldReturnOffString() {
final CharSequence result = AccessibilityUtil.getSummary(mContext, SECURE_TEST_KEY,
R.string.switch_on_text, R.string.switch_off_text);
assertThat(result)
.isEqualTo(mContext.getText(R.string.switch_off_text));
}
@Test
public void getAccessibilityServiceFragmentType_targetSdkQ_volumeShortcutType() {
final AccessibilityServiceInfo info = getMockAccessibilityServiceInfo();
info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo(
AccessibilityUtil.AccessibilityServiceFragmentType.VOLUME_SHORTCUT_TOGGLE);
}
@Test
public void getAccessibilityServiceFragmentType_targetSdkR_HaveA11yButton_invisibleType() {
final AccessibilityServiceInfo info = getMockAccessibilityServiceInfo();
info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo(
AccessibilityUtil.AccessibilityServiceFragmentType.INVISIBLE_TOGGLE);
}
@Test
public void getAccessibilityServiceFragmentType_targetSdkR_NoA11yButton_toggleType() {
final AccessibilityServiceInfo info = getMockAccessibilityServiceInfo();
info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
info.flags |= ~AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo(
AccessibilityUtil.AccessibilityServiceFragmentType.TOGGLE);
}
@Test
public void hasValueInSettings_putValue_hasValue() {
setShortcut(UserShortcutType.SOFTWARE, MOCK_COMPONENT_NAME.flattenToString());
assertThat(AccessibilityUtil.hasValueInSettings(mContext, UserShortcutType.SOFTWARE,
MOCK_COMPONENT_NAME)).isTrue();
}
@Test
public void getUserShortcutTypeFromSettings_putOneValue_hasValue() {
setShortcut(UserShortcutType.SOFTWARE, MOCK_COMPONENT_NAME.flattenToString());
final int shortcutType = AccessibilityUtil.getUserShortcutTypesFromSettings(mContext,
MOCK_COMPONENT_NAME);
assertThat(
(shortcutType & UserShortcutType.SOFTWARE) == UserShortcutType.SOFTWARE).isTrue();
}
@Test
public void getUserShortcutTypeFromSettings_putTwoValues_hasValue() {
setShortcut(UserShortcutType.SOFTWARE, MOCK_COMPONENT_NAME.flattenToString());
setShortcut(UserShortcutType.HARDWARE, MOCK_COMPONENT_NAME.flattenToString());
final int shortcutType = AccessibilityUtil.getUserShortcutTypesFromSettings(mContext,
MOCK_COMPONENT_NAME);
assertThat(
(shortcutType & UserShortcutType.SOFTWARE) == UserShortcutType.SOFTWARE).isTrue();
assertThat(
(shortcutType & UserShortcutType.HARDWARE) == UserShortcutType.HARDWARE).isTrue();
}
@Test
public void optInAllValuesToSettings_optInValue_haveMatchString() {
clearShortcuts();
int shortcutTypes = UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE;
AccessibilityUtil.optInAllValuesToSettings(mContext, shortcutTypes, MOCK_COMPONENT_NAME);
assertThat(getStringFromSettings(SOFTWARE_SHORTCUT_KEY)).isEqualTo(
MOCK_COMPONENT_NAME.flattenToString());
assertThat(getStringFromSettings(HARDWARE_SHORTCUT_KEY)).isEqualTo(
MOCK_COMPONENT_NAME.flattenToString());
}
@Test
public void optInValueToSettings_optInValue_haveMatchString() {
setShortcut(UserShortcutType.SOFTWARE, MOCK_COMPONENT_NAME.flattenToString());
AccessibilityUtil.optInValueToSettings(mContext, UserShortcutType.SOFTWARE,
MOCK_COMPONENT_NAME2);
assertThat(getStringFromSettings(SOFTWARE_SHORTCUT_KEY)).isEqualTo(
MOCK_COMPONENT_NAME.flattenToString() + ":"
+ MOCK_COMPONENT_NAME2.flattenToString());
}
@Test
public void optInValueToSettings_optInTwoValues_haveMatchString() {
setShortcut(UserShortcutType.SOFTWARE, MOCK_COMPONENT_NAME.flattenToString());
AccessibilityUtil.optInValueToSettings(mContext, UserShortcutType.SOFTWARE,
MOCK_COMPONENT_NAME2);
AccessibilityUtil.optInValueToSettings(mContext, UserShortcutType.SOFTWARE,
MOCK_COMPONENT_NAME2);
assertThat(getStringFromSettings(SOFTWARE_SHORTCUT_KEY)).isEqualTo(
MOCK_COMPONENT_NAME.flattenToString() + ":"
+ MOCK_COMPONENT_NAME2.flattenToString());
}
@Test
public void optOutAllValuesToSettings_optOutValue_emptyString() {
setShortcut(UserShortcutType.SOFTWARE, MOCK_COMPONENT_NAME.flattenToString());
setShortcut(UserShortcutType.HARDWARE, MOCK_COMPONENT_NAME.flattenToString());
int shortcutTypes =
UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE | UserShortcutType.TRIPLETAP;
AccessibilityUtil.optOutAllValuesFromSettings(mContext, shortcutTypes,
MOCK_COMPONENT_NAME);
assertThat(getStringFromSettings(SOFTWARE_SHORTCUT_KEY)).isEmpty();
assertThat(getStringFromSettings(HARDWARE_SHORTCUT_KEY)).isEmpty();
}
@Test
public void optOutValueFromSettings_optOutValue_emptyString() {
setShortcut(UserShortcutType.SOFTWARE, MOCK_COMPONENT_NAME.flattenToString());
AccessibilityUtil.optOutValueFromSettings(mContext, UserShortcutType.SOFTWARE,
MOCK_COMPONENT_NAME);
assertThat(getStringFromSettings(SOFTWARE_SHORTCUT_KEY)).isEmpty();
}
@Test
public void optOutValueFromSettings_optOutValue_haveMatchString() {
setShortcut(UserShortcutType.SOFTWARE, MOCK_COMPONENT_NAME.flattenToString(),
MOCK_COMPONENT_NAME2.flattenToString());
AccessibilityUtil.optOutValueFromSettings(mContext, UserShortcutType.SOFTWARE,
MOCK_COMPONENT_NAME2);
assertThat(getStringFromSettings(SOFTWARE_SHORTCUT_KEY)).isEqualTo(
MOCK_COMPONENT_NAME.flattenToString());
}
private AccessibilityServiceInfo getMockAccessibilityServiceInfo() {
final ApplicationInfo applicationInfo = new ApplicationInfo();
final ServiceInfo serviceInfo = new ServiceInfo();
applicationInfo.packageName = MOCK_PACKAGE_NAME;
serviceInfo.packageName = MOCK_PACKAGE_NAME;
serviceInfo.name = MOCK_CLASS_NAME;
serviceInfo.applicationInfo = applicationInfo;
final ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.serviceInfo = serviceInfo;
try {
final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo,
mContext);
info.setComponentName(MOCK_COMPONENT_NAME);
return info;
} catch (XmlPullParserException | IOException e) {
// Do nothing
}
return null;
}
private String getStringFromSettings(String key) {
return Settings.Secure.getString(mContext.getContentResolver(), key);
}
private void setSettingsFeatureEnabled(String settingsKey, boolean enabled) {
Settings.Secure.putInt(mContext.getContentResolver(),
settingsKey,
enabled ? AccessibilityUtil.State.ON : AccessibilityUtil.State.OFF);
}
private void setShortcut(@UserShortcutType int shortcutType, String... componentNames) {
StringJoiner shortcutComponents = new StringJoiner(":");
for (String componentName : componentNames) {
shortcutComponents.add(componentName);
}
Settings.Secure.putString(mContext.getContentResolver(),
shortcutType == UserShortcutType.SOFTWARE ? SOFTWARE_SHORTCUT_KEY
: HARDWARE_SHORTCUT_KEY, shortcutComponents.toString());
}
private void clearShortcuts() {
Settings.Secure.putString(mContext.getContentResolver(), SOFTWARE_SHORTCUT_KEY, "");
Settings.Secure.putString(mContext.getContentResolver(), HARDWARE_SHORTCUT_KEY, "");
}
}

View File

@@ -0,0 +1,165 @@
/*
* 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.accessibility;
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 android.media.AudioManager;
import android.os.VibrationAttributes;
import android.os.Vibrator;
import android.provider.Settings;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.testutils.shadow.ShadowInteractionJankMonitor;
import com.android.settings.widget.SeekBarPreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
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.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowInteractionJankMonitor.class})
public class AlarmVibrationIntensityPreferenceControllerTest {
private static final String PREFERENCE_KEY = "preference_key";
@Mock private PreferenceScreen mScreen;
@Mock private AudioManager mAudioManager;
private Lifecycle mLifecycle;
private Context mContext;
private Vibrator mVibrator;
private AlarmVibrationIntensityPreferenceController mController;
private SeekBarPreference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycle = new Lifecycle(() -> mLifecycle);
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager);
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
mVibrator = mContext.getSystemService(Vibrator.class);
mController = new AlarmVibrationIntensityPreferenceController(mContext, PREFERENCE_KEY,
Vibrator.VIBRATION_INTENSITY_HIGH);
mLifecycle.addObserver(mController);
mPreference = new SeekBarPreference(mContext);
mPreference.setSummary("Test summary");
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
}
@Test
public void verifyConstants() {
assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
assertThat(mController.getMin()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
assertThat(mController.getMax()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
}
@Test
public void missingSetting_shouldReturnDefault() {
Settings.System.putString(mContext.getContentResolver(),
Settings.System.ALARM_VIBRATION_INTENSITY, /* value= */ null);
mController.updateState(mPreference);
assertThat(mPreference.getProgress()).isEqualTo(
mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_ALARM));
}
@Test
public void updateState_ringerModeUpdates_shouldNotAffectSettings() {
updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW);
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
mController.updateState(mPreference);
assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
assertThat(mPreference.isEnabled()).isTrue();
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
mController.updateState(mPreference);
assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
assertThat(mPreference.isEnabled()).isTrue();
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
mController.updateState(mPreference);
assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
assertThat(mPreference.isEnabled()).isTrue();
}
@Test
public void updateState_shouldDisplayIntensityInSliderPosition() {
updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH);
mController.updateState(mPreference);
assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY,
Vibrator.VIBRATION_INTENSITY_MEDIUM);
mController.updateState(mPreference);
assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW);
mController.updateState(mPreference);
assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
mController.updateState(mPreference);
assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
}
@Test
public void setProgress_updatesIntensitySetting() throws Exception {
mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_OFF);
assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY))
.isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_LOW);
assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY))
.isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_MEDIUM);
assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY))
.isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_HIGH);
assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY))
.isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
}
private void updateSetting(String key, int value) {
Settings.System.putInt(mContext.getContentResolver(), key, value);
}
private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
return Settings.System.getInt(mContext.getContentResolver(), settingKey);
}
}

View File

@@ -0,0 +1,153 @@
/*
* 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.accessibility;
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 android.media.AudioManager;
import android.os.VibrationAttributes;
import android.os.Vibrator;
import android.provider.Settings;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
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;
@RunWith(RobolectricTestRunner.class)
public class AlarmVibrationTogglePreferenceControllerTest {
private static final String PREFERENCE_KEY = "preference_key";
@Mock private PreferenceScreen mScreen;
@Mock AudioManager mAudioManager;
private Lifecycle mLifecycle;
private Context mContext;
private Vibrator mVibrator;
private AlarmVibrationTogglePreferenceController mController;
private SwitchPreference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycle = new Lifecycle(() -> mLifecycle);
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager);
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
mVibrator = mContext.getSystemService(Vibrator.class);
mController = new AlarmVibrationTogglePreferenceController(mContext, PREFERENCE_KEY);
mLifecycle.addObserver(mController);
mPreference = new SwitchPreference(mContext);
mPreference.setSummary("Test summary");
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
}
@Test
public void verifyConstants() {
assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
}
@Test
public void missingSetting_shouldReturnDefault() {
Settings.System.putString(mContext.getContentResolver(),
Settings.System.ALARM_VIBRATION_INTENSITY, /* value= */ null);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
}
@Test
public void updateState_ringerModeUpdates_shouldNotAffectSettings() {
updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW);
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
assertThat(mPreference.isEnabled()).isTrue();
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
assertThat(mPreference.isEnabled()).isTrue();
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
assertThat(mPreference.isEnabled()).isTrue();
}
@Test
public void updateState_shouldDisplayOnOffState() {
updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY,
Vibrator.VIBRATION_INTENSITY_MEDIUM);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isFalse();
}
@Test
public void setChecked_updatesIntensityAndDependentSettings() throws Exception {
updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isFalse();
mController.setChecked(true);
assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY)).isEqualTo(
mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_ALARM));
mController.setChecked(false);
assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY))
.isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
}
private void updateSetting(String key, int value) {
Settings.System.putInt(mContext.getContentResolver(), key, value);
}
private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
return Settings.System.getInt(mContext.getContentResolver(), settingKey);
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2021 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.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.robolectric.RobolectricTestRunner;
import java.util.List;
/** Tests for {@link AudioAdjustmentFragment}. */
@RunWith(RobolectricTestRunner.class)
public class AudioAdjustmentFragmentTest {
private final Context mContext = ApplicationProvider.getApplicationContext();
private AudioAdjustmentFragment mFragment;
@Before
public void setUp() {
mFragment = new AudioAdjustmentFragment();
}
@Test
public void getMetricsCategory_returnsCorrectCategory() {
assertThat(mFragment.getMetricsCategory()).isEqualTo(
SettingsEnums.ACCESSIBILITY_AUDIO_ADJUSTMENT);
}
@Test
public void getPreferenceScreenResId_returnsCorrectXml() {
assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(
R.xml.accessibility_audio_adjustment);
}
@Test
public void getLogTag_returnsCorrectTag() {
assertThat(mFragment.getLogTag()).isEqualTo("AudioAdjustmentFragment");
}
@Test
public void getNonIndexableKeys_existInXmlLayout() {
final List<String> niks = AudioAdjustmentFragment.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(mContext);
final List<String> keys =
XmlTestUtils.getKeysFromPreferenceXml(mContext,
R.xml.accessibility_audio_adjustment);
assertThat(keys).containsAtLeastElementsIn(niks);
}
}

View File

@@ -0,0 +1,132 @@
/*
* 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.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 AudioDescriptionPreferenceControllerTest {
private static final String KEY_AUDIO_DESCRIPTION =
Settings.Secure.ENABLED_ACCESSIBILITY_AUDIO_DESCRIPTION_BY_DEFAULT;
private static final int UNKNOWN = -1;
private final Context mContext = ApplicationProvider.getApplicationContext();
private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext));
private final AudioDescriptionPreferenceController mController =
new AudioDescriptionPreferenceController(mContext,
AudioDescriptionPreferenceController.PREF_KEY);
@Before
public void setUp() {
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mSwitchPreference.setKey(AudioDescriptionPreferenceController.PREF_KEY);
screen.addPreference(mSwitchPreference);
mController.displayPreference(screen);
}
@Test
public void getAvailabilityStatus_byDefault_shouldReturnAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void isChecked_disableAudioDescription_onResumeShouldReturnFalse() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, OFF);
mController.updateState(mSwitchPreference);
assertThat(mController.isChecked()).isFalse();
assertThat(mSwitchPreference.isChecked()).isFalse();
}
@Test
public void isChecked_enableAudioDescription_onResumeShouldReturnTrue() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, ON);
mController.updateState(mSwitchPreference);
assertThat(mController.isChecked()).isTrue();
assertThat(mSwitchPreference.isChecked()).isTrue();
}
@Test
public void performClick_enableAudioDescription_shouldReturnTrue() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, OFF);
mController.updateState(mSwitchPreference);
mSwitchPreference.performClick();
verify(mSwitchPreference).setChecked(true);
assertThat(mController.isChecked()).isTrue();
assertThat(mSwitchPreference.isChecked()).isTrue();
}
@Test
public void performClick_disableAudioDescription_shouldReturnFalse() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, ON);
mController.updateState(mSwitchPreference);
mSwitchPreference.performClick();
verify(mSwitchPreference).setChecked(false);
assertThat(mController.isChecked()).isFalse();
assertThat(mSwitchPreference.isChecked()).isFalse();
}
@Test
public void setChecked_setFalse_shouldDisableAudioDescription() {
mController.setChecked(false);
assertThat(Settings.Secure.getInt(
mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, UNKNOWN)).isEqualTo(OFF);
}
@Test
public void setChecked_setTrue_shouldEnableAudioDescription() {
mController.setChecked(true);
assertThat(Settings.Secure.getInt(
mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, UNKNOWN)).isEqualTo(ON);
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2019 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 android.view.accessibility.AccessibilityManager.AUTOCLICK_DELAY_DEFAULT;
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 android.content.Context;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AutoclickPreferenceController}. */
@RunWith(RobolectricTestRunner.class)
public class AutoclickPreferenceControllerTest {
private final Context mContext = ApplicationProvider.getApplicationContext();
private AutoclickPreferenceController mController;
@Before
public void setUp() {
mController = new AutoclickPreferenceController(mContext, "auto_click");
}
@Test
public void getAvailabilityStatus_shouldReturnAvailableUnsearchable() {
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
}
@Test
public void getSummary_disabledAutoclick_shouldReturnOffSummary() {
setAutoClickEnabled(false);
assertThat(mController.getSummary().toString())
.isEqualTo(mContext.getText(R.string.autoclick_disabled));
}
@Test
public void getSummary_enabledAutoclick_shouldReturnOnSummary() {
setAutoClickEnabled(true);
setAutoClickDelayed(AUTOCLICK_DELAY_DEFAULT);
assertThat(mController.getSummary().toString())
.isEqualTo(AutoclickUtils.getAutoclickDelaySummary(
mContext,
R.string.accessibilty_autoclick_preference_subtitle_medium_delay,
AUTOCLICK_DELAY_DEFAULT).toString());
}
private void setAutoClickEnabled(boolean enabled) {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, enabled ? ON : OFF);
}
private void setAutoClickDelayed(int delayedInMs) {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, delayedInMs);
}
}

View File

@@ -0,0 +1,55 @@
/*
* 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.accessibility;
import static com.android.settings.accessibility.AutoclickUtils.MAX_AUTOCLICK_DELAY_MS;
import static com.android.settings.accessibility.AutoclickUtils.MIN_AUTOCLICK_DELAY_MS;
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.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AutoclickUtils}. */
@RunWith(RobolectricTestRunner.class)
public final class AutoclickUtilsTest {
private final Context mContext = ApplicationProvider.getApplicationContext();
@Test
public void getAutoclickDelaySummary_minDelay_shouldReturnOnSummary() {
final CharSequence summary = AutoclickUtils.getAutoclickDelaySummary(
mContext, R.string.accessibilty_autoclick_delay_unit_second,
MIN_AUTOCLICK_DELAY_MS);
assertThat(summary.toString()).isEqualTo("0.2 seconds");
}
@Test
public void getAutoclickDelaySummary_maxDelay_shouldReturnOnSummary() {
final CharSequence summary = AutoclickUtils.getAutoclickDelaySummary(
mContext, R.string.accessibilty_autoclick_delay_unit_second,
MAX_AUTOCLICK_DELAY_MS);
assertThat(summary.toString()).isEqualTo("1 second");
}
}

View File

@@ -0,0 +1,125 @@
/*
* 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.when;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.bluetooth.Utils;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
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;
import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
/** Tests for {@link AvailableHearingDeviceUpdater}. */
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothUtils.class})
public class AvailableHearingDeviceUpdaterTest {
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
private final Context mContext = ApplicationProvider.getApplicationContext();
@Mock
private DevicePreferenceCallback mDevicePreferenceCallback;
@Mock
private CachedBluetoothDeviceManager mCachedDeviceManager;
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
@Mock
private CachedBluetoothDevice mCachedBluetoothDevice;
@Mock
private BluetoothDevice mBluetoothDevice;
private AvailableHearingDeviceUpdater mUpdater;
@Before
public void setUp() {
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
mUpdater = new AvailableHearingDeviceUpdater(mContext,
mDevicePreferenceCallback, /* metricsCategory= */ 0);
}
@Test
public void isFilterMatch_connectedHearingDevice_returnTrue() {
CachedBluetoothDevice connectedHearingDevice = mCachedBluetoothDevice;
when(connectedHearingDevice.isHearingAidDevice()).thenReturn(true);
when(mBluetoothDevice.isConnected()).thenReturn(true);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(
new ArrayList<>(List.of(connectedHearingDevice)));
assertThat(mUpdater.isFilterMatched(connectedHearingDevice)).isEqualTo(true);
}
@Test
public void isFilterMatch_nonConnectedHearingDevice_returnFalse() {
CachedBluetoothDevice nonConnectedHearingDevice = mCachedBluetoothDevice;
when(nonConnectedHearingDevice.isHearingAidDevice()).thenReturn(true);
when(mBluetoothDevice.isConnected()).thenReturn(false);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(
new ArrayList<>(List.of(nonConnectedHearingDevice)));
assertThat(mUpdater.isFilterMatched(nonConnectedHearingDevice)).isEqualTo(false);
}
@Test
public void isFilterMatch_connectedBondingHearingDevice_returnFalse() {
CachedBluetoothDevice connectedBondingHearingDevice = mCachedBluetoothDevice;
when(connectedBondingHearingDevice.isHearingAidDevice()).thenReturn(true);
when(mBluetoothDevice.isConnected()).thenReturn(true);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(
new ArrayList<>(List.of(connectedBondingHearingDevice)));
assertThat(mUpdater.isFilterMatched(connectedBondingHearingDevice)).isEqualTo(false);
}
@Test
public void isFilterMatch_hearingDeviceNotInCachedDevicesList_returnFalse() {
CachedBluetoothDevice notInCachedDevicesListDevice = mCachedBluetoothDevice;
when(notInCachedDevicesListDevice.isHearingAidDevice()).thenReturn(true);
when(mBluetoothDevice.isConnected()).thenReturn(true);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(new ArrayList<>());
assertThat(mUpdater.isFilterMatched(notInCachedDevicesListDevice)).isEqualTo(false);
}
}

View File

@@ -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());
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2019 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.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.testutils.shadow.ShadowInteractionJankMonitor;
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;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowInteractionJankMonitor.class})
public class BalanceSeekBarPreferenceTest {
private static final int BALANCE_CENTER_VALUE = 100;
private static final int BALANCE_MAX_VALUE = 200;
private Context mContext;
private AttributeSet mAttrs;
private PreferenceViewHolder mHolder;
private BalanceSeekBar mSeekBar;
private BalanceSeekBarPreference mSeekBarPreference;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mSeekBarPreference = new BalanceSeekBarPreference(mContext, mAttrs);
LayoutInflater inflater = LayoutInflater.from(mContext);
final View view =
inflater.inflate(mSeekBarPreference.getLayoutResource(),
new LinearLayout(mContext), false);
mHolder = PreferenceViewHolder.createInstanceForTests(view);
mSeekBar = (BalanceSeekBar) view.findViewById(com.android.internal.R.id.seekbar);
}
@Test
public void seekBarPreferenceOnBindViewHolder_shouldInitSeekBarValue() {
mSeekBarPreference.onBindViewHolder(mHolder);
assertThat(mSeekBar.getMax()).isEqualTo(BALANCE_MAX_VALUE);
assertThat(mSeekBar.getProgress()).isEqualTo(BALANCE_CENTER_VALUE);
}
}

View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2019 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 android.view.HapticFeedbackConstants.CLOCK_TICK;
import static android.view.HapticFeedbackConstants.CONTEXT_CLICK;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.robolectric.Shadows.shadowOf;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.SeekBar;
import com.android.settings.testutils.shadow.ShadowSystemSettings;
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;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowSystemSettings.class,
})
public class BalanceSeekBarTest {
// Fix the maximum process value to 200 for testing the BalanceSeekBar.
// It affects the SeekBar value of center(100) and snapThreshold(200 * SNAP_TO_PERCENTAGE).
private static final int MAX_PROGRESS_VALUE = 200;
private Context mContext;
private AttributeSet mAttrs;
private BalanceSeekBar mSeekBar;
private BalanceSeekBar.OnSeekBarChangeListener mProxySeekBarListener;
private SeekBar.OnSeekBarChangeListener mockSeekBarChangeListener;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mSeekBar = new BalanceSeekBar(mContext, mAttrs);
mProxySeekBarListener = shadowOf(mSeekBar).getOnSeekBarChangeListener();
mockSeekBarChangeListener = mock(SeekBar.OnSeekBarChangeListener.class);
mSeekBar.setOnSeekBarChangeListener(mockSeekBarChangeListener);
}
@Test
public void onStartTrackingTouch_shouldInvokeMethod() {
mProxySeekBarListener.onStartTrackingTouch(mSeekBar);
verify(mockSeekBarChangeListener, times(1)).onStartTrackingTouch(mSeekBar);
}
@Test
public void onStopTrackingTouch_shouldInvokeMethod() {
mProxySeekBarListener.onStopTrackingTouch(mSeekBar);
verify(mockSeekBarChangeListener, times(1)).onStopTrackingTouch(mSeekBar);
}
@Test
public void onProgressChanged_shouldInvokeMethod() {
// Assign the test value of SeekBar progress
mProxySeekBarListener.onProgressChanged(mSeekBar, MAX_PROGRESS_VALUE, true);
verify(mockSeekBarChangeListener, times(1)).onProgressChanged(eq(mSeekBar),
eq(MAX_PROGRESS_VALUE), eq(true));
}
@Test
public void onProgressChanged_minimumValue_clockTickFeedbackPerformed() {
mSeekBar.performHapticFeedback(CONTEXT_CLICK);
mProxySeekBarListener.onProgressChanged(mSeekBar, 0, true);
assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isEqualTo(CLOCK_TICK);
}
@Test
public void onProgressChanged_centerValue_clockTickFeedbackPerformed() {
mSeekBar.performHapticFeedback(CONTEXT_CLICK);
mProxySeekBarListener.onProgressChanged(mSeekBar, MAX_PROGRESS_VALUE / 2, true);
assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isEqualTo(CLOCK_TICK);
}
@Test
public void onProgressChanged_maximumValue_clockTickFeedbackPerformed() {
mSeekBar.setMax(MAX_PROGRESS_VALUE);
mSeekBar.performHapticFeedback(CONTEXT_CLICK);
mProxySeekBarListener.onProgressChanged(mSeekBar, MAX_PROGRESS_VALUE, true);
assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isEqualTo(CLOCK_TICK);
}
@Test
public void setMaxTest_shouldSetValue() {
mSeekBar.setMax(MAX_PROGRESS_VALUE);
assertThat(getBalanceSeekBarCenter(mSeekBar)).isEqualTo(MAX_PROGRESS_VALUE / 2);
assertThat(getBalanceSeekBarSnapThreshold(mSeekBar)).isEqualTo(
MAX_PROGRESS_VALUE * BalanceSeekBar.SNAP_TO_PERCENTAGE);
}
@Test
public void setProgressTest_shouldSnapToCenter() {
// Assign the test value of SeekBar progress within the threshold (94-106 in this case).
final int progressWithinThreshold = 102;
mSeekBar.setMax(MAX_PROGRESS_VALUE);
mSeekBar.setProgress(progressWithinThreshold + 10); //set progress which is over threshold.
mProxySeekBarListener.onProgressChanged(mSeekBar, progressWithinThreshold, true);
assertThat(mSeekBar.getProgress()).isEqualTo(getBalanceSeekBarCenter(mSeekBar));
}
@Test
public void setProgressTest_shouldMaintainInputValue() {
// Assign the test value of SeekBar progress without the threshold.
final int progressWithoutThreshold = 107;
mSeekBar.setMax(MAX_PROGRESS_VALUE);
mSeekBar.setProgress(progressWithoutThreshold);
mProxySeekBarListener.onProgressChanged(mSeekBar, progressWithoutThreshold, true);
assertThat(mSeekBar.getProgress()).isEqualTo(progressWithoutThreshold);
}
// method to get the center from BalanceSeekBar for testing setMax().
private int getBalanceSeekBarCenter(BalanceSeekBar seekBar) {
return seekBar.getMax() / 2;
}
// method to get the snapThreshold from BalanceSeekBar for testing setMax().
private float getBalanceSeekBarSnapThreshold(BalanceSeekBar seekBar) {
return seekBar.getMax() * BalanceSeekBar.SNAP_TO_PERCENTAGE;
}
}

Some files were not shown because too many files have changed in this diff Show More