Snap for 5452883 from dc4f7ce282 to qt-release

Change-Id: I67ecb7b174d2e9ea6cd363d8bcc7484fff1946f9
This commit is contained in:
android-build-team Robot
2019-04-10 03:08:22 +00:00
101 changed files with 1400 additions and 3451 deletions

View File

@@ -2819,30 +2819,6 @@
</intent-filter>
</activity>
<activity
android:name="Settings$AdvancedAppsActivity"
android:exported="true"
android:label="@string/app_default_dashboard_title"
android:parentActivityName="Settings">
<intent-filter android:priority="1">
<action android:name="android.settings.MANAGE_DEFAULT_APPS_SETTINGS" />
<action android:name="android.settings.HOME_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="com.android.settings.action.SETTINGS"/>
</intent-filter>
<meta-data android:name="com.android.settings.order" android:value="-120"/>
<meta-data android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.apps"/>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.applications.DefaultAppSettings" />
<meta-data android:name="com.android.settings.summary"
android:resource="@string/summary_empty"/>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
<!-- Keep compatibility with old WebView-picker implementation -->
<activity-alias android:name=".WebViewImplementation"
android:targetActivity="Settings$WebViewAppPickerActivity"

View File

@@ -0,0 +1,46 @@
<?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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dismissal_swipe_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/homepage_card_dismissal_background">
<ImageView
android:id="@+id/dismissal_icon_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_delete"
android:layout_gravity="start|center_vertical"
android:layout_marginStart="@dimen/homepage_card_dismissal_side_margin"/>
<Space
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<ImageView
android:id="@+id/dismissal_icon_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_delete"
android:layout_gravity="end|center_vertical"
android:layout_marginEnd="@dimen/homepage_card_dismissal_side_margin"/>
</LinearLayout>

View File

@@ -21,7 +21,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/homepage_card_dismissal_background"
android:orientation="vertical">
android:orientation="vertical"
android:visibility="gone">
<TextView
android:layout_width="match_parent"

View File

@@ -21,11 +21,12 @@
android:layout_height="wrap_content"
style="@style/ContextualCardStyle">
<ViewFlipper
android:id="@+id/view_flipper"
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/dismissal_swipe_background"/>
<LinearLayout
android:id="@+id/content"
android:layout_width="match_parent"
@@ -33,6 +34,7 @@
android:paddingEnd="@dimen/homepage_card_padding_end"
android:paddingTop="@dimen/homepage_half_card_padding_top"
android:paddingBottom="@dimen/homepage_half_card_padding_bottom"
android:background="@color/contextual_card_background"
android:orientation="vertical">
<ImageView
@@ -57,5 +59,5 @@
<!--dismissal view-->
<include layout="@layout/homepage_dismissal_view"/>
</ViewFlipper>
</FrameLayout>
</com.google.android.material.card.MaterialCardView>

View File

@@ -21,21 +21,22 @@
android:layout_height="wrap_content"
style="@style/ContextualCardStyle">
<ViewFlipper
android:id="@+id/view_flipper"
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="match_parent">
<include layout="@layout/dismissal_swipe_background"/>
<androidx.slice.widget.SliceView
android:id="@+id/slice_view"
style="@style/SliceViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:importantForAccessibility="no"
style="@style/SliceViewStyle"/>
android:importantForAccessibility="no"/>
<!--dismissal view-->
<include layout="@layout/homepage_dismissal_view"/>
</ViewFlipper>
</FrameLayout>
</com.google.android.material.card.MaterialCardView>

View File

@@ -47,6 +47,8 @@
<!-- Package name and fully-qualified class name for the wallpaper picker activity. -->
<string name="config_wallpaper_picker_package" translatable="false">com.android.settings</string>
<string name="config_wallpaper_picker_class" translatable="false">com.android.settings.Settings$WallpaperSettingsActivity</string>
<!-- Fully-qualified class name for the styles & wallpaper picker activity. -->
<string name="config_styles_and_wallpaper_picker_class" translatable="false"></string>
<!-- Manufacturer backup settings to launch -->
<string name="config_backup_settings_intent" translatable="false"></string>
@@ -320,9 +322,6 @@
<!-- Whether wallpaper attribution should be shown or not. -->
<bool name="config_show_wallpaper_attribution">true</bool>
<!-- Whether default_home should be shown or not. -->
<bool name="config_show_default_home">true</bool>
<!-- Whether assist_and_voice_input should be shown or not. -->
<bool name="config_show_assist_and_voice_input">true</bool>

View File

@@ -1007,6 +1007,10 @@
<string name="skip_anyway_button_label">Skip anyway</string>
<!-- Button for going to the previous screen or step [CHAR LIMIT=20] -->
<string name="go_back_button_label">Go back</string>
<!-- Button text to skip lock screen setup [CHAR LIMIT=20] -->
<string name="skip_lock_screen_dialog_button_label">Skip</string>
<!-- Button text to cancel lock screen skip dialog [CHAR LIMIT=20] -->
<string name="cancel_lock_screen_dialog_button_label">Cancel</string>
<!-- Introduction title shown in fingerprint enrollment dialog to locate the sensor [CHAR LIMIT=29] -->
<string name="security_settings_fingerprint_enroll_find_sensor_title">Touch the sensor</string>
<!-- Message shown in fingerprint enrollment dialog to locate the sensor -->
@@ -1037,6 +1041,24 @@
<string name="setup_fingerprint_enroll_enrolling_skip_title">Skip fingerprint setup?</string>
<!-- Content of the dialog shown when the user tries to skip fingerprint setup, asking them to confirm the action [CHAR LIMIT=NONE] -->
<string name="setup_fingerprint_enroll_enrolling_skip_message">You\u2019ve chosen to use your fingerprint as one way to unlock your phone. If you skip now, you\u2019ll need to set this up later. Setup takes only a minute or so.</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set fingerprint. (tablet) [CHAR LIMIT=NONE] -->
<string name="fingerprint_lock_screen_setup_skip_dialog_text" product="tablet">Protect your tablet with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up fingerprint. Tap Cancel, then set a PIN or choose another screen lock option.</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set fingerprint. (device) [CHAR LIMIT=NONE] -->
<string name="fingerprint_lock_screen_setup_skip_dialog_text" product="device">Protect your device with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up fingerprint. Tap Cancel, then set a PIN or choose another screen lock option.</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set fingerprint. (default) [CHAR LIMIT=NONE] -->
<string name="fingerprint_lock_screen_setup_skip_dialog_text" product="default">Protect your phone with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up fingerprint. Tap Cancel, then set a PIN or choose another screen lock option.</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set face authentication. (tablet) [CHAR LIMIT=NONE] -->
<string name="face_lock_screen_setup_skip_dialog_text" product="tablet">Protect your tablet with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face authentication. Tap Cancel, then set a PIN or choose another screen lock option.</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set face authentication. (device) [CHAR LIMIT=NONE] -->
<string name="face_lock_screen_setup_skip_dialog_text" product="device">Protect your device with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face authentication. Tap Cancel, then set a PIN or choose another screen lock option.</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set face authentication. (default) [CHAR LIMIT=NONE] -->
<string name="face_lock_screen_setup_skip_dialog_text" product="default">Protect your phone with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face authentication. Tap Cancel, then set a PIN or choose another screen lock option.</string>
<!-- Title of dialog shown when the user tries to skip setting up a PIN, warning them of potential consequences of not doing so [CHAR LIMIT=30]-->
<string name="lock_screen_pin_skip_title">Skip PIN Setup?</string>
<!-- Title of dialog shown when the user tries to skip setting up a password, warning them of potential consequences of not doing so [CHAR LIMIT=30]-->
<string name="lock_screen_password_skip_title">Skip Password Setup?</string>
<!-- Title of dialog shown when the user tries to skip setting up a pattern, warning them of potential consequences of not doing so [CHAR LIMIT=30]-->
<string name="lock_screen_pattern_skip_title">Skip Pattern Setup?</string>
<!-- Button text to setup screen lock in onboard dialog [CHAR LIMIT=34] -->
<string name="security_settings_fingerprint_enroll_setup_screen_lock">Set up screen lock</string>
@@ -7160,10 +7182,8 @@
<!-- Search keyword for "Flashlight" settings [CHAR_LIMIT=NONE]-->
<string name="keywords_flashlight">Flashlight, Light, Torch</string>
<string name="keywords_change_wifi_state">wifi, wi-fi, toggle, control</string>
<string name="keywords_more_default_sms_app">text message, texting, messages, messaging, default</string>
<string name="keywords_more_mobile_networks">cellular, mobile, cell carrier, wireless, data, 4g,3g, 2g, lte</string>
<string name="keywords_wifi_calling">wifi, wi-fi, call, calling</string>
<string name="keywords_home">launcher, default, apps</string>
<string name="keywords_display">screen, touchscreen</string>
<string name="keywords_display_brightness_level">dim screen, touchscreen, battery, bright</string>
<string name="keywords_display_night_display">dim screen, night, tint, night shift, brightness, screen color, colour, color</string>
@@ -7188,8 +7208,6 @@
<string name="keywords_users">restriction, restrict, restricted</string>
<string name="keywords_keyboard_and_ime">text correction, correct, sound, vibrate, auto, language, gesture, suggest, suggestion, theme, offensive, word, type, emoji, international</string>
<string name="keywords_reset_apps">reset, preferences, default</string>
<string name="keywords_emergency_app">emergency, ice, app, default</string>
<string name="keywords_default_phone_app">phone, dialer, default</string>
<string name="keywords_all_apps">apps, download, applications, system</string>
<string name="keywords_app_permissions">apps, permissions, security</string>
<string name="keywords_default_apps">apps, default</string>
@@ -7261,15 +7279,9 @@
<!-- List of synonyms for the Default Assist and Voice input setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_assist_input">default, assistant</string>
<!-- List of synonyms for the Wallpaper picker setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_default_browser">default, default browser</string>
<!-- List of synonyms for the default payment app setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_default_payment_app">payment, default</string>
<!-- List of synonyms for the default links setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_default_links">default</string>
<!-- List of synonyms for Ambient display setting (when the screen is off), used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_ambient_display">incoming notification</string>

View File

@@ -492,6 +492,7 @@
<item name="android:paddingEnd">8dp</item>
<item name="rowStyle">@style/SliceRowStyle</item>
<item name="android:background">@color/contextual_card_background</item>
</style>
<style name="SliceRowStyle">

View File

@@ -50,6 +50,14 @@
android:key="dashboard_tile_placeholder"
android:order="10"/>
<Preference
android:key="default_apps"
android:title="@string/app_default_dashboard_title"
android:order="11"
settings:controller="com.android.settings.applications.DefaultAppsPreferenceController">
<intent android:action="android.settings.MANAGE_DEFAULT_APPS_SETTINGS"/>
</Preference>
<Preference
android:key="manage_perms"
android:title="@string/app_permissions"

View File

@@ -1,113 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="app_default_settings_screen"
android:title="@string/app_default_dashboard_title"
settings:keywords="@string/keywords_app_default">
<com.android.settingslib.widget.apppreference.AppPreference
android:key="assist_and_voice_input"
android:title="@string/assist_and_voice_input_title"
android:fragment="com.android.settings.applications.assist.ManageAssist"
settings:searchable="false"/>
<com.android.settingslib.widget.apppreference.AppPreference
android:key="default_browser"
android:title="@string/default_browser_title"
android:fragment="com.android.settings.applications.defaultapps.DefaultBrowserPicker"
settings:keywords="@string/keywords_default_browser">
<extra android:name="for_work" android:value="false" />
</com.android.settingslib.widget.apppreference.AppPreference>
<com.android.settingslib.widget.apppreference.AppPreference
android:key="default_home"
android:title="@string/home_app"
android:fragment="com.android.settings.applications.defaultapps.DefaultHomePicker"
settings:keywords="@string/keywords_home" />
<com.android.settingslib.widget.apppreference.AppPreference
android:key="default_phone_app"
android:title="@string/default_phone_title"
android:fragment="com.android.settings.applications.defaultapps.DefaultPhonePicker"
settings:keywords="@string/keywords_default_phone_app" />
<com.android.settingslib.widget.apppreference.AppPreference
android:key="default_sms_app"
android:title="@string/sms_application_title"
android:fragment="com.android.settings.applications.defaultapps.DefaultSmsPicker"
settings:keywords="@string/keywords_more_default_sms_app" />
<com.android.settingslib.widget.apppreference.AppPreference
android:key="default_payment_app"
android:title="@string/nfc_payment_settings_title"
android:summary="@string/summary_placeholder"
android:fragment="com.android.settings.nfc.PaymentSettings"
settings:keywords="@string/keywords_default_payment_app"/>
<com.android.settingslib.widget.apppreference.AppPreference
android:key="default_emergency_app"
android:title="@string/default_emergency_app"
settings:keywords="@string/keywords_emergency_app" />
<!--
<com.android.settingslib.widget.apppreference.AppPreference
android:key="default_notification_asst_app"
android:title="@string/default_notification_assistant"
android:fragment="com.android.settings.applications.defaultapps.DefaultNotificationAssistantPicker"
/>
-->
<com.android.settingslib.widget.apppreference.AppPreference
android:key="domain_urls"
android:title="@string/domain_urls_title"
android:fragment="com.android.settings.applications.managedomainurls.ManageDomainUrls"
settings:keywords="@string/keywords_default_links"/>
<!--
~ STOPSHIP(b/110557011): Remove once the new UI is ready.
-->
<Preference
android:key="roles"
android:title="@string/roles_title"
settings:controller="com.android.settings.applications.defaultapps.RolesPreferenceController" />
<com.android.settings.widget.WorkOnlyCategory
android:key="work_app_defaults"
android:title="@string/default_for_work">
<com.android.settingslib.widget.apppreference.AppPreference
android:key="work_default_browser"
android:title="@string/default_browser_title"
android:fragment="com.android.settings.applications.defaultapps.DefaultBrowserPicker"
settings:searchable="false">
<extra android:name="for_work" android:value="true" />
</com.android.settingslib.widget.apppreference.AppPreference>
<com.android.settingslib.widget.apppreference.AppPreference
android:key="work_default_phone_app"
android:title="@string/default_phone_title"
android:fragment="com.android.settings.applications.defaultapps.DefaultPhonePicker"
settings:searchable="false">
<extra android:name="for_work" android:value="true" />
</com.android.settingslib.widget.apppreference.AppPreference>
</com.android.settings.widget.WorkOnlyCategory>
</PreferenceScreen>

View File

@@ -19,13 +19,6 @@
android:title="@string/configure_notification_settings"
android:key="configure_notification_settings">
<com.android.settingslib.widget.apppreference.AppPreference
android:key="notification_assistant"
android:title="@string/notification_assistant_title"
android:summary="@string/summary_placeholder"
settings:fragment="com.android.settings.notification.NotificationAssistantPicker"
settings:controller="com.android.settings.notification.NotificationAssistantPreferenceController"/>
<SwitchPreference
android:key="asst_capability_prioritizer"
android:title="@string/asst_capability_prioritizer_title"

View File

@@ -1,20 +0,0 @@
<?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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/default_assist_title" />

View File

@@ -1,20 +0,0 @@
<?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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/default_browser_title" />

View File

@@ -1,20 +0,0 @@
<?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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/default_emergency_app" />

View File

@@ -1,20 +0,0 @@
<?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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/home_app" />

View File

@@ -1,20 +0,0 @@
<?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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/default_phone_title" />

View File

@@ -1,20 +0,0 @@
<?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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/sms_application_title" />

View File

@@ -53,9 +53,6 @@
settings:keywords="@string/keywords_display_wallpaper"
settings:useAdminDisabledSummary="true"
settings:controller="com.android.settings.display.WallpaperPreferenceController">
<intent
android:targetPackage="@string/config_wallpaper_picker_package"
android:targetClass="@string/config_wallpaper_picker_class" />
</com.android.settingslib.RestrictedPreference>

View File

@@ -65,6 +65,13 @@
android:value="com.android.settings.Settings$WriteSettingsActivity" />
</Preference>
<com.android.settingslib.widget.apppreference.AppPreference
android:key="notification_assistant"
android:title="@string/notification_assistant_title"
android:summary="@string/summary_placeholder"
settings:fragment="com.android.settings.notification.NotificationAssistantPicker"
settings:controller="com.android.settings.notification.NotificationAssistantPreferenceController"/>
<Preference
android:key="notification_access"
android:title="@string/manage_notification_access_title"
@@ -84,6 +91,13 @@
android:fragment="com.android.settings.applications.specialaccess.premiumsms.PremiumSmsAccess"
settings:controller="com.android.settings.applications.specialaccess.premiumsms.PremiumSmsController" />
<Preference
android:key="default_payment_app"
android:title="@string/nfc_payment_settings_title"
android:fragment="com.android.settings.nfc.PaymentSettings"
settings:keywords="@string/keywords_default_payment_app"
settings:controller="com.android.settings.applications.specialaccess.DefaultPaymentSettingsPreferenceController" />
<Preference
android:key="data_saver"
android:title="@string/unrestricted_data_saver"

View File

@@ -36,49 +36,45 @@
android:key="buttons"
android:selectable="false" />
<!-- General Details Category -->
<PreferenceCategory
android:key="general_details_category" >
<Preference
android:key="signal_strength"
android:title="@string/wifi_signal"
android:selectable="false"/>
<!-- General Details Preferences -->
<Preference
android:key="signal_strength"
android:title="@string/wifi_signal"
android:selectable="false"
settings:allowDividerAbove="true"/>
<Preference
android:key="frequency"
android:icon="@drawable/ic_frequency_antenna"
android:title="@string/wifi_frequency"
android:selectable="false"/>
<Preference
android:key="frequency"
android:icon="@drawable/ic_frequency_antenna"
android:title="@string/wifi_frequency"
android:selectable="false"/>
<Preference
android:key="security"
android:icon="@drawable/ic_security_lock_24dp"
android:title="@string/wifi_security"
android:selectable="false"/>
<Preference
android:key="security"
android:icon="@drawable/ic_security_lock_24dp"
android:title="@string/wifi_security"
android:selectable="false"/>
<DropDownPreference
android:key="metered"
android:icon="@drawable/ic_attach_money_black_24dp"
android:title="@string/data_usage_metered_yes"
android:entries="@array/wifi_metered_entries"
android:entryValues="@array/wifi_metered_values"/>
<DropDownPreference
android:key="metered"
android:icon="@drawable/ic_attach_money_black_24dp"
android:title="@string/data_usage_metered_yes"
android:entries="@array/wifi_metered_entries"
android:entryValues="@array/wifi_metered_values"/>
<DropDownPreference
android:key="privacy"
android:icon="@drawable/ic_wifi_privacy_24dp"
android:title="@string/wifi_privacy_settings"
android:entries="@array/wifi_privacy_entries"
android:entryValues="@array/wifi_privacy_values"/>
</PreferenceCategory>
<DropDownPreference
android:key="privacy"
android:icon="@drawable/ic_wifi_privacy_24dp"
android:title="@string/wifi_privacy_settings"
android:entries="@array/wifi_privacy_entries"
android:entryValues="@array/wifi_privacy_values"/>
<!-- Add device Category -->
<PreferenceCategory
android:key="add_device_category" >
<Preference
android:key="add_device_to_network"
android:title="@string/wifi_dpp_add_device"
android:summary="@string/wifi_dpp_connect_network_using_qr_code"/>
</PreferenceCategory>
<!-- Add device Preference -->
<Preference
android:key="add_device_to_network"
android:title="@string/wifi_dpp_add_device"
android:summary="@string/wifi_dpp_connect_network_using_qr_code"
settings:allowDividerAbove="true"/>
<!-- Network Details -->
<PreferenceCategory

View File

@@ -136,7 +136,6 @@ public class Settings extends SettingsActivity {
public static class ChangeWifiStateActivity extends SettingsActivity { /* empty */ }
public static class AppDrawOverlaySettingsActivity extends SettingsActivity { /* empty */ }
public static class AppWriteSettingsActivity extends SettingsActivity { /* empty */ }
public static class AdvancedAppsActivity extends SettingsActivity { /* empty */ }
public static class ManageExternalSourcesActivity extends SettingsActivity {/* empty */ }
public static class ManageAppExternalSourcesActivity extends SettingsActivity { /* empty */ }

View File

@@ -93,8 +93,6 @@ public class AppStateInstallAppsBridge extends AppStateBaseBridge {
final InstallAppsState appState = new InstallAppsState();
appState.permissionRequested = hasRequestedAppOpPermission(
Manifest.permission.REQUEST_INSTALL_PACKAGES, packageName);
appState.permissionGranted = hasPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES,
uid);
appState.appOpMode = getAppOpMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, uid,
packageName);
return appState;
@@ -105,7 +103,6 @@ public class AppStateInstallAppsBridge extends AppStateBaseBridge {
*/
public static class InstallAppsState {
boolean permissionRequested;
boolean permissionGranted;
int appOpMode;
public InstallAppsState() {
@@ -113,11 +110,7 @@ public class AppStateInstallAppsBridge extends AppStateBaseBridge {
}
public boolean canInstallApps() {
if (appOpMode == AppOpsManager.MODE_DEFAULT) {
return permissionGranted;
} else {
return appOpMode == AppOpsManager.MODE_ALLOWED;
}
return appOpMode == AppOpsManager.MODE_ALLOWED;
}
public boolean isPotentialAppSource() {
@@ -126,8 +119,8 @@ public class AppStateInstallAppsBridge extends AppStateBaseBridge {
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[permissionGranted: " + permissionGranted);
sb.append(", permissionRequested: " + permissionRequested);
StringBuilder sb = new StringBuilder();
sb.append("[permissionRequested: " + permissionRequested);
sb.append(", appOpMode: " + appOpMode);
sb.append("]");
return sb.toString();

View File

@@ -1,158 +0,0 @@
/*
* 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.applications;
import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.icu.text.ListFormatter;
import android.provider.SearchIndexableResource;
import android.text.TextUtils;
import com.android.settings.R;
import com.android.settings.applications.assist.DefaultAssistPreferenceController;
import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController;
import com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController;
import com.android.settings.applications.defaultapps.DefaultHomePreferenceController;
import com.android.settings.applications.defaultapps.DefaultPaymentSettingsPreferenceController;
import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController;
import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController;
import com.android.settings.applications.defaultapps.DefaultWorkBrowserPreferenceController;
import com.android.settings.applications.defaultapps.DefaultWorkPhonePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.widget.PreferenceCategoryController;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@SearchIndexable
public class DefaultAppSettings extends DashboardFragment {
static final String TAG = "DefaultAppSettings";
private static final String KEY_DEFAULT_WORK_CATEGORY = "work_app_defaults";
private static final String KEY_ASSIST_VOICE_INPUT = "assist_and_voice_input";
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.app_default_settings;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
}
@Override
public int getMetricsCategory() {
return SettingsEnums.APPLICATIONS_ADVANCED;
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
final List<AbstractPreferenceController> workControllers = new ArrayList<>();
workControllers.add(new DefaultWorkPhonePreferenceController(context));
workControllers.add(new DefaultWorkBrowserPreferenceController(context));
controllers.addAll(workControllers);
controllers.add(new PreferenceCategoryController(
context, KEY_DEFAULT_WORK_CATEGORY).setChildren(workControllers));
controllers.add(new DefaultAssistPreferenceController(context, KEY_ASSIST_VOICE_INPUT,
false /* showSetting */));
controllers.add(new DefaultBrowserPreferenceController(context));
controllers.add(new DefaultPhonePreferenceController(context));
controllers.add(new DefaultSmsPreferenceController(context));
controllers.add(new DefaultEmergencyPreferenceController(context));
controllers.add(new DefaultHomePreferenceController(context));
controllers.add(new DefaultPaymentSettingsPreferenceController(context));
return controllers;
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.app_default_settings;
return Arrays.asList(sir);
}
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
return buildPreferenceControllers(context);
}
};
static class SummaryProvider implements SummaryLoader.SummaryProvider {
private final Context mContext;
private final SummaryLoader mSummaryLoader;
private final DefaultSmsPreferenceController mDefaultSmsPreferenceController;
private final DefaultBrowserPreferenceController mDefaultBrowserPreferenceController;
private final DefaultPhonePreferenceController mDefaultPhonePreferenceController;
public SummaryProvider(Context context, SummaryLoader summaryLoader) {
mContext = context;
mSummaryLoader = summaryLoader;
mDefaultSmsPreferenceController = new DefaultSmsPreferenceController(mContext);
mDefaultBrowserPreferenceController = new DefaultBrowserPreferenceController(mContext);
mDefaultPhonePreferenceController = new DefaultPhonePreferenceController(mContext);
}
@Override
public void setListening(boolean listening) {
if (!listening) {
return;
}
final List<CharSequence> summaries = new ArrayList<>();
if(!TextUtils.isEmpty(mDefaultBrowserPreferenceController.getDefaultAppLabel())) {
summaries.add(mDefaultBrowserPreferenceController.getDefaultAppLabel());
}
if(!TextUtils.isEmpty(mDefaultPhonePreferenceController.getDefaultAppLabel())) {
summaries.add(mDefaultPhonePreferenceController.getDefaultAppLabel());
}
if(!TextUtils.isEmpty(mDefaultSmsPreferenceController.getDefaultAppLabel())) {
summaries.add(mDefaultSmsPreferenceController.getDefaultAppLabel());
}
CharSequence summary = ListFormatter.getInstance().format(summaries);
if (!TextUtils.isEmpty(summary)) {
mSummaryLoader.setSummary(this, summary);
}
}
}
public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY =
new SummaryLoader.SummaryProviderFactory() {
@Override
public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
SummaryLoader summaryLoader) {
return new DefaultAppSettings.SummaryProvider(activity, summaryLoader);
}
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 The Android Open Source Project
* 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.
@@ -11,66 +11,38 @@
* 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.
* limitations under the License
*/
package com.android.settings.applications.defaultapps;
package com.android.settings.applications;
import android.app.role.RoleManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.icu.text.ListFormatter;
import android.provider.Settings;
import android.text.TextUtils;
import androidx.preference.Preference;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.applications.AppUtils;
import java.util.ArrayList;
import java.util.List;
/**
* STOPSHIP(b/110557011): Remove once the new UI is ready.
*/
public class RolesPreferenceController extends BasePreferenceController {
public class DefaultAppsPreferenceController extends BasePreferenceController {
private final PackageManager mPackageManager;
private final RoleManager mRoleManager;
private final Intent mIntent;
public RolesPreferenceController(Context context, String preferenceKey) {
public DefaultAppsPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mPackageManager = context.getPackageManager();
mRoleManager = context.getSystemService(RoleManager.class);
final String packageName = mPackageManager.getPermissionControllerPackageName();
if (packageName != null) {
mIntent = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
.setPackage(packageName);
} else {
mIntent = null;
}
}
@Override
public int getAvailabilityStatus() {
return mIntent != null ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (TextUtils.equals(preference.getKey(), mPreferenceKey)) {
if (mIntent != null) {
mContext.startActivity(mIntent);
}
return true;
}
return false;
return AVAILABLE;
}
@Override

View File

@@ -112,7 +112,8 @@ public class AppInfoDashboardFragment extends DashboardFragment
private UserManager mUserManager;
private PackageManager mPm;
private boolean mFinishing;
@VisibleForTesting
boolean mFinishing;
private boolean mListeningToPackageRemove;
@@ -544,7 +545,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
@VisibleForTesting
void retrieveAppEntry() {
final Activity activity = getActivity();
if (activity == null) {
if (activity == null || mFinishing) {
return;
}
if (mState == null) {
@@ -650,7 +651,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
|| TextUtils.equals(mAppEntry.info.packageName, packageName)) {
onPackageRemoved();
} else if (mAppEntry.info.isResourceOverlay()
&& TextUtils.equals(mPackageInfo.overlayTarget, packageName)) {
&& TextUtils.equals(mPackageInfo.overlayTarget, packageName)) {
refreshUi();
}
}

View File

@@ -1,74 +0,0 @@
/*
* 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.applications.defaultapps;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import com.android.settings.R;
import com.android.settingslib.applications.DefaultAppInfo;
import java.util.ArrayList;
import java.util.List;
/**
* Fragment for choosing default browser.
*/
public class DefaultBrowserPicker extends DefaultAppPickerFragment {
@Override
protected int getPreferenceScreenResId() {
return R.xml.default_browser_settings;
}
@Override
public int getMetricsCategory() {
return SettingsEnums.DEFAULT_BROWSER_PICKER;
}
@Override
protected String getDefaultKey() {
return mPm.getDefaultBrowserPackageNameAsUser(mUserId);
}
@Override
protected boolean setDefaultKey(String packageName) {
return mPm.setDefaultBrowserPackageNameAsUser(packageName, mUserId);
}
@Override
protected List<DefaultAppInfo> getCandidates() {
final List<DefaultAppInfo> candidates = new ArrayList<>();
final Context context = getContext();
// Resolve that intent and check that the handleAllWebDataURI boolean is set
final List<ResolveInfo> list =
DefaultBrowserPreferenceController.getCandidates(mPm, mUserId);
for (ResolveInfo info : list) {
try {
candidates.add(new DefaultAppInfo(context, mPm, mUserId,
mPm.getApplicationInfoAsUser(info.activityInfo.packageName, 0, mUserId)));
} catch (PackageManager.NameNotFoundException e) {
// Skip unknown packages.
}
}
return candidates;
}
}

View File

@@ -1,198 +0,0 @@
/*
* 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.applications.defaultapps;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.IconDrawableFactory;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import com.android.settingslib.applications.DefaultAppInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class DefaultBrowserPreferenceController extends DefaultAppPreferenceController {
private static final String TAG = "BrowserPrefCtrl";
static final Intent BROWSE_PROBE = new Intent()
.setAction(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(Uri.parse("http:"))
.addFlags(Intent.FLAG_IGNORE_EPHEMERAL);
public DefaultBrowserPreferenceController(Context context) {
super(context);
}
@Override
public boolean isAvailable() {
final List<ResolveInfo> candidates = getCandidates(mPackageManager, mUserId);
return candidates != null && !candidates.isEmpty();
}
@Override
public String getPreferenceKey() {
return "default_browser";
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
final CharSequence defaultAppLabel = getDefaultAppLabel();
if (!TextUtils.isEmpty(defaultAppLabel)) {
preference.setSummary(defaultAppLabel);
}
}
@Override
protected DefaultAppInfo getDefaultAppInfo() {
try {
final String packageName = mPackageManager.getDefaultBrowserPackageNameAsUser(mUserId);
Log.d(TAG, "Get default browser package: " + packageName);
return new DefaultAppInfo(mContext, mPackageManager, mUserId,
mPackageManager.getApplicationInfoAsUser(packageName, 0, mUserId));
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
@Override
public CharSequence getDefaultAppLabel() {
if (!isAvailable()) {
return null;
}
final DefaultAppInfo defaultApp = getDefaultAppInfo();
final CharSequence defaultAppLabel = defaultApp != null ? defaultApp.loadLabel() : null;
if (!TextUtils.isEmpty(defaultAppLabel)) {
return defaultAppLabel;
}
return getOnlyAppLabel();
}
@Override
public Drawable getDefaultAppIcon() {
if (!isAvailable()) {
return null;
}
final DefaultAppInfo defaultApp = getDefaultAppInfo();
if (defaultApp != null) {
return defaultApp.loadIcon();
}
return getOnlyAppIcon();
}
static List<ResolveInfo> getCandidates(PackageManager packageManager, int userId) {
final List<ResolveInfo> candidates = new ArrayList<>();
// Resolve that intent and check that the handleAllWebDataURI boolean is set
final List<ResolveInfo> list = packageManager.queryIntentActivitiesAsUser(
BROWSE_PROBE, PackageManager.MATCH_ALL, userId);
if (list != null) {
final Set<String> addedPackages = new ArraySet<>();
for (ResolveInfo info : list) {
if (!info.handleAllWebDataURI || info.activityInfo == null
|| !info.activityInfo.enabled
|| !info.activityInfo.applicationInfo.enabled) {
continue;
}
final String packageName = info.activityInfo.packageName;
if (addedPackages.contains(packageName)) {
continue;
}
candidates.add(info);
addedPackages.add(packageName);
}
}
return candidates;
}
private String getOnlyAppLabel() {
// Resolve that intent and check that the handleAllWebDataURI boolean is set
final List<ResolveInfo> list = getCandidates(mPackageManager, mUserId);
if (list != null && list.size() == 1) {
final ResolveInfo info = list.get(0);
final String label = info.loadLabel(mPackageManager).toString();
final ComponentInfo cn = info.getComponentInfo();
final String packageName = cn == null ? null : cn.packageName;
Log.d(TAG, "Getting label for the only browser app: " + packageName + label);
return label;
}
return null;
}
@VisibleForTesting
Drawable getOnlyAppIcon() {
final List<ResolveInfo> list = getCandidates(mPackageManager, mUserId);
if (list != null && list.size() == 1) {
final ResolveInfo info = list.get(0);
final ComponentInfo cn = info.getComponentInfo();
final String packageName = cn == null ? null : cn.packageName;
if (TextUtils.isEmpty(packageName)) {
return null;
}
final ApplicationInfo appInfo;
try {
appInfo = mPackageManager.getApplicationInfoAsUser(packageName, 0, mUserId);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Error getting app info for " + packageName);
return null;
}
Log.d(TAG, "Getting icon for the only browser app: " + packageName);
final IconDrawableFactory iconFactory = IconDrawableFactory.newInstance(mContext);
return iconFactory.getBadgedIcon(cn, appInfo, mUserId);
}
return null;
}
/**
* Whether or not the pkg contains browser capability
*/
public static boolean hasBrowserPreference(String pkg, Context context, int userId) {
final Intent intent = new Intent(BROWSE_PROBE);
intent.setPackage(pkg);
final List<ResolveInfo> resolveInfos = context.getPackageManager()
.queryIntentActivitiesAsUser(intent, 0 /* flags */, userId);
return resolveInfos != null && resolveInfos.size() != 0;
}
/**
* Whether or not the pkg is the default browser
*/
public boolean isBrowserDefault(String pkg, int userId) {
final String defaultPackage = mPackageManager.getDefaultBrowserPackageNameAsUser(userId);
if (defaultPackage != null) {
return defaultPackage.equals(pkg);
}
final List<ResolveInfo> list = getCandidates(mPackageManager, userId);
// There is only 1 app, it must be the default browser.
return list != null && list.size() == 1;
}
}

View File

@@ -1,115 +0,0 @@
/*
* 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.applications.defaultapps;
import android.app.role.RoleManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.AsyncTask;
import android.os.Process;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.util.CollectionUtils;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.applications.DefaultAppInfo;
import com.android.settingslib.widget.CandidateInfo;
import java.util.ArrayList;
import java.util.List;
public class DefaultEmergencyPicker extends DefaultAppPickerFragment {
private static final String TAG = "DefaultEmergencyPicker";
@Override
public int getMetricsCategory() {
return SettingsEnums.DEFAULT_EMERGENCY_APP_PICKER;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.default_emergency_settings;
}
@Override
protected List<DefaultAppInfo> getCandidates() {
final List<DefaultAppInfo> candidates = new ArrayList<>();
final List<ResolveInfo> infos = mPm.queryIntentActivities(
DefaultEmergencyPreferenceController.QUERY_INTENT, 0);
PackageInfo bestMatch = null;
final Context context = getContext();
for (ResolveInfo info : infos) {
try {
final PackageInfo packageInfo =
mPm.getPackageInfo(info.activityInfo.packageName, 0);
final ApplicationInfo appInfo = packageInfo.applicationInfo;
candidates.add(new DefaultAppInfo(context, mPm, mUserId, appInfo));
// Get earliest installed system app.
if (isSystemApp(appInfo) && (bestMatch == null ||
bestMatch.firstInstallTime > packageInfo.firstInstallTime)) {
bestMatch = packageInfo;
}
} catch (PackageManager.NameNotFoundException e) {
// Skip unknown packages.
}
if (bestMatch != null) {
final String defaultKey = getDefaultKey();
if (TextUtils.isEmpty(defaultKey)) {
setDefaultKey(bestMatch.packageName);
}
}
}
return candidates;
}
@Override
protected String getConfirmationMessage(CandidateInfo info) {
return Utils.isPackageDirectBootAware(getContext(), info.getKey()) ? null
: getContext().getString(R.string.direct_boot_unaware_dialog_message);
}
@Override
protected String getDefaultKey() {
RoleManager roleManager = getContext().getSystemService(RoleManager.class);
return CollectionUtils.firstOrNull(roleManager.getRoleHolders(RoleManager.ROLE_EMERGENCY));
}
@Override
protected boolean setDefaultKey(String key) {
final String previousValue = getDefaultKey();
if (!TextUtils.isEmpty(key) && !TextUtils.equals(key, previousValue)) {
getContext().getSystemService(RoleManager.class).addRoleHolderAsUser(
RoleManager.ROLE_EMERGENCY, key, 0, Process.myUserHandle(),
AsyncTask.THREAD_POOL_EXECUTOR, successful -> {
if (!successful) {
Log.e(TAG, "Failed to set emergency default app.");
}
});
return true;
}
return false;
}
private boolean isSystemApp(ApplicationInfo info) {
return info != null && (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
}

View File

@@ -1,79 +0,0 @@
/*
* 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.applications.defaultapps;
import android.app.role.RoleManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import com.android.internal.util.CollectionUtils;
import com.android.settingslib.applications.DefaultAppInfo;
import java.util.List;
public class DefaultEmergencyPreferenceController extends DefaultAppPreferenceController {
private static final boolean DEFAULT_EMERGENCY_APP_IS_CONFIGURABLE = false;
public static final Intent QUERY_INTENT = new Intent(
TelephonyManager.ACTION_EMERGENCY_ASSISTANCE);
public DefaultEmergencyPreferenceController(Context context) {
super(context);
}
@Override
public boolean isAvailable() {
return DEFAULT_EMERGENCY_APP_IS_CONFIGURABLE
&& isCapable()
&& mPackageManager.resolveActivity(QUERY_INTENT, 0) != null;
}
@Override
public String getPreferenceKey() {
return "default_emergency_app";
}
@Override
protected DefaultAppInfo getDefaultAppInfo() {
return null;
}
private boolean isCapable() {
return TelephonyManager.EMERGENCY_ASSISTANCE_ENABLED
&& mContext.getResources().getBoolean(
com.android.internal.R.bool.config_voice_capable);
}
public static boolean hasEmergencyPreference(String pkg, Context context) {
Intent i = new Intent(QUERY_INTENT);
i.setPackage(pkg);
final List<ResolveInfo> resolveInfos =
context.getPackageManager().queryIntentActivities(i, 0);
return resolveInfos != null && resolveInfos.size() != 0;
}
public static boolean isEmergencyDefault(String pkg, Context context) {
String defaultPackage = CollectionUtils.firstOrNull(
context.getSystemService(RoleManager.class)
.getRoleHolders(RoleManager.ROLE_EMERGENCY));
return defaultPackage != null && defaultPackage.equals(pkg);
}
}

View File

@@ -1,152 +0,0 @@
/*
* 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.applications.defaultapps;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.os.Build;
import android.text.TextUtils;
import com.android.settings.R;
import com.android.settingslib.applications.DefaultAppInfo;
import java.util.ArrayList;
import java.util.List;
public class DefaultHomePicker extends DefaultAppPickerFragment {
private String mPackageName;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mPackageName = context.getPackageName();
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.default_home_settings;
}
@Override
public int getMetricsCategory() {
return SettingsEnums.DEFAULT_HOME_PICKER;
}
@Override
protected List<DefaultAppInfo> getCandidates() {
final boolean mustSupportManagedProfile = hasManagedProfile();
final List<DefaultAppInfo> candidates = new ArrayList<>();
final List<ResolveInfo> homeActivities = new ArrayList<>();
final Context context = getContext();
mPm.getHomeActivities(homeActivities);
for (ResolveInfo resolveInfo : homeActivities) {
final ActivityInfo info = resolveInfo.activityInfo;
final ComponentName activityName = new ComponentName(info.packageName, info.name);
if (info.packageName.equals(mPackageName)) {
continue;
}
final String summary;
boolean enabled = true;
if (mustSupportManagedProfile && !launcherHasManagedProfilesFeature(resolveInfo)) {
summary = getContext().getString(R.string.home_work_profile_not_supported);
enabled = false;
} else {
summary = null;
}
final DefaultAppInfo candidate =
new DefaultAppInfo(context, mPm, mUserId, activityName, summary, enabled);
candidates.add(candidate);
}
return candidates;
}
@Override
protected String getDefaultKey() {
final ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
final ComponentName currentDefaultHome = mPm.getHomeActivities(homeActivities);
if (currentDefaultHome != null) {
return currentDefaultHome.flattenToString();
}
return null;
}
@Override
protected boolean setDefaultKey(String key) {
if (!TextUtils.isEmpty(key)) {
final ComponentName component = ComponentName.unflattenFromString(key);
final List<ResolveInfo> homeActivities = new ArrayList<>();
mPm.getHomeActivities(homeActivities);
final List<ComponentName> allComponents = new ArrayList<>();
for (ResolveInfo info : homeActivities) {
final ActivityInfo appInfo = info.activityInfo;
ComponentName activityName = new ComponentName(appInfo.packageName, appInfo.name);
allComponents.add(activityName);
}
mPm.replacePreferredActivity(
DefaultHomePreferenceController.HOME_FILTER,
IntentFilter.MATCH_CATEGORY_EMPTY,
allComponents.toArray(new ComponentName[0]),
component);
// Launch the new Home app so the change is immediately visible even if
// the Home button is not pressed.
final Context context = getContext();
Intent i = new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_HOME);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
return true;
}
return false;
}
private boolean hasManagedProfile() {
final Context context = getContext();
List<UserInfo> profiles = mUserManager.getProfiles(context.getUserId());
for (UserInfo userInfo : profiles) {
if (userInfo.isManagedProfile()) {
return true;
}
}
return false;
}
private boolean launcherHasManagedProfilesFeature(ResolveInfo resolveInfo) {
try {
ApplicationInfo appInfo = mPm.getApplicationInfo(resolveInfo.activityInfo.packageName,
0 /* default flags */);
return versionNumberAtLeastL(appInfo.targetSdkVersion);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
private boolean versionNumberAtLeastL(int versionNumber) {
return versionNumber >= Build.VERSION_CODES.LOLLIPOP;
}
}

View File

@@ -1,129 +0,0 @@
/*
* 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.applications.defaultapps;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import com.android.settings.R;
import com.android.settingslib.applications.DefaultAppInfo;
import java.util.ArrayList;
import java.util.List;
public class DefaultHomePreferenceController extends DefaultAppPreferenceController {
static final IntentFilter HOME_FILTER;
private final String mPackageName;
static {
HOME_FILTER = new IntentFilter(Intent.ACTION_MAIN);
HOME_FILTER.addCategory(Intent.CATEGORY_HOME);
HOME_FILTER.addCategory(Intent.CATEGORY_DEFAULT);
}
public DefaultHomePreferenceController(Context context) {
super(context);
mPackageName = mContext.getPackageName();
}
@Override
public String getPreferenceKey() {
return "default_home";
}
@Override
public boolean isAvailable() {
return mContext.getResources().getBoolean(R.bool.config_show_default_home);
}
@Override
protected DefaultAppInfo getDefaultAppInfo() {
final ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
final ComponentName currentDefaultHome = mPackageManager.getHomeActivities(homeActivities);
if (currentDefaultHome != null) {
return new DefaultAppInfo(mContext, mPackageManager, mUserId, currentDefaultHome);
}
final ActivityInfo onlyAppInfo = getOnlyAppInfo(homeActivities);
if (onlyAppInfo != null) {
return new DefaultAppInfo(mContext, mPackageManager, mUserId,
onlyAppInfo.getComponentName());
}
return null;
}
private ActivityInfo getOnlyAppInfo(List<ResolveInfo> homeActivities) {
final List<ActivityInfo> appLabels = new ArrayList<>();
mPackageManager.getHomeActivities(homeActivities);
for (ResolveInfo candidate : homeActivities) {
final ActivityInfo info = candidate.activityInfo;
if (info.packageName.equals(mPackageName)) {
continue;
}
appLabels.add(info);
}
return appLabels.size() == 1
? appLabels.get(0)
: null;
}
@Override
protected Intent getSettingIntent(DefaultAppInfo info) {
if (info == null) {
return null;
}
final String packageName;
if (info.componentName != null) {
packageName = info.componentName.getPackageName();
} else if (info.packageItemInfo != null) {
packageName = info.packageItemInfo.packageName;
} else {
return null;
}
Intent intent = new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
.setPackage(packageName)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return intent.resolveActivity(mPackageManager) != null ? intent : null;
}
public static boolean hasHomePreference(String pkg, Context context) {
ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
PackageManager pm = context.getPackageManager();
pm.getHomeActivities(homeActivities);
for (int i = 0; i < homeActivities.size(); i++) {
if (homeActivities.get(i).activityInfo.packageName.equals(pkg)) {
return true;
}
}
return false;
}
public static boolean isHomeDefault(String pkg, PackageManager pm) {
final ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
ComponentName def = pm.getHomeActivities(homeActivities);
return def == null || def.getPackageName().equals(pkg);
}
}

View File

@@ -1,80 +0,0 @@
/*
* 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.applications.defaultapps;
import android.content.Context;
import android.content.pm.PackageManager;
import android.nfc.NfcAdapter;
import android.os.UserManager;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.nfc.PaymentBackend;
import com.android.settingslib.core.AbstractPreferenceController;
public class DefaultPaymentSettingsPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin {
private final NfcAdapter mNfcAdapter;
private final PackageManager mPackageManager;
private final UserManager mUserManager;
private PaymentBackend mPaymentBackend;
public DefaultPaymentSettingsPreferenceController(Context context) {
super(context);
mPackageManager = context.getPackageManager();
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext);
}
@Override
public boolean isAvailable() {
return mPackageManager.hasSystemFeature(PackageManager.FEATURE_NFC)
&& mPackageManager.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
&& mUserManager.isAdminUser()
&& mNfcAdapter != null
&& mNfcAdapter.isEnabled();
}
@Override
public void updateState(Preference preference) {
if (mPaymentBackend == null) {
if (mNfcAdapter != null) {
mPaymentBackend = new PaymentBackend(mContext);
} else {
mPaymentBackend = null;
}
}
if (mPaymentBackend == null) {
return;
}
mPaymentBackend.refresh();
final PaymentBackend.PaymentAppInfo app = mPaymentBackend.getDefaultApp();
if (app != null) {
preference.setSummary(app.label);
} else {
preference.setSummary(R.string.app_list_preference_none);
}
}
@Override
public String getPreferenceKey() {
return "default_payment_app";
}
}

View File

@@ -1,111 +0,0 @@
/*
* 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.applications.defaultapps;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.pm.PackageManager;
import android.telecom.DefaultDialerManager;
import android.telecom.TelecomManager;
import android.text.TextUtils;
import com.android.settings.R;
import com.android.settingslib.applications.DefaultAppInfo;
import java.util.ArrayList;
import java.util.List;
public class DefaultPhonePicker extends DefaultAppPickerFragment {
private DefaultKeyUpdater mDefaultKeyUpdater;
@Override
public int getMetricsCategory() {
return SettingsEnums.DEFAULT_PHONE_PICKER;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mDefaultKeyUpdater = new DefaultKeyUpdater(
(TelecomManager) context.getSystemService(Context.TELECOM_SERVICE));
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.default_phone_settings;
}
@Override
protected List<DefaultAppInfo> getCandidates() {
final List<DefaultAppInfo> candidates = new ArrayList<>();
final List<String> dialerPackages =
DefaultDialerManager.getInstalledDialerApplications(getContext(), mUserId);
final Context context = getContext();
for (String packageName : dialerPackages) {
try {
candidates.add(new DefaultAppInfo(context, mPm, mUserId,
mPm.getApplicationInfoAsUser(packageName, 0, mUserId)));
} catch (PackageManager.NameNotFoundException e) {
// Skip unknown packages.
}
}
return candidates;
}
@Override
protected String getDefaultKey() {
return mDefaultKeyUpdater.getDefaultDialerApplication(getContext(), mUserId);
}
@Override
protected String getSystemDefaultKey() {
return mDefaultKeyUpdater.getSystemDialerPackage();
}
@Override
protected boolean setDefaultKey(String key) {
if (!TextUtils.isEmpty(key) && !TextUtils.equals(key, getDefaultKey())) {
mBatteryUtils.clearForceAppStandby(key);
return mDefaultKeyUpdater.setDefaultDialerApplication(getContext(), key, mUserId);
}
return false;
}
/**
* Wrapper class to handle default phone app update.
*/
static class DefaultKeyUpdater {
private final TelecomManager mTelecomManager;
public DefaultKeyUpdater(TelecomManager telecomManager) {
mTelecomManager = telecomManager;
}
public String getSystemDialerPackage() {
return mTelecomManager.getSystemDialerPackage();
}
public String getDefaultDialerApplication(Context context, int uid) {
return DefaultDialerManager.getDefaultDialerApplication(context, uid);
}
public boolean setDefaultDialerApplication(Context context, String key, int uid) {
return DefaultDialerManager.setDefaultDialerApplication(context, key, uid);
}
}
}

View File

@@ -1,85 +0,0 @@
/*
* 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.applications.defaultapps;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.telecom.DefaultDialerManager;
import android.telephony.TelephonyManager;
import com.android.settingslib.applications.DefaultAppInfo;
import java.util.List;
public class DefaultPhonePreferenceController extends DefaultAppPreferenceController {
public DefaultPhonePreferenceController(Context context) {
super(context);
}
@Override
public boolean isAvailable() {
final TelephonyManager tm =
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (!tm.isVoiceCapable()) {
return false;
}
final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
final boolean hasUserRestriction =
um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
if (hasUserRestriction) {
return false;
}
final List<String> candidates = getCandidates();
return candidates != null && !candidates.isEmpty();
}
@Override
public String getPreferenceKey() {
return "default_phone_app";
}
@Override
protected DefaultAppInfo getDefaultAppInfo() {
try {
return new DefaultAppInfo(mContext, mPackageManager, mUserId,
mPackageManager.getApplicationInfo(
DefaultDialerManager.getDefaultDialerApplication(mContext, mUserId), 0));
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
private List<String> getCandidates() {
return DefaultDialerManager.getInstalledDialerApplications(mContext, mUserId);
}
public static boolean hasPhonePreference(String pkg, Context context) {
List<String> dialerPackages =
DefaultDialerManager.getInstalledDialerApplications(context, UserHandle.myUserId());
return dialerPackages.contains(pkg);
}
public static boolean isPhoneDefault(String pkg, Context context) {
String def = DefaultDialerManager.getDefaultDialerApplication(context,
UserHandle.myUserId());
return def != null && def.equals(pkg);
}
}

View File

@@ -1,106 +0,0 @@
/*
* 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.applications.defaultapps;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import com.android.internal.telephony.SmsApplication;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.applications.DefaultAppInfo;
import com.android.settingslib.widget.CandidateInfo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class DefaultSmsPicker extends DefaultAppPickerFragment {
private DefaultKeyUpdater mDefaultKeyUpdater = new DefaultKeyUpdater();
@Override
public int getMetricsCategory() {
return SettingsEnums.DEFAULT_SMS_PICKER;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.default_sms_settings;
}
@Override
protected List<DefaultAppInfo> getCandidates() {
final Context context = getContext();
final Collection<SmsApplication.SmsApplicationData> smsApplications =
SmsApplication.getApplicationCollection(context);
final List<DefaultAppInfo> candidates = new ArrayList<>(smsApplications.size());
for (SmsApplication.SmsApplicationData smsApplicationData : smsApplications) {
try {
candidates.add(new DefaultAppInfo(context, mPm, mUserId,
mPm.getApplicationInfoAsUser(smsApplicationData.mPackageName, 0, mUserId)));
} catch (PackageManager.NameNotFoundException e) {
// Skip unknown packages.
}
}
return candidates;
}
@Override
protected String getDefaultKey() {
return mDefaultKeyUpdater.getDefaultApplication(getContext());
}
@Override
protected boolean setDefaultKey(String key) {
if (!TextUtils.isEmpty(key) && !TextUtils.equals(key, getDefaultKey())) {
mDefaultKeyUpdater.setDefaultApplication(getContext(), key);
mBatteryUtils.clearForceAppStandby(key);
return true;
}
return false;
}
@Override
protected String getConfirmationMessage(CandidateInfo info) {
return Utils.isPackageDirectBootAware(getContext(), info.getKey()) ? null
: getContext().getString(R.string.direct_boot_unaware_dialog_message);
}
/**
* Wrapper class to handle default phone app update.
*/
static class DefaultKeyUpdater {
public String getDefaultApplication(Context context) {
final ComponentName appName = SmsApplication.getDefaultSmsApplication(context, true);
if (appName != null) {
return appName.getPackageName();
}
return null;
}
public void setDefaultApplication(Context context, String key) {
SmsApplication.setDefaultApplication(key, context);
}
}
}

View File

@@ -1,71 +0,0 @@
/*
* 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.applications.defaultapps;
import android.content.ComponentName;
import android.content.Context;
import android.telephony.TelephonyManager;
import com.android.internal.telephony.SmsApplication;
import com.android.settingslib.applications.DefaultAppInfo;
import java.util.Collection;
public class DefaultSmsPreferenceController extends DefaultAppPreferenceController {
public DefaultSmsPreferenceController(Context context) {
super(context);
}
@Override
public boolean isAvailable() {
boolean isRestrictedUser = mUserManager.getUserInfo(mUserId).isRestricted();
TelephonyManager tm =
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
return !isRestrictedUser && tm.isSmsCapable();
}
@Override
public String getPreferenceKey() {
return "default_sms_app";
}
@Override
protected DefaultAppInfo getDefaultAppInfo() {
final ComponentName app = SmsApplication.getDefaultSmsApplication(mContext, true);
if (app != null) {
return new DefaultAppInfo(mContext, mPackageManager, mUserId, app);
}
return null;
}
public static boolean hasSmsPreference(String pkg, Context context) {
Collection<SmsApplication.SmsApplicationData> smsApplications =
SmsApplication.getApplicationCollection(context);
for (SmsApplication.SmsApplicationData data : smsApplications) {
if (data.mPackageName.equals(pkg)) {
return true;
}
}
return false;
}
public static boolean isSmsDefault(String pkg, Context context) {
ComponentName appName = SmsApplication.getDefaultSmsApplication(context, true);
return appName != null && appName.getPackageName().equals(pkg);
}
}

View File

@@ -1,50 +0,0 @@
/*
* 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.applications.defaultapps;
import android.content.Context;
import android.os.UserHandle;
import com.android.settings.Utils;
public class DefaultWorkBrowserPreferenceController extends DefaultBrowserPreferenceController {
public static final String KEY = "work_default_browser";
private final UserHandle mUserHandle;
public DefaultWorkBrowserPreferenceController(Context context) {
super(context);
mUserHandle = Utils.getManagedProfile(mUserManager);
if (mUserHandle != null) {
mUserId = mUserHandle.getIdentifier();
}
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
if (mUserHandle == null) {
return false;
}
return super.isAvailable();
}
}

View File

@@ -1,49 +0,0 @@
/*
* 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.applications.defaultapps;
import android.content.Context;
import android.os.UserHandle;
import com.android.settings.Utils;
public class DefaultWorkPhonePreferenceController extends DefaultPhonePreferenceController {
public static final String KEY = "work_default_phone_app";
private final UserHandle mUserHandle;
public DefaultWorkPhonePreferenceController(Context context) {
super(context);
mUserHandle = Utils.getManagedProfile(mUserManager);
if (mUserHandle != null) {
mUserId = mUserHandle.getIdentifier();
}
}
@Override
public boolean isAvailable() {
if (mUserHandle == null) {
return false;
}
return super.isAvailable();
}
@Override
public String getPreferenceKey() {
return KEY;
}
}

View File

@@ -92,7 +92,6 @@ import com.android.settings.applications.AppStateUsageBridge;
import com.android.settings.applications.AppStateUsageBridge.UsageState;
import com.android.settings.applications.AppStateWriteSettingsBridge;
import com.android.settings.applications.AppStorageSettings;
import com.android.settings.applications.DefaultAppSettings;
import com.android.settings.applications.InstalledAppCounter;
import com.android.settings.applications.UsageAccessDetails;
import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
@@ -704,12 +703,9 @@ public class ManageApplications extends InstrumentedFragment
.setResultListener(this, ADVANCED_SETTINGS)
.launch();
} else {
new SubSettingLauncher(getContext())
.setDestination(DefaultAppSettings.class.getName())
.setTitleRes(R.string.configure_apps)
.setSourceMetricsCategory(getMetricsCategory())
.setResultListener(this, ADVANCED_SETTINGS)
.launch();
Intent intent = new Intent(
android.provider.Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
startActivityForResult(intent, ADVANCED_SETTINGS);
}
return true;
default:

View File

@@ -0,0 +1,55 @@
/*
* 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.applications.specialaccess;
import android.content.Context;
import android.content.pm.PackageManager;
import android.nfc.NfcAdapter;
import android.os.UserManager;
import com.android.settings.core.BasePreferenceController;
public class DefaultPaymentSettingsPreferenceController extends BasePreferenceController {
private final NfcAdapter mNfcAdapter;
private final PackageManager mPackageManager;
private final UserManager mUserManager;
public DefaultPaymentSettingsPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mPackageManager = context.getPackageManager();
mUserManager = context.getSystemService(UserManager.class);
mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext);
}
@Override
public int getAvailabilityStatus() {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_NFC)
|| !mPackageManager.hasSystemFeature(
PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
return UNSUPPORTED_ON_DEVICE;
}
if (!mUserManager.isAdminUser()) {
return DISABLED_FOR_USER;
}
if (mNfcAdapter == null || !mNfcAdapter.isEnabled()) {
return CONDITIONALLY_UNAVAILABLE;
}
return AVAILABLE;
}
}

View File

@@ -41,6 +41,7 @@ import com.android.settings.core.BasePreferenceController;
import com.android.settings.fuelgauge.BatteryMeterView;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnDestroy;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.utils.ThreadUtils;
@@ -54,7 +55,7 @@ import java.util.Map;
* This class adds a header with device name and status (connected/disconnected, etc.).
*/
public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceController implements
LifecycleObserver, OnStart, OnStop, CachedBluetoothDevice.Callback {
LifecycleObserver, OnStart, OnStop, OnDestroy, CachedBluetoothDevice.Callback {
private static final String TAG = "AdvancedBtHeaderCtrl";
@VisibleForTesting
@@ -118,7 +119,13 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
}
mCachedDevice.unregisterCallback(this::onDeviceAttributesChanged);
mBluetoothAdapter.unregisterMetadataListener(mCachedDevice.getDevice());
}
@Override
public void onDestroy() {
if (!isAvailable()) {
return;
}
// Destroy icon bitmap associated with this header
for (Bitmap bitmap : mIconCache.values()) {
if (bitmap != null) {

View File

@@ -34,7 +34,6 @@ import com.android.settings.accounts.AccountSyncSettings;
import com.android.settings.accounts.ChooseAccountFragment;
import com.android.settings.accounts.ManagedProfileSettings;
import com.android.settings.applications.AppAndNotificationDashboardFragment;
import com.android.settings.applications.DefaultAppSettings;
import com.android.settings.applications.ProcessStatsSummary;
import com.android.settings.applications.ProcessStatsUi;
import com.android.settings.applications.UsageAccessDetails;
@@ -247,7 +246,6 @@ public class SettingsGateway {
DrawOverlayDetails.class.getName(),
WriteSettingsDetails.class.getName(),
ExternalSourcesDetails.class.getName(),
DefaultAppSettings.class.getName(),
WallpaperTypeSettings.class.getName(),
VrListenerSettings.class.getName(),
PictureInPictureSettings.class.getName(),
@@ -308,7 +306,6 @@ public class SettingsGateway {
// Home page > Apps & Notifications
Settings.UserSettingsActivity.class.getName(),
Settings.ConfigureNotificationSettingsActivity.class.getName(),
Settings.AdvancedAppsActivity.class.getName(),
Settings.ManageApplicationsActivity.class.getName(),
Settings.PaymentSettingsActivity.class.getName(),
// Home page > Security & screen lock

View File

@@ -23,7 +23,6 @@ import com.android.settings.LegalSettings;
import com.android.settings.accounts.AccountDashboardFragment;
import com.android.settings.accounts.AccountDetailDashboardFragment;
import com.android.settings.applications.AppAndNotificationDashboardFragment;
import com.android.settings.applications.DefaultAppSettings;
import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.development.DevelopmentSettingsDashboardFragment;
@@ -79,8 +78,6 @@ public class DashboardFragmentRegistry {
CategoryKey.CATEGORY_APPS);
PARENT_TO_CATEGORY_KEY_MAP.put(PowerUsageSummary.class.getName(),
CategoryKey.CATEGORY_BATTERY);
PARENT_TO_CATEGORY_KEY_MAP.put(DefaultAppSettings.class.getName(),
CategoryKey.CATEGORY_APPS_DEFAULT);
PARENT_TO_CATEGORY_KEY_MAP.put(DisplaySettings.class.getName(),
CategoryKey.CATEGORY_DISPLAY);
PARENT_TO_CATEGORY_KEY_MAP.put(SoundSettings.class.getName(),

View File

@@ -36,11 +36,15 @@ public class TopLevelDisplayPreferenceController extends BasePreferenceControlle
@Override
public CharSequence getSummary() {
if (new WallpaperPreferenceController(mContext, "dummy_key").isAvailable()) {
return mContext.getText(R.string.display_dashboard_summary);
final WallpaperPreferenceController controller =
new WallpaperPreferenceController(mContext, "dummy_key");
if (controller.isAvailable()) {
return mContext.getText(
controller.areStylesAvailable()
? R.string.display_dashboard_summary_with_style
: R.string.display_dashboard_summary);
} else {
return mContext.getText(R.string.display_dashboard_nowallpaper_summary);
}
}
}

View File

@@ -25,6 +25,7 @@ import android.text.TextUtils;
import android.util.Log;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
@@ -34,16 +35,26 @@ import com.android.settingslib.RestrictedPreference;
import java.util.List;
public class WallpaperPreferenceController extends BasePreferenceController {
private static final String TAG = "WallpaperPrefController";
private final String mWallpaperPackage;
private final String mWallpaperClass;
private final String mStylesAndWallpaperClass;
public WallpaperPreferenceController(Context context, String key) {
super(context, key);
mWallpaperPackage = mContext.getString(R.string.config_wallpaper_picker_package);
mWallpaperClass = mContext.getString(R.string.config_wallpaper_picker_class);
mStylesAndWallpaperClass =
mContext.getString(R.string.config_styles_and_wallpaper_picker_class);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
Preference preference = screen.findPreference(getPreferenceKey());
preference.setTitle(mContext.getString(areStylesAvailable()
? R.string.style_and_wallpaper_settings_title : R.string.wallpaper_settings_title));
}
@Override
@@ -52,14 +63,7 @@ public class WallpaperPreferenceController extends BasePreferenceController {
Log.e(TAG, "No Wallpaper picker specified!");
return UNSUPPORTED_ON_DEVICE;
}
final ComponentName componentName =
new ComponentName(mWallpaperPackage, mWallpaperClass);
final PackageManager pm = mContext.getPackageManager();
final Intent intent = new Intent();
intent.setComponent(componentName);
final List<ResolveInfo> resolveInfos =
pm.queryIntentActivities(intent, 0 /* flags */);
return resolveInfos != null && !resolveInfos.isEmpty()
return canResolveWallpaperComponent(mWallpaperClass)
? AVAILABLE_UNSEARCHABLE : CONDITIONALLY_UNAVAILABLE;
}
@@ -68,6 +72,31 @@ public class WallpaperPreferenceController extends BasePreferenceController {
disablePreferenceIfManaged((RestrictedPreference) preference);
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (getPreferenceKey().equals(preference.getKey())) {
final ComponentName componentName = new ComponentName(mWallpaperPackage,
areStylesAvailable() ? mStylesAndWallpaperClass : mWallpaperClass);
preference.getContext().startActivity(new Intent().setComponent(componentName));
return true;
}
return super.handlePreferenceTreeClick(preference);
}
/** Returns whether Styles & Wallpaper is enabled and available. */
public boolean areStylesAvailable() {
return !TextUtils.isEmpty(mStylesAndWallpaperClass)
&& canResolveWallpaperComponent(mStylesAndWallpaperClass);
}
private boolean canResolveWallpaperComponent(String className) {
final ComponentName componentName = new ComponentName(mWallpaperPackage, className);
final PackageManager pm = mContext.getPackageManager();
final Intent intent = new Intent().setComponent(componentName);
final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0 /* flags */);
return resolveInfos != null && !resolveInfos.isEmpty();
}
private void disablePreferenceIfManaged(RestrictedPreference pref) {
final String restriction = DISALLOW_SET_WALLPAPER;
if (pref != null) {

View File

@@ -20,6 +20,7 @@ import static com.android.settings.slices.CustomSliceRegistry.BLUETOOTH_DEVICES_
import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI;
import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
@@ -32,7 +33,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.homepage.contextualcards.logging.ContextualCardLogUtils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.AsyncLoaderCompat;
import java.util.ArrayList;
@@ -162,10 +165,16 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>
return visibleCards;
} finally {
if (!CardContentProvider.DELETE_CARD_URI.equals(mNotifyUri)) {
final ContextualCardFeatureProvider contextualCardFeatureProvider =
FeatureFactory.getFactory(mContext)
.getContextualCardFeatureProvider(mContext);
contextualCardFeatureProvider.logContextualCardDisplay(visibleCards, hiddenCards);
final MetricsFeatureProvider metricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
metricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_CONTEXTUAL_CARD_SHOW,
ContextualCardLogUtils.buildCardListLog(visibleCards));
metricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_CONTEXTUAL_CARD_NOT_SHOW,
ContextualCardLogUtils.buildCardListLog(hiddenCards));
}
}
}

View File

@@ -77,8 +77,7 @@ public class ContextualCardsFragment extends InstrumentedFragment implements
mCardsContainer.setAdapter(mContextualCardsAdapter);
mContextualCardManager.setListener(mContextualCardsAdapter);
mCardsContainer.setListener(this);
mItemTouchHelper = new ItemTouchHelper(
new SwipeDismissalDelegate(context, mContextualCardsAdapter));
mItemTouchHelper = new ItemTouchHelper(new SwipeDismissalDelegate(mContextualCardsAdapter));
mItemTouchHelper.attachToRecyclerView(mCardsContainer);
return rootView;

View File

@@ -0,0 +1,263 @@
/*
* 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.homepage.contextualcards.logging;
import android.util.Log;
import androidx.slice.widget.EventInfo;
import com.android.settings.homepage.contextualcards.ContextualCard;
import java.util.ArrayList;
import java.util.List;
/**
* Utils of building contextual card to string, and parse string back to {@link CardLog}
*/
public class ContextualCardLogUtils {
private static final String TAG = "ContextualCardLogUtils";
private static final class TapTarget {
static int TARGET_DEFAULT = 0;
static int TARGET_TITLE = 1;
static int TARGET_TOGGLE = 2;
static int TARGET_SLIDER = 3;
}
/**
* Log data for a general contextual card event
*/
public static class CardLog {
private final String mSliceUri;
private final double mRankingScore;
public CardLog(Builder builder) {
mSliceUri = builder.mSliceUri;
mRankingScore = builder.mRankingScore;
}
public String getSliceUri() {
return mSliceUri;
}
public double getRankingScore() {
return mRankingScore;
}
public static class Builder {
private String mSliceUri;
private double mRankingScore;
public Builder setSliceUri(String sliceUri) {
mSliceUri = sliceUri;
return this;
}
public Builder setRankingScore(double rankingScore) {
mRankingScore = rankingScore;
return this;
}
public CardLog build() {
return new CardLog(this);
}
}
}
/**
* Log data for a contextual card click event
*/
public static class CardClickLog extends CardLog {
private final int mSliceRow;
private final int mSliceTapTarget;
private final int mUiPosition;
public CardClickLog(Builder builder) {
super(builder);
mSliceRow = builder.mSliceRow;
mSliceTapTarget = builder.mSliceTapTarget;
mUiPosition = builder.mUiPosition;
}
public int getSliceRow() {
return mSliceRow;
}
public int getSliceTapTarget() {
return mSliceTapTarget;
}
public int getUiPosition() {
return mUiPosition;
}
public static class Builder extends CardLog.Builder {
private int mSliceRow;
private int mSliceTapTarget;
private int mUiPosition;
public Builder setSliceRow(int sliceRow) {
mSliceRow = sliceRow;
return this;
}
public Builder setSliceTapTarget(int sliceTapTarget) {
mSliceTapTarget = sliceTapTarget;
return this;
}
public Builder setUiPosition(int uiPosition) {
mUiPosition = uiPosition;
return this;
}
@Override
public CardClickLog build() {
return new CardClickLog(this);
}
}
}
/**
* Serialize {@link ContextualCard} click event to string
*
* @param card Clicked Contextual card.
* @param sliceRow A Slice can contains multiple row, which row are we clicked
* @param tapTarget Integer value of {@link TapTarget}
* @param uiPosition Contextual card position in Listview
*/
public static String buildCardClickLog(ContextualCard card, int sliceRow, int tapTarget,
int uiPosition) {
final StringBuilder log = new StringBuilder();
log.append(card.getTextSliceUri()).append("|")
.append(card.getRankingScore()).append("|")
.append(sliceRow).append("|")
.append(actionTypeToTapTarget(tapTarget)).append("|")
.append(uiPosition);
return log.toString();
}
/**
* Parse string to a {@link CardClickLog}
*/
public static CardClickLog parseCardClickLog(String clickLog) {
if (clickLog != null) {
final String[] parts = clickLog.split("\\|");
if (parts.length < 5) {
return null;
}
try {
final CardClickLog.Builder builder = new CardClickLog.Builder();
builder.setSliceRow(Integer.parseInt(parts[2]))
.setSliceTapTarget(Integer.parseInt(parts[3]))
.setUiPosition(Integer.parseInt(parts[4]))
.setSliceUri(parts[0])
.setRankingScore(Double.parseDouble(parts[1]));
return builder.build();
} catch (Exception e) {
Log.e(TAG, "error parsing log", e);
return null;
}
}
return null;
}
/**
* Serialize {@link ContextualCard} to string
*
* @param card Contextual card.
*/
public static String buildCardDismissLog(ContextualCard card) {
final StringBuilder log = new StringBuilder();
log.append(card.getTextSliceUri())
.append("|")
.append(card.getRankingScore());
return log.toString();
}
/**
* Parse string to a {@link CardLog}
*/
public static CardLog parseCardDismissLog(String dismissLog) {
if (dismissLog != null) {
final String[] parts = dismissLog.split("\\|");
if (parts.length < 2) {
return null;
}
try {
final CardLog.Builder builder = new CardLog.Builder();
builder.setSliceUri(parts[0])
.setRankingScore(Double.parseDouble(parts[1]));
return builder.build();
} catch (Exception e) {
Log.e(TAG, "error parsing log", e);
return null;
}
}
return null;
}
/**
* Serialize List of {@link ContextualCard} to string
*/
public static String buildCardListLog(List<ContextualCard> cards) {
final StringBuilder log = new StringBuilder();
log.append(cards.size());
for (ContextualCard card : cards) {
log.append("|").append(card.getTextSliceUri())
.append("|").append(card.getRankingScore());
}
return log.toString();
}
/**
* Parse string to a List of {@link CardLog}
*/
public static List<CardLog> parseCardListLog(String listLog) {
final List<CardLog> logList = new ArrayList<>();
try {
final String[] parts = listLog.split("\\|");
if (Integer.parseInt(parts[0]) < 0) {
return logList;
}
final int size = parts.length;
for (int i = 1; i < size; ) {
final CardLog.Builder builder = new CardLog.Builder();
builder.setSliceUri(parts[i++])
.setRankingScore(Double.parseDouble(parts[i++]));
logList.add(builder.build());
}
} catch (Exception e) {
Log.e(TAG, "error parsing log", e);
return logList;
}
return logList;
}
public static int actionTypeToTapTarget(int actionType) {
switch (actionType) {
case EventInfo.ACTION_TYPE_CONTENT:
return TapTarget.TARGET_TITLE;
case EventInfo.ACTION_TYPE_TOGGLE:
return TapTarget.TARGET_TOGGLE;
case EventInfo.ACTION_TYPE_SLIDER:
return TapTarget.TARGET_SLIDER;
default:
Log.w(TAG, "unknown type " + actionType);
return TapTarget.TARGET_DEFAULT;
}
}
}

View File

@@ -16,8 +16,10 @@
package com.android.settings.homepage.contextualcards.slices;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
@@ -26,10 +28,11 @@ import com.android.settings.R;
import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
import com.android.settings.homepage.contextualcards.ContextualCard;
import com.android.settings.homepage.contextualcards.ContextualCardController;
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.homepage.contextualcards.ContextualCardFeedbackDialog;
import com.android.settings.homepage.contextualcards.logging.ContextualCardLogUtils;
import com.android.settings.homepage.contextualcards.ContextualCardUpdateListener;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.ThreadUtils;
/**
@@ -69,9 +72,13 @@ public class SliceContextualCardController implements ContextualCardController {
dbHelper.markContextualCardAsDismissed(mContext, card.getName());
});
showFeedbackDialog(card);
final ContextualCardFeatureProvider contextualCardFeatureProvider =
FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext);
contextualCardFeatureProvider.logContextualCardDismiss(card);
final MetricsFeatureProvider metricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
metricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_CONTEXTUAL_CARD_DISMISS,
ContextualCardLogUtils.buildCardDismissLog(card));
}
@Override
@@ -82,7 +89,7 @@ public class SliceContextualCardController implements ContextualCardController {
@VisibleForTesting
void showFeedbackDialog(ContextualCard card) {
final String email = mContext.getString(R.string.config_contextual_card_feedback_email);
if (TextUtils.isEmpty(email)) {
if (!isFeedbackEnabled(email)) {
return;
}
final Intent feedbackIntent = new Intent(mContext, ContextualCardFeedbackDialog.class);
@@ -93,6 +100,11 @@ public class SliceContextualCardController implements ContextualCardController {
mContext.startActivity(feedbackIntent);
}
@VisibleForTesting
boolean isFeedbackEnabled(String email) {
return !TextUtils.isEmpty(email) && Build.IS_DEBUGGABLE;
}
private String getSimpleCardName(ContextualCard card) {
final String[] split = card.getName().split("/");
return split[split.length - 1];

View File

@@ -24,7 +24,6 @@ import android.util.ArraySet;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ViewFlipper;
import androidx.annotation.LayoutRes;
import androidx.annotation.VisibleForTesting;
@@ -142,7 +141,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, Life
}
if (card.isPendingDismiss()) {
flipCardToDismissalView(holder);
showDismissalView(holder);
mFlippedCardSet.add(holder);
}
}
@@ -170,12 +169,19 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, Life
}
private void resetCardView(RecyclerView.ViewHolder holder) {
final ViewFlipper viewFlipper = holder.itemView.findViewById(R.id.view_flipper);
viewFlipper.setDisplayedChild(0 /* whichChild */);
holder.itemView.findViewById(R.id.dismissal_view).setVisibility(View.GONE);
getInitialView(holder).setVisibility(View.VISIBLE);
}
private void flipCardToDismissalView(RecyclerView.ViewHolder holder) {
final ViewFlipper viewFlipper = holder.itemView.findViewById(R.id.view_flipper);
viewFlipper.showNext();
private void showDismissalView(RecyclerView.ViewHolder holder) {
holder.itemView.findViewById(R.id.dismissal_view).setVisibility(View.VISIBLE);
getInitialView(holder).setVisibility(View.INVISIBLE);
}
private View getInitialView(RecyclerView.ViewHolder viewHolder) {
if (viewHolder.getItemViewType() == VIEW_TYPE_HALF_WIDTH) {
return ((SliceHalfCardRendererHelper.HalfCardViewHolder) viewHolder).content;
}
return ((SliceFullCardRendererHelper.SliceViewHolder) viewHolder).sliceView;
}
}

View File

@@ -17,6 +17,7 @@
package com.android.settings.homepage.contextualcards.slices;
import android.app.PendingIntent;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.util.Log;
import android.view.View;
@@ -33,8 +34,9 @@ import androidx.slice.widget.EventInfo;
import com.android.settings.R;
import com.android.settings.homepage.contextualcards.ContextualCard;
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.homepage.contextualcards.logging.ContextualCardLogUtils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Card renderer helper for {@link ContextualCard} built as slice deferred setup card.
@@ -65,10 +67,14 @@ class SliceDeferredSetupCardRendererHelper {
} catch (PendingIntent.CanceledException e) {
Log.w(TAG, "Failed to start intent " + primaryAction.getTitle());
}
final ContextualCardFeatureProvider contextualCardFeatureProvider =
FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext);
contextualCardFeatureProvider.logContextualCardClick(card, 0 /* row */,
final String log = ContextualCardLogUtils.buildCardClickLog(card, 0 /* row */,
EventInfo.ACTION_TYPE_CONTENT, view.getAdapterPosition());
final MetricsFeatureProvider metricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
metricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_CONTEXTUAL_CARD_CLICK, log);
});
}

View File

@@ -16,8 +16,10 @@
package com.android.settings.homepage.contextualcards.slices;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;
import androidx.recyclerview.widget.RecyclerView;
import androidx.slice.Slice;
@@ -25,8 +27,9 @@ import androidx.slice.widget.SliceView;
import com.android.settings.R;
import com.android.settings.homepage.contextualcards.ContextualCard;
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.homepage.contextualcards.logging.ContextualCardLogUtils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Card renderer helper for {@link ContextualCard} built as slice full card.
@@ -53,11 +56,14 @@ class SliceFullCardRendererHelper {
// Set this listener so we can log the interaction users make on the slice
cardHolder.sliceView.setOnSliceActionListener(
(eventInfo, sliceItem) -> {
final ContextualCardFeatureProvider contextualCardFeatureProvider =
FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(
mContext);
contextualCardFeatureProvider.logContextualCardClick(card, eventInfo.rowIndex,
final String log = ContextualCardLogUtils.buildCardClickLog(card, eventInfo.rowIndex,
eventInfo.actionType, cardHolder.getAdapterPosition());
final MetricsFeatureProvider metricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
metricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_CONTEXTUAL_CARD_CLICK, log);
});
// Customize slice view for Settings

View File

@@ -17,6 +17,7 @@
package com.android.settings.homepage.contextualcards.slices;
import android.app.PendingIntent;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.util.Log;
import android.view.View;
@@ -32,8 +33,9 @@ import androidx.slice.widget.EventInfo;
import com.android.settings.R;
import com.android.settings.homepage.contextualcards.ContextualCard;
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.homepage.contextualcards.logging.ContextualCardLogUtils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Card renderer helper for {@link ContextualCard} built as slice half card.
@@ -63,10 +65,14 @@ class SliceHalfCardRendererHelper {
} catch (PendingIntent.CanceledException e) {
Log.w(TAG, "Failed to start intent " + primaryAction.getTitle());
}
final ContextualCardFeatureProvider contextualCardFeatureProvider =
FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext);
contextualCardFeatureProvider.logContextualCardClick(card, 0 /* row */,
final String log = ContextualCardLogUtils.buildCardClickLog(card, 0 /* row */,
EventInfo.ACTION_TYPE_CONTENT, view.getAdapterPosition());
final MetricsFeatureProvider metricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
metricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_CONTEXTUAL_CARD_CLICK, log);
});
}

View File

@@ -16,13 +16,8 @@
package com.android.settings.homepage.contextualcards.slices;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ViewFlipper;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
@@ -39,20 +34,10 @@ public class SwipeDismissalDelegate extends ItemTouchHelper.Callback {
void onSwiped(int position);
}
private final Context mContext;
private final SwipeDismissalDelegate.Listener mListener;
private final Drawable mIconDelete;
private final Paint mBgPaint;
private final int mBgCornerRadius;
public SwipeDismissalDelegate(Context context, SwipeDismissalDelegate.Listener listener) {
mContext = context;
public SwipeDismissalDelegate(SwipeDismissalDelegate.Listener listener) {
mListener = listener;
mIconDelete = mContext.getDrawable(R.drawable.ic_delete);
mBgPaint = new Paint();
mBgPaint.setColor(mContext.getColor(R.color.homepage_card_dismissal_background));
mBgCornerRadius = mContext.getResources()
.getDimensionPixelSize(R.dimen.homepage_card_corner_radius);
}
/**
@@ -70,14 +55,10 @@ public class SwipeDismissalDelegate extends ItemTouchHelper.Callback {
switch (viewHolder.getItemViewType()) {
case SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH:
case SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH:
//TODO(b/129438972): Convert this to a regular view.
final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
// As we are using ViewFlipper to switch between the initial view and
// dismissal view, here we are making sure the current displayed view is the
// initial view of either slice full card or half card, and only allow swipe on
// these two types.
if (viewFlipper.getCurrentView().getId() != getInitialViewId(viewHolder)) {
// Here we are making sure the current displayed view is the initial view of
// either slice full card or half card, and only allow swipe on these two types.
if (viewHolder.itemView.findViewById(R.id.dismissal_view).getVisibility()
== View.VISIBLE) {
// Disable swiping when we are in the dismissal view
return 0;
}
@@ -100,41 +81,42 @@ public class SwipeDismissalDelegate extends ItemTouchHelper.Callback {
mListener.onSwiped(viewHolder.getAdapterPosition());
}
@Override
public void clearView(@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder viewHolder) {
final View view = getSwipeableView(viewHolder);
getDefaultUIUtil().clearView(view);
}
@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
final View view = getSwipeableView(viewHolder);
final View iconStart = viewHolder.itemView.findViewById(R.id.dismissal_icon_start);
final View iconEnd = viewHolder.itemView.findViewById(R.id.dismissal_icon_end);
final View itemView = viewHolder.itemView;
final int iconMargin = mContext.getResources()
.getDimensionPixelSize(R.dimen.homepage_card_dismissal_side_margin);
final int iconTop =
itemView.getTop() + (itemView.getHeight() - mIconDelete.getIntrinsicHeight()) / 2;
final int iconBottom = iconTop + mIconDelete.getIntrinsicHeight();
if (dX > 0) { //swipe to the right
final int iconLeft = itemView.getLeft() + iconMargin;
final int iconRight = iconLeft + mIconDelete.getIntrinsicWidth();
final RectF rect = new RectF(itemView.getLeft(), itemView.getTop(),
itemView.getLeft() + ((int) dX) + mBgCornerRadius, itemView.getBottom());
mIconDelete.setBounds(iconLeft, iconTop, iconRight, iconBottom);
c.drawRoundRect(rect, mBgCornerRadius, mBgCornerRadius, mBgPaint);
if (dX > 0) {
iconStart.setVisibility(View.VISIBLE);
iconEnd.setVisibility(View.GONE);
} else if (dX < 0) {
final int iconRight = itemView.getRight() - iconMargin;
final int iconLeft = iconRight - mIconDelete.getIntrinsicWidth();
final RectF rect = new RectF(itemView.getRight() + ((int) dX), itemView.getTop(),
itemView.getRight(), itemView.getBottom());
mIconDelete.setBounds(iconLeft, iconTop, iconRight, iconBottom);
c.drawRoundRect(rect, mBgCornerRadius, mBgCornerRadius, mBgPaint);
iconStart.setVisibility(View.GONE);
iconEnd.setVisibility(View.VISIBLE);
}
mIconDelete.draw(c);
getDefaultUIUtil().onDraw(c, recyclerView, view, dX, dY, actionState, isCurrentlyActive);
}
private int getInitialViewId(RecyclerView.ViewHolder viewHolder) {
/**
* Get the foreground view from the {@link android.widget.FrameLayout} as we only swipe
* the foreground out in {@link SwipeDismissalDelegate#onChildDraw} and gets the view
* beneath revealed.
*
* @return The foreground view.
*/
private View getSwipeableView(RecyclerView.ViewHolder viewHolder) {
if (viewHolder.getItemViewType() == SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH) {
return R.id.content;
return ((SliceHalfCardRendererHelper.HalfCardViewHolder) viewHolder).content;
}
return R.id.slice_view;
return ((SliceFullCardRendererHelper.SliceViewHolder) viewHolder).sliceView;
}
}

View File

@@ -1164,7 +1164,8 @@ public class ApnEditor extends SettingsPreferenceFragment
// add APN type if it is not read-only and is not wild-cardable
if (!readOnlyApnTypes.contains(apnType)
&& !apnType.equals(PhoneConstants.APN_TYPE_IA)
&& !apnType.equals(PhoneConstants.APN_TYPE_EMERGENCY)) {
&& !apnType.equals(PhoneConstants.APN_TYPE_EMERGENCY)
&& !apnType.equals(PhoneConstants.APN_TYPE_MCX)) {
if (first) {
first = false;
} else {

View File

@@ -24,12 +24,12 @@ import android.content.Intent;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.euicc.EuiccManager;
import android.util.ArrayMap;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.List;
@@ -81,8 +81,8 @@ public class MobileNetworkListController extends AbstractPreferenceController im
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceScreen = screen;
final EuiccManager euiccManager = mContext.getSystemService(EuiccManager.class);
mPreferenceScreen.findPreference(KEY_ADD_MORE).setVisible(euiccManager.isEnabled());
mPreferenceScreen.findPreference(KEY_ADD_MORE).setVisible(
MobileNetworkUtils.showEuiccSettings(mContext));
update();
}

View File

@@ -28,6 +28,7 @@ import android.telephony.euicc.EuiccManager;
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.widget.AddPreference;
import com.android.settingslib.Utils;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -49,7 +50,6 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
private SubscriptionManager mSubscriptionManager;
private SubscriptionsChangeListener mChangeListener;
private EuiccManager mEuiccManager;
private AddPreference mPreference;
/**
@@ -70,7 +70,6 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
public MobileNetworkSummaryController(Context context, Lifecycle lifecycle) {
super(context);
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mEuiccManager = mContext.getSystemService(EuiccManager.class);
if (lifecycle != null) {
mChangeListener = new SubscriptionsChangeListener(context, this);
lifecycle.addObserver(this);
@@ -99,7 +98,7 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
mSubscriptionManager);
if (subs.isEmpty()) {
if (mEuiccManager.isEnabled()) {
if (MobileNetworkUtils.showEuiccSettings(mContext)) {
return mContext.getResources().getString(
R.string.mobile_network_summary_add_a_network);
}
@@ -133,7 +132,7 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
mSubscriptionManager);
if (subs.isEmpty()) {
if (mEuiccManager.isEnabled()) {
if (MobileNetworkUtils.showEuiccSettings(mContext)) {
mPreference.setOnPreferenceClickListener((Preference pref) -> {
startAddSimFlow();
return true;
@@ -142,7 +141,7 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
} else {
// We have one or more existing subscriptions, so we want the plus button if eSIM is
// supported.
if (mEuiccManager.isEnabled()) {
if (MobileNetworkUtils.showEuiccSettings(mContext)) {
mPreference.setAddWidgetEnabled(!mChangeListener.isAirplaneModeOn());
mPreference.setOnAddClickListener(p -> startAddSimFlow());
}

View File

@@ -27,16 +27,33 @@ import java.util.Iterator;
import java.util.List;
public class SubscriptionUtil {
private static List<SubscriptionInfo> sResultsForTesting;
private static List<SubscriptionInfo> sAvailableResultsForTesting;
private static List<SubscriptionInfo> sActiveResultsForTesting;
@VisibleForTesting
public static void setAvailableSubscriptionsForTesting(List<SubscriptionInfo> results) {
sResultsForTesting = results;
sAvailableResultsForTesting = results;
}
@VisibleForTesting
public static void setActiveSubscriptionsForTesting(List<SubscriptionInfo> results) {
sActiveResultsForTesting = results;
}
public static List<SubscriptionInfo> getActiveSubscriptions(SubscriptionManager manager) {
if (sActiveResultsForTesting != null) {
return sActiveResultsForTesting;
}
List<SubscriptionInfo> subscriptions = manager.getActiveSubscriptionInfoList(true);
if (subscriptions == null) {
return new ArrayList<>();
}
return subscriptions;
}
public static List<SubscriptionInfo> getAvailableSubscriptions(SubscriptionManager manager) {
if (sResultsForTesting != null) {
return sResultsForTesting;
if (sAvailableResultsForTesting != null) {
return sAvailableResultsForTesting;
}
List<SubscriptionInfo> subscriptions = manager.getSelectableSubscriptionInfoList();
if (subscriptions == null) {

View File

@@ -129,7 +129,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
mSubscriptionPreferences = new ArrayMap<>();
int order = mStartOrder;
for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mManager)) {
for (SubscriptionInfo info : SubscriptionUtil.getActiveSubscriptions(mManager)) {
final int subId = info.getSubscriptionId();
Preference pref = existingPrefs.remove(subId);
if (pref == null) {
@@ -216,7 +216,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
if (mSubscriptionsListener.isAirplaneModeOn()) {
return false;
}
return SubscriptionUtil.getAvailableSubscriptions(mManager).size() >= 2;
return SubscriptionUtil.getActiveSubscriptions(mManager).size() >= 2;
}
@Override

View File

@@ -75,7 +75,7 @@ public abstract class DefaultSubscriptionController extends BasePreferenceContro
@Override
public int getAvailabilityStatus() {
final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mManager);
if (subs.size() > 1) {
return AVAILABLE;
} else {
@@ -121,7 +121,7 @@ public abstract class DefaultSubscriptionController extends BasePreferenceContro
}
mPreference.setVisible(true);
final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mManager);
// We'll have one entry for each available subscription, plus one for a "ask me every
// time" entry at the end.

View File

@@ -177,7 +177,7 @@ public class MobileNetworkUtils {
*/
public static boolean showEuiccSettings(Context context) {
EuiccManager euiccManager =
(EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
(EuiccManager) context.getSystemService(EuiccManager.class);
if (!euiccManager.isEnabled()) {
return false;
}
@@ -185,7 +185,7 @@ public class MobileNetworkUtils {
final ContentResolver cr = context.getContentResolver();
TelephonyManager tm =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
(TelephonyManager) context.getSystemService(TelephonyManager.class);
String currentCountry = tm.getNetworkCountryIso().toLowerCase();
String supportedCountries =
Settings.Global.getString(cr, Settings.Global.EUICC_SUPPORTED_COUNTRIES);

View File

@@ -31,6 +31,7 @@ import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.SetupWizardUtils;
import com.android.settings.Utils;
import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -452,6 +453,7 @@ public final class ChooseLockSettingsHelper {
}
private void copyInternalExtras(Intent inIntent, Intent outIntent) {
SetupWizardUtils.copySetupExtras(inIntent, outIntent);
String theme = inIntent.getStringExtra(WizardManagerHelper.EXTRA_THEME);
if (theme != null) {
outIntent.putExtra(WizardManagerHelper.EXTRA_THEME, theme);

View File

@@ -78,11 +78,8 @@ class SliceDataConverter {
private Context mContext;
private List<SliceData> mSliceData;
public SliceDataConverter(Context context) {
mContext = context;
mSliceData = new ArrayList<>();
}
/**
@@ -96,9 +93,7 @@ class SliceDataConverter {
* {@link com.android.settings.core.BasePreferenceController}.
*/
public List<SliceData> getSliceData() {
if (!mSliceData.isEmpty()) {
return mSliceData;
}
List<SliceData> sliceData = new ArrayList<>();
final Collection<Class> indexableClasses = FeatureFactory.getFactory(mContext)
.getSearchFeatureProvider().getSearchIndexableResources().getProviderValues();
@@ -117,12 +112,12 @@ class SliceDataConverter {
final List<SliceData> providerSliceData = getSliceDataFromProvider(provider,
fragmentName);
mSliceData.addAll(providerSliceData);
sliceData.addAll(providerSliceData);
}
final List<SliceData> a11ySliceData = getAccessibilitySliceData();
mSliceData.addAll(a11ySliceData);
return mSliceData;
sliceData.addAll(a11ySliceData);
return sliceData;
}
private List<SliceData> getSliceDataFromProvider(SearchIndexProvider provider,

View File

@@ -40,18 +40,22 @@ public class UserPreference extends RestrictedPreference {
public static final int USERID_UNKNOWN = -10;
public static final int USERID_GUEST_DEFAULTS = -11;
public static final Comparator<UserPreference> SERIAL_NUMBER_COMPARATOR =
new Comparator<UserPreference>() {
@Override
public int compare(UserPreference p1, UserPreference p2) {
int sn1 = p1.getSerialNumber();
int sn2 = p2.getSerialNumber();
if (sn1 < sn2) {
return -1;
} else if (sn1 > sn2) {
return 1;
}
return 0;
(p1, p2) -> {
if (p1 == null) {
return -1;
}
else if (p2 == null) {
return 1;
}
int sn1 = p1.getSerialNumber();
int sn2 = p2.getSerialNumber();
if (sn1 < sn2) {
return -1;
} else if (sn1 > sn2) {
return 1;
}
return 0;
};
private OnClickListener mDeleteClickListener;

View File

@@ -35,14 +35,13 @@ public class AddDevicePreferenceController extends BasePreferenceController {
private static final String TAG = "AddDevicePreferenceController";
private static final String KEY_ADD_DEVICE_CATEGORY = "add_device_category";
private static final String KEY_ADD_DEVICE = "add_device_to_network";
private AccessPoint mAccessPoint;
private WifiManager mWifiManager;
public AddDevicePreferenceController(Context context) {
super(context, KEY_ADD_DEVICE_CATEGORY);
super(context, KEY_ADD_DEVICE);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}

View File

@@ -409,7 +409,8 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
.setButton4Text(R.string.share)
.setButton4Icon(R.drawable.ic_qrcode_24dp)
.setButton4OnClickListener(view -> shareNetwork())
.setButton4Visible(WifiDppUtils.isSupportConfiguratorQrCodeGenerator(mAccessPoint));
.setButton4Visible(
WifiDppUtils.isSupportConfiguratorQrCodeGenerator(mContext, mAccessPoint));
mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
mTxLinkSpeedPref = screen.findPreference(KEY_TX_LINK_SPEED);
@@ -449,8 +450,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
headerPref.findViewById(R.id.entity_header));
ImageView iconView = headerPref.findViewById(R.id.entity_header_icon);
iconView.setBackground(
mContext.getDrawable(R.drawable.ic_settings_widget_background));
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
mEntityHeaderController.setLabel(mAccessPoint.getTitle());
@@ -602,10 +602,9 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
mRssiSignalLevel = signalLevel;
Drawable wifiIcon = mIconInjector.getIcon(mRssiSignalLevel);
wifiIcon.setTintList(Utils.getColorAccent(mContext));
if (mEntityHeaderController != null) {
mEntityHeaderController
.setIcon(rescaleIconForHeader(wifiIcon)).done(mFragment.getActivity(),
.setIcon(redrawIconForHeader(wifiIcon)).done(mFragment.getActivity(),
true /* rebind */);
}
@@ -617,7 +616,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
mSignalStrengthPref.setVisible(true);
}
private Drawable rescaleIconForHeader(Drawable original) {
private Drawable redrawIconForHeader(Drawable original) {
final int iconSize = mContext.getResources().getDimensionPixelSize(
R.dimen.wifi_detail_page_header_image_size);
final int actualWidth = original.getMinimumWidth();
@@ -628,10 +627,19 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
return original;
}
// clear tint list to make sure can set 87% black after enlarge
original.setTintList(null);
// enlarge icon size
final Bitmap bitmap = Utils.createBitmap(original,
iconSize /*width*/,
iconSize /*height*/);
return new BitmapDrawable(null /*resource*/, bitmap);
Drawable newIcon = new BitmapDrawable(null /*resource*/, bitmap);
// config color for 87% black after enlarge
newIcon.setTintList(Utils.getColorAttr(mContext, android.R.attr.textColorPrimary));
return newIcon;
}
private void refreshFrequency() {

View File

@@ -46,6 +46,8 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.StringRes;
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.ViewModelProviders;
import com.android.settings.R;
@@ -57,6 +59,7 @@ import com.android.settingslib.wifi.AccessPoint;
import com.android.settingslib.wifi.WifiTracker;
import com.android.settingslib.wifi.WifiTrackerFactory;
import java.util.ArrayList;
import java.util.List;
public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment implements
@@ -104,7 +107,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
private WifiQrCode mWifiQrCode;
/** The WifiConfiguration connecting for enrollee usage */
private WifiConfiguration mWifiConfiguration;
private WifiConfiguration mEnrolleeWifiConfiguration;
private int mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_FAILURE_NONE;
@@ -140,14 +143,8 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
break;
case MESSAGE_SCAN_WIFI_DPP_SUCCESS:
if (mCamera != null) {
mCamera.stop();
}
mDecorateView.setFocused(true);
mErrorMessage.setVisibility(View.INVISIBLE);
if (mScanWifiDppSuccessListener == null) {
// mScanWifiDppSuccessListener may be null after onDetach(), do nothing here
return;
}
mScanWifiDppSuccessListener.onScanWifiDppSuccess((WifiQrCode)msg.obj);
@@ -160,23 +157,43 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
WifiDppUtils.triggerVibrationForQrCodeRecognition(getContext());
notifyUserForQrCodeRecognition();
break;
case MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS:
if (mCamera != null) {
mCamera.stop();
// We may get 2 WifiConfiguration if the QR code has no password in it,
// one for open network and one for enhanced open network.
final WifiManager wifiManager =
getContext().getSystemService(WifiManager.class);
final WifiNetworkConfig qrCodeWifiNetworkConfig =
(WifiNetworkConfig)msg.obj;
final List<WifiConfiguration> qrCodeWifiConfigurations =
qrCodeWifiNetworkConfig.getWifiConfigurations();
// Adds all Wi-Fi networks in QR code to the set of configured networks and
// connects to it if it's reachable.
boolean hasReachableWifiNetwork = false;
for (WifiConfiguration qrCodeWifiConfiguration : qrCodeWifiConfigurations) {
final int id = wifiManager.addNetwork(qrCodeWifiConfiguration);
if (id == -1) {
continue;
}
wifiManager.enableNetwork(id, /* attemptConnect */ false);
if (isReachableWifiNetwork(qrCodeWifiConfiguration)) {
hasReachableWifiNetwork = true;
mEnrolleeWifiConfiguration = qrCodeWifiConfiguration;
wifiManager.connect(id,
/* listener */ WifiDppQrCodeScannerFragment.this);
}
}
mDecorateView.setFocused(true);
mErrorMessage.setVisibility(View.INVISIBLE);
if (hasReachableWifiNetwork == false) {
showErrorMessageAndRestartCamera(
R.string.wifi_dpp_check_connection_try_again);
return;
}
final WifiNetworkConfig wifiNetworkConfig = (WifiNetworkConfig)msg.obj;
mWifiConfiguration = wifiNetworkConfig.getWifiConfigurationOrNull();
wifiNetworkConfig.connect(getContext(),
/* listener */ WifiDppQrCodeScannerFragment.this);
WifiDppUtils.triggerVibrationForQrCodeRecognition(getContext());
notifyUserForQrCodeRecognition();
break;
default:
@@ -185,6 +202,30 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
}
};
@UiThread
private void notifyUserForQrCodeRecognition() {
if (mCamera != null) {
mCamera.stop();
}
mDecorateView.setFocused(true);
mErrorMessage.setVisibility(View.INVISIBLE);
WifiDppUtils.triggerVibrationForQrCodeRecognition(getContext());
}
private boolean isReachableWifiNetwork(WifiConfiguration wifiConfiguration) {
final List<AccessPoint> scannedAccessPoints = mWifiTracker.getAccessPoints();
for (AccessPoint scannedAccessPoint : scannedAccessPoints) {
if (scannedAccessPoint.matches(wifiConfiguration) &&
scannedAccessPoint.isReachable()) {
return true;
}
}
return false;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -192,7 +233,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
if (savedInstanceState != null) {
mIsConfiguratorMode = savedInstanceState.getBoolean(KEY_IS_CONFIGURATOR_MODE);
mLatestStatusCode = savedInstanceState.getInt(KEY_LATEST_ERROR_CODE);
mWifiConfiguration = savedInstanceState.getParcelable(KEY_WIFI_CONFIGURATION);
mEnrolleeWifiConfiguration = savedInstanceState.getParcelable(KEY_WIFI_CONFIGURATION);
}
final WifiDppInitiatorViewModel model =
@@ -221,6 +262,24 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
});
}
@Override
public void onPause() {
if (mCamera != null) {
mCamera.stop();
}
super.onPause();
}
@Override
public void onResume() {
super.onResume();
if (!isGoingInitiator()) {
restartCamera();
}
}
@Override
public int getMetricsCategory() {
if (mIsConfiguratorMode) {
@@ -480,7 +539,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_IS_CONFIGURATOR_MODE, mIsConfiguratorMode);
outState.putInt(KEY_LATEST_ERROR_CODE, mLatestStatusCode);
outState.putParcelable(KEY_WIFI_CONFIGURATION, mWifiConfiguration);
outState.putParcelable(KEY_WIFI_CONFIGURATION, mEnrolleeWifiConfiguration);
super.onSaveInstanceState(outState);
}
@@ -496,7 +555,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
for (WifiConfiguration wifiConfig : wifiConfigs) {
if (wifiConfig.networkId == newNetworkId) {
mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_SUCCESS;
mWifiConfiguration = wifiConfig;
mEnrolleeWifiConfiguration = wifiConfig;
wifiManager.connect(wifiConfig, WifiDppQrCodeScannerFragment.this);
return;
}
@@ -588,17 +647,13 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
@Override
public void onSuccess() {
if (isEnrollingWifiNetworkReachable()) {
final Intent resultIntent = new Intent();
resultIntent.putExtra(WifiDialogActivity.KEY_WIFI_CONFIGURATION, mWifiConfiguration);
final Intent resultIntent = new Intent();
resultIntent.putExtra(WifiDialogActivity.KEY_WIFI_CONFIGURATION,
mEnrolleeWifiConfiguration);
final Activity hostActivity = getActivity();
hostActivity.setResult(Activity.RESULT_OK, resultIntent);
hostActivity.finish();
} else {
Log.d(TAG, "Enroll Wi-Fi network succeeded but it's not reachable");
showErrorMessageAndRestartCamera(R.string.wifi_dpp_check_connection_try_again);
}
final Activity hostActivity = getActivity();
hostActivity.setResult(Activity.RESULT_OK, resultIntent);
hostActivity.finish();
}
@Override
@@ -607,22 +662,6 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
showErrorMessageAndRestartCamera(R.string.wifi_dpp_check_connection_try_again);
}
private boolean isEnrollingWifiNetworkReachable() {
if (mWifiConfiguration == null) {
Log.e(TAG, "Connect succeeded but lost WifiConfiguration");
return false;
}
final List<AccessPoint> scannedAccessPoints = mWifiTracker.getAccessPoints();
for (AccessPoint accessPoint : scannedAccessPoints) {
if (accessPoint.matches(mWifiConfiguration) &&
accessPoint.isReachable()) {
return true;
}
}
return false;
}
// Check is Easy Connect handshaking or not
private boolean isGoingInitiator() {
final WifiDppInitiatorViewModel model =
@@ -682,4 +721,9 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
public void onAccessPointsChanged() {
// Do nothing.
}
@VisibleForTesting
protected boolean isDecodeTaskAlive() {
return mCamera != null && mCamera.isDecodeTaskAlive();
}
}

View File

@@ -162,6 +162,9 @@ public class WifiDppUtils {
if (config.allowedKeyManagement.get(KeyMgmt.SAE)) {
return WifiQrCode.SECURITY_SAE;
}
if (config.allowedKeyManagement.get(KeyMgmt.OWE)) {
return WifiQrCode.SECURITY_NO_PASSWORD;
}
if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ||
config.allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
return WifiQrCode.SECURITY_WPA_PSK;
@@ -185,7 +188,7 @@ public class WifiDppUtils {
public static Intent getConfiguratorQrCodeGeneratorIntentOrNull(Context context,
WifiManager wifiManager, AccessPoint accessPoint) {
final Intent intent = new Intent(context, WifiDppConfiguratorActivity.class);
if (isSupportConfiguratorQrCodeGenerator(accessPoint)) {
if (isSupportConfiguratorQrCodeGenerator(context, accessPoint)) {
intent.setAction(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
} else {
return null;
@@ -343,22 +346,24 @@ public class WifiDppUtils {
/**
* Checks if QR code generator supports to config other devices with the Wi-Fi network
*
* @param context The context to use for {@code WifiManager}
* @param accessPoint The {@link AccessPoint} of the Wi-Fi network
*/
public static boolean isSupportConfiguratorQrCodeGenerator(AccessPoint accessPoint) {
return isSupportZxing(accessPoint.getSecurity());
public static boolean isSupportConfiguratorQrCodeGenerator(Context context,
AccessPoint accessPoint) {
return isSupportZxing(context, accessPoint.getSecurity());
}
/**
* Checks if this device supports to be configured by the Wi-Fi network of the security
*
* @param context The context to use for {@link WifiManager#isEasyConnectSupported()}
* @param context The context to use for {@code WifiManager}
* @param accesspointSecurity The security constants defined in {@link AccessPoint}
*/
public static boolean isSupportEnrolleeQrCodeScanner(Context context,
int accesspointSecurity) {
return isSupportWifiDpp(context, accesspointSecurity) ||
isSupportZxing(accesspointSecurity);
isSupportZxing(context, accesspointSecurity);
}
private static boolean isSupportHotspotConfiguratorQrCodeGenerator(
@@ -376,19 +381,38 @@ public class WifiDppUtils {
}
// DPP 1.0 only supports SAE and PSK.
if (accesspointSecurity == AccessPoint.SECURITY_SAE ||
accesspointSecurity == AccessPoint.SECURITY_PSK) {
return true;
final WifiManager wifiManager = context.getSystemService(WifiManager.class);
switch (accesspointSecurity) {
case AccessPoint.SECURITY_SAE:
if (wifiManager.isWpa3SaeSupported()) {
return true;
}
break;
case AccessPoint.SECURITY_PSK:
return true;
default:
}
return false;
}
// TODO (b/124131581 b/129396816): TO support WPA3 securities (SAE & OWE), change here at first
private static boolean isSupportZxing(int accesspointSecurity) {
if (accesspointSecurity == AccessPoint.SECURITY_PSK ||
accesspointSecurity == AccessPoint.SECURITY_WEP ||
accesspointSecurity == AccessPoint.SECURITY_NONE) {
return true;
private static boolean isSupportZxing(Context context, int accesspointSecurity) {
final WifiManager wifiManager = context.getSystemService(WifiManager.class);
switch (accesspointSecurity) {
case AccessPoint.SECURITY_PSK:
case AccessPoint.SECURITY_WEP:
case AccessPoint.SECURITY_NONE:
return true;
case AccessPoint.SECURITY_SAE:
if (wifiManager.isWpa3SaeSupported()) {
return true;
}
break;
case AccessPoint.SECURITY_OWE:
if (wifiManager.isEnhancedOpenSupported()) {
return true;
}
break;
default:
}
return false;
}

View File

@@ -32,6 +32,9 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting;
import java.util.ArrayList;
import java.util.List;
/**
* Wraps the parameters of ZXing reader library's Wi-Fi Network config format.
* Please check {@code WifiQrCode} for detail of the format.
@@ -203,50 +206,63 @@ public class WifiNetworkConfig {
return mIsHotspot;
}
public void connect(Context context, WifiManager.ActionListener listener) {
WifiConfiguration wifiConfiguration = getWifiConfigurationOrNull();
if (wifiConfiguration == null) {
if (listener != null) {
listener.onFailure(WifiManager.ERROR);
}
return;
}
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
wifiManager.connect(wifiConfiguration, listener);
}
public boolean isSupportWifiDpp(Context context) {
if (!WifiDppUtils.isWifiDppEnabled(context)) {
return false;
}
// DPP 1.0 only supports SAE and PSK.
if (SECURITY_SAE.equals(mSecurity) || SECURITY_WPA_PSK.equals(mSecurity)) {
return true;
if (TextUtils.isEmpty(mSecurity)) {
return false;
}
// DPP 1.0 only supports SAE and PSK.
final WifiManager wifiManager = context.getSystemService(WifiManager.class);
switch (mSecurity) {
case SECURITY_SAE:
if (wifiManager.isWpa3SaeSupported()) {
return true;
}
break;
case SECURITY_WPA_PSK:
return true;
default:
}
return false;
}
/**
* This is a simplified method from {@code WifiConfigController.getConfig()}
*
* TODO (b/129021867): WifiConfiguration is a deprecated class, should replace it with
* {@code android.net.wifi.WifiNetworkSuggestion}
*
* @return When it's a open network, returns 2 WifiConfiguration in the List, the 1st is
* open network and the 2nd is enhanced open network. Returns 1 WifiConfiguration in the
* List for all other supported Wi-Fi securities.
*/
WifiConfiguration getWifiConfigurationOrNull() {
if (!isValidConfig(this)) {
return null;
}
List<WifiConfiguration> getWifiConfigurations() {
final List<WifiConfiguration> wifiConfigurations = new ArrayList<>();
final WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = addQuotationIfNeeded(mSsid);
wifiConfiguration.hiddenSSID = mHiddenSsid;
wifiConfiguration.networkId = mNetworkId;
if (!isValidConfig(this)) {
return wifiConfigurations;
}
if (TextUtils.isEmpty(mSecurity) || SECURITY_NO_PASSWORD.equals(mSecurity)) {
wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
return wifiConfiguration;
// TODO (b/129835824): we add both open network and enhanced open network to WifiManager
// for android Q, should improve it in the future.
final WifiConfiguration openNetworkWifiConfiguration = getBasicWifiConfiguration();
openNetworkWifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
wifiConfigurations.add(openNetworkWifiConfiguration);
final WifiConfiguration enhancedOpenNetworkWifiConfiguration =
getBasicWifiConfiguration();
enhancedOpenNetworkWifiConfiguration.allowedKeyManagement.set(KeyMgmt.OWE);
enhancedOpenNetworkWifiConfiguration.requirePMF = true;
wifiConfigurations.add(enhancedOpenNetworkWifiConfiguration);
return wifiConfigurations;
}
final WifiConfiguration wifiConfiguration = getBasicWifiConfiguration();
if (mSecurity.startsWith(SECURITY_WEP)) {
wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
wifiConfiguration.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
@@ -268,11 +284,27 @@ public class WifiNetworkConfig {
} else {
wifiConfiguration.preSharedKey = addQuotationIfNeeded(mPreSharedKey);
}
} else if (mSecurity.startsWith(SECURITY_SAE)) {
wifiConfiguration.allowedKeyManagement.set(KeyMgmt.SAE);
wifiConfiguration.requirePMF = true;
if (mPreSharedKey.length() != 0) {
wifiConfiguration.preSharedKey = addQuotationIfNeeded(mPreSharedKey);
}
} else {
Log.w(TAG, "Unsupported security");
return null;
return wifiConfigurations;
}
wifiConfigurations.add(wifiConfiguration);
return wifiConfigurations;
}
private WifiConfiguration getBasicWifiConfiguration() {
final WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = addQuotationIfNeeded(mSsid);
wifiConfiguration.hiddenSSID = mHiddenSsid;
wifiConfiguration.networkId = mNetworkId;
return wifiConfiguration;
}

View File

@@ -64,10 +64,10 @@ public class WifiQrCode {
public static final String DELIMITER_QR_CODE = ";";
// Ignores password if security is SECURITY_NO_PASSWORD or absent
public static final String SECURITY_NO_PASSWORD = "nopass";
public static final String SECURITY_NO_PASSWORD = "nopass"; //open network or OWE
public static final String SECURITY_WEP = "WEP";
public static final String SECURITY_WPA_PSK = "WPA";
public static final String SECURITY_SAE = "WPA3";
public static final String SECURITY_SAE = "SAE";
private String mQrCode;

View File

@@ -401,4 +401,14 @@ public class QrCamera extends Handler {
mScannerCallback.handleSuccessfulResult(qrCode.getText());
}
}
/**
* After {@link #start(SurfaceTexture)}, DecodingTask runs continuously to capture images and
* decode QR code. DecodingTask become null After {@link #stop()}.
*
* Uses this method in test case to prevent power consumption problem.
*/
public boolean isDecodeTaskAlive() {
return mDecodeTask != null;
}
}

View File

@@ -46,7 +46,6 @@
<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_default_home">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>

View File

@@ -33,8 +33,10 @@ public class AppStateInstallAppsBridgeTest {
new AppStateInstallAppsBridge.InstallAppsState();
assertThat(appState.canInstallApps()).isFalse();
appState.permissionGranted = true;
appState.permissionRequested = true;
assertThat(appState.canInstallApps()).isFalse();
appState.appOpMode = AppOpsManager.MODE_ALLOWED;
assertThat(appState.canInstallApps()).isTrue();
appState.appOpMode = AppOpsManager.MODE_ERRORED;

View File

@@ -1,174 +0,0 @@
/*
* 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.applications;
import static com.google.common.truth.Truth.assertThat;
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.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserManager;
import android.telephony.TelephonyManager;
import com.android.settings.R;
import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController;
import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController;
import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController;
import com.android.settings.dashboard.SummaryLoader;
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 org.robolectric.util.ReflectionHelpers;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class DefaultAppSettingsTest {
private Context mContext;
private DefaultAppSettings mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mFragment = new DefaultAppSettings();
mFragment.onAttach(mContext);
}
@Test
public void getPreferenceScreenResId_shouldUseAppDefaultSettingPrefLayout() {
assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(R.xml.app_default_settings);
}
@Test
public void setListening_shouldUpdateSummary() {
final SummaryLoader summaryLoader = mock(SummaryLoader.class);
final DefaultAppSettings.SummaryProvider summaryProvider =
new DefaultAppSettings.SummaryProvider(mContext, summaryLoader);
final DefaultSmsPreferenceController defaultSms =
mock(DefaultSmsPreferenceController.class);
final DefaultBrowserPreferenceController defaultBrowser =
mock(DefaultBrowserPreferenceController.class);
final DefaultPhonePreferenceController defaultPhone =
mock(DefaultPhonePreferenceController.class);
ReflectionHelpers.setField(summaryProvider, "mDefaultSmsPreferenceController", defaultSms);
ReflectionHelpers.setField(
summaryProvider, "mDefaultBrowserPreferenceController", defaultBrowser);
ReflectionHelpers.setField(
summaryProvider, "mDefaultPhonePreferenceController", defaultPhone);
// all available
when(defaultSms.getDefaultAppLabel()).thenReturn("Sms1");
when(defaultBrowser.getDefaultAppLabel()).thenReturn("Browser1");
when(defaultPhone.getDefaultAppLabel()).thenReturn("Phone1");
summaryProvider.setListening(true);
verify(summaryLoader).setSummary(summaryProvider, "Browser1, Phone1, and Sms1");
// 2 available
when(defaultSms.getDefaultAppLabel()).thenReturn(null);
when(defaultBrowser.getDefaultAppLabel()).thenReturn("Browser1");
when(defaultPhone.getDefaultAppLabel()).thenReturn("Phone1");
summaryProvider.setListening(true);
verify(summaryLoader).setSummary(summaryProvider, "Browser1 and Phone1");
when(defaultSms.getDefaultAppLabel()).thenReturn("Sms1");
when(defaultBrowser.getDefaultAppLabel()).thenReturn(null);
when(defaultPhone.getDefaultAppLabel()).thenReturn("Phone1");
summaryProvider.setListening(true);
verify(summaryLoader).setSummary(summaryProvider, "Phone1 and Sms1");
when(defaultSms.getDefaultAppLabel()).thenReturn("Sms1");
when(defaultBrowser.getDefaultAppLabel()).thenReturn("Browser1");
when(defaultPhone.getDefaultAppLabel()).thenReturn(null);
summaryProvider.setListening(true);
verify(summaryLoader).setSummary(summaryProvider, "Browser1 and Sms1");
// 1 available
when(defaultSms.getDefaultAppLabel()).thenReturn(null);
when(defaultBrowser.getDefaultAppLabel()).thenReturn("Browser1");
when(defaultPhone.getDefaultAppLabel()).thenReturn(null);
summaryProvider.setListening(true);
verify(summaryLoader).setSummary(summaryProvider, "Browser1");
when(defaultSms.getDefaultAppLabel()).thenReturn("Sms1");
when(defaultBrowser.getDefaultAppLabel()).thenReturn(null);
when(defaultPhone.getDefaultAppLabel()).thenReturn(null);
summaryProvider.setListening(true);
verify(summaryLoader).setSummary(summaryProvider, "Sms1");
when(defaultSms.getDefaultAppLabel()).thenReturn(null);
when(defaultBrowser.getDefaultAppLabel()).thenReturn(null);
when(defaultPhone.getDefaultAppLabel()).thenReturn("Phone1");
summaryProvider.setListening(true);
verify(summaryLoader).setSummary(summaryProvider, "Phone1");
// None available
when(defaultSms.getDefaultAppLabel()).thenReturn(null);
when(defaultBrowser.getDefaultAppLabel()).thenReturn(null);
when(defaultPhone.getDefaultAppLabel()).thenReturn(null);
summaryProvider.setListening(true);
verify(summaryLoader, never()).setSummary(summaryProvider, eq(anyString()));
}
@Test
public void testNonIndexableKeys_existInXmlLayout() {
final Context context = spy(RuntimeEnvironment.application);
when(context.getApplicationContext()).thenReturn(context);
final UserManager userManager = mock(UserManager.class, RETURNS_DEEP_STUBS);
when(context.getSystemService(Context.USER_SERVICE))
.thenReturn(userManager);
when(userManager.getUserInfo(anyInt()).isRestricted()).thenReturn(true);
when(context.getSystemService(Context.TELEPHONY_SERVICE))
.thenReturn(mock(TelephonyManager.class));
when(context.getPackageManager())
.thenReturn(mock(PackageManager.class));
final List<String> niks = DefaultAppSettings.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(context);
final int xmlId = new DefaultAppSettings().getPreferenceScreenResId();
final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(context, xmlId);
assertThat(keys).containsAllIn(niks);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 The Android Open Source Project
* 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.
@@ -11,36 +11,25 @@
* 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.
* limitations under the License
*/
package com.android.settings.applications.defaultapps;
package com.android.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
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 android.app.role.RoleManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.provider.Settings;
import androidx.preference.Preference;
import com.android.settings.core.BasePreferenceController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -48,13 +37,9 @@ import org.robolectric.RobolectricTestRunner;
import java.util.Collections;
@RunWith(RobolectricTestRunner.class)
public class RolesPreferenceControllerTest {
public class DefaultAppsPreferenceControllerTest {
private static final String PREFERENCE_KEY = "roles";
private static final String DIFFERENT_PREFERENCE_KEY = "different";
private static final String PERMISSION_CONTROLLER_PACKAGE_NAME =
"com.android.permissioncontroller";
private static final String PREFERENCE_KEY = "DefaultApps";
private static final String BROWSER_PACKAGE_NAME = "com.example.browser1";
private static final String DIALER_PACKAGE_NAME = "com.example.dialer1";
@@ -73,6 +58,8 @@ public class RolesPreferenceControllerTest {
@Mock
private ApplicationInfo mSmsApplicationInfo;
private DefaultAppsPreferenceController mPreferenceController;
@Before
public void setUp() throws PackageManager.NameNotFoundException {
MockitoAnnotations.initMocks(this);
@@ -89,80 +76,13 @@ public class RolesPreferenceControllerTest {
when(mSmsApplicationInfo.loadLabel(mPackageManager)).thenReturn("Sms1");
when(mPackageManager.getApplicationInfo(eq(SMS_PACKAGE_NAME), anyInt())).thenReturn(
mSmsApplicationInfo);
mPreferenceController = new DefaultAppsPreferenceController(mContext, PREFERENCE_KEY);
}
@Test
public void getAvailabilityStatus_noPermissionController_shouldReturnUnsupportedOnDevice() {
when(mPackageManager.getPermissionControllerPackageName()).thenReturn(null);
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
assertThat(preferenceController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_hasPermissionController_shouldReturnAvailableUnsearchable() {
when(mPackageManager.getPermissionControllerPackageName())
.thenReturn(PERMISSION_CONTROLLER_PACKAGE_NAME);
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
assertThat(preferenceController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE_UNSEARCHABLE);
}
@Test
public void handlePreferenceTreeClick_differentKey_shouldReturnFalse() {
when(mPackageManager.getPermissionControllerPackageName())
.thenReturn(PERMISSION_CONTROLLER_PACKAGE_NAME);
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
Preference preference = mock(Preference.class);
when(preference.getKey()).thenReturn(DIFFERENT_PREFERENCE_KEY);
assertThat(preferenceController.handlePreferenceTreeClick(preference)).isFalse();
}
@Test
public void handlePreferenceTreeClick_sameKey_shouldReturnTrue() {
when(mPackageManager.getPermissionControllerPackageName())
.thenReturn(PERMISSION_CONTROLLER_PACKAGE_NAME);
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
Preference preference = mock(Preference.class);
when(preference.getKey()).thenReturn(PREFERENCE_KEY);
assertThat(preferenceController.handlePreferenceTreeClick(preference)).isTrue();
}
@Test
public void handlePreferenceTreeClick_noPermissionController_shouldNotStartActivity() {
when(mPackageManager.getPermissionControllerPackageName()).thenReturn(null);
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
Preference preference = mock(Preference.class);
when(preference.getKey()).thenReturn(PREFERENCE_KEY);
preferenceController.handlePreferenceTreeClick(preference);
verify(mContext, never()).startActivity(any(Intent.class));
}
@Test
public void handlePreferenceTreeClick_hasPermissionController_shouldStartActivityWithIntent() {
when(mPackageManager.getPermissionControllerPackageName())
.thenReturn(PERMISSION_CONTROLLER_PACKAGE_NAME);
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
Preference preference = mock(Preference.class);
when(preference.getKey()).thenReturn(PREFERENCE_KEY);
preferenceController.handlePreferenceTreeClick(preference);
ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intent.capture());
assertThat(intent.getValue().getAction())
.isEqualTo(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
assertThat(intent.getValue().getPackage()).isEqualTo(PERMISSION_CONTROLLER_PACKAGE_NAME);
public void isAvailable_shouldReturnTrue() {
assertThat(mPreferenceController.isAvailable()).isTrue();
}
@Test
@@ -173,10 +93,8 @@ public class RolesPreferenceControllerTest {
Collections.singletonList(DIALER_PACKAGE_NAME));
when(mRoleManager.getRoleHolders(RoleManager.ROLE_SMS)).thenReturn(
Collections.singletonList(SMS_PACKAGE_NAME));
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
assertThat(preferenceController.getSummary()).isEqualTo("Browser1, Phone1, and Sms1");
assertThat(mPreferenceController.getSummary()).isEqualTo("Browser1, Phone1, and Sms1");
}
@Test
@@ -186,10 +104,8 @@ public class RolesPreferenceControllerTest {
when(mRoleManager.getRoleHolders(RoleManager.ROLE_DIALER)).thenReturn(
Collections.singletonList(DIALER_PACKAGE_NAME));
when(mRoleManager.getRoleHolders(RoleManager.ROLE_SMS)).thenReturn(Collections.emptyList());
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
assertThat(preferenceController.getSummary()).isEqualTo("Browser1 and Phone1");
assertThat(mPreferenceController.getSummary()).isEqualTo("Browser1 and Phone1");
}
@Test
@@ -200,10 +116,8 @@ public class RolesPreferenceControllerTest {
Collections.emptyList());
when(mRoleManager.getRoleHolders(RoleManager.ROLE_SMS)).thenReturn(
Collections.singletonList(SMS_PACKAGE_NAME));
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
assertThat(preferenceController.getSummary()).isEqualTo("Browser1 and Sms1");
assertThat(mPreferenceController.getSummary()).isEqualTo("Browser1 and Sms1");
}
@Test
@@ -214,10 +128,8 @@ public class RolesPreferenceControllerTest {
Collections.singletonList(DIALER_PACKAGE_NAME));
when(mRoleManager.getRoleHolders(RoleManager.ROLE_SMS)).thenReturn(
Collections.singletonList(SMS_PACKAGE_NAME));
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
assertThat(preferenceController.getSummary()).isEqualTo("Phone1 and Sms1");
assertThat(mPreferenceController.getSummary()).isEqualTo("Phone1 and Sms1");
}
@Test
@@ -227,10 +139,8 @@ public class RolesPreferenceControllerTest {
when(mRoleManager.getRoleHolders(RoleManager.ROLE_DIALER)).thenReturn(
Collections.emptyList());
when(mRoleManager.getRoleHolders(RoleManager.ROLE_SMS)).thenReturn(Collections.emptyList());
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
assertThat(preferenceController.getSummary()).isEqualTo("Browser1");
assertThat(mPreferenceController.getSummary()).isEqualTo("Browser1");
}
@Test
@@ -240,10 +150,8 @@ public class RolesPreferenceControllerTest {
when(mRoleManager.getRoleHolders(RoleManager.ROLE_DIALER)).thenReturn(
Collections.singletonList(DIALER_PACKAGE_NAME));
when(mRoleManager.getRoleHolders(RoleManager.ROLE_SMS)).thenReturn(Collections.emptyList());
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
assertThat(preferenceController.getSummary()).isEqualTo("Phone1");
assertThat(mPreferenceController.getSummary()).isEqualTo("Phone1");
}
@Test
@@ -254,10 +162,8 @@ public class RolesPreferenceControllerTest {
Collections.emptyList());
when(mRoleManager.getRoleHolders(RoleManager.ROLE_SMS)).thenReturn(
Collections.singletonList(SMS_PACKAGE_NAME));
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
assertThat(preferenceController.getSummary()).isEqualTo("Sms1");
assertThat(mPreferenceController.getSummary()).isEqualTo("Sms1");
}
@Test
@@ -267,9 +173,7 @@ public class RolesPreferenceControllerTest {
when(mRoleManager.getRoleHolders(RoleManager.ROLE_DIALER)).thenReturn(
Collections.emptyList());
when(mRoleManager.getRoleHolders(RoleManager.ROLE_SMS)).thenReturn(Collections.emptyList());
RolesPreferenceController preferenceController = new RolesPreferenceController(mContext,
PREFERENCE_KEY);
assertThat(preferenceController.getSummary()).isNull();
assertThat(mPreferenceController.getSummary()).isNull();
}
}

View File

@@ -281,6 +281,13 @@ public final class AppInfoDashboardFragmentTest {
assertThat(mFragment.createPreferenceControllers(mShadowContext)).isNull();
}
@Test
public void getPreferenceControllers_exiting_shouldReturnNull() {
mFragment.mFinishing = true;
assertThat(mFragment.createPreferenceControllers(mShadowContext)).isNull();
}
@Test
public void getNumberOfUserWithPackageInstalled_twoUsersInstalled_shouldReturnTwo()
throws PackageManager.NameNotFoundException {

View File

@@ -1,77 +0,0 @@
/*
* 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.applications.defaultapps;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserManager;
import com.android.settings.testutils.FakeFeatureFactory;
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.RobolectricTestRunner;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class DefaultBrowserPickerTest {
private static final String TEST_APP_KEY = "";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private UserManager mUserManager;
@Mock
private PackageManager mPackageManager;
private DefaultBrowserPicker mPicker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest();
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mPicker = new DefaultBrowserPicker();
mPicker.onAttach(mActivity);
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
}
@Test
public void setDefaultAppKey_shouldUpdateDefaultBrowser() {
mPicker.setDefaultKey(TEST_APP_KEY);
verify(mPackageManager).setDefaultBrowserPackageNameAsUser(eq(TEST_APP_KEY), anyInt());
}
@Test
public void getDefaultAppKey_shouldReturnDefaultBrowser() {
mPicker.getDefaultKey();
verify(mPackageManager).getDefaultBrowserPackageNameAsUser(anyInt());
}
}

View File

@@ -1,231 +0,0 @@
/*
* 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.applications.defaultapps;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
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.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.os.UserManager;
import androidx.preference.Preference;
import com.android.settings.R;
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.RobolectricTestRunner;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class DefaultBrowserPreferenceControllerTest {
@Mock
private Context mContext;
@Mock
private UserManager mUserManager;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PackageManager mPackageManager;
private DefaultBrowserPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = new DefaultBrowserPreferenceController(mContext);
ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager);
}
@Test
public void isAvailable_noBrowser_shouldReturnFalse() {
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(null);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_hasBrowser_shouldReturnTrue() {
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(Collections.singletonList(createResolveInfo("com.test.pkg")));
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void getSoleAppLabel_hasNoApp_shouldNotReturnLabel() {
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(null);
final Preference pref = mock(Preference.class);
mController.updateState(pref);
verify(pref).setSummary(R.string.app_list_preference_none);
}
@Test
public void getDefaultAppLabel_hasAppWithMultipleResolvedInfo_shouldReturnLabel()
throws NameNotFoundException {
DefaultBrowserPreferenceController spyController = spy(mController);
doReturn(null).when(spyController).getDefaultAppIcon();
final List<ResolveInfo> resolveInfos = new ArrayList<>();
final CharSequence PACKAGE_NAME = "com.test.package";
// This ResolveInfo will return a non-null label from loadLabel.
final ResolveInfo info1 = createResolveInfo(PACKAGE_NAME.toString());
info1.nonLocalizedLabel = PACKAGE_NAME;
resolveInfos.add(info1);
// This ResolveInfo will return a null label from loadLabel.
final ResolveInfo info2 = createResolveInfo(PACKAGE_NAME.toString());
resolveInfos.add(info2);
when(mPackageManager.getDefaultBrowserPackageNameAsUser(anyInt())).thenReturn(null);
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(resolveInfos);
when(mPackageManager.getApplicationInfoAsUser(
eq(PACKAGE_NAME.toString()), anyInt(), anyInt()))
.thenReturn(createApplicationInfo(PACKAGE_NAME.toString()));
assertThat(spyController.getDefaultAppLabel()).isEqualTo(PACKAGE_NAME);
}
@Test
public void getDefaultApp_shouldGetDefaultBrowserPackage() {
mController.getDefaultAppInfo();
verify(mPackageManager).getDefaultBrowserPackageNameAsUser(anyInt());
}
@Test
public void getDefaultApp_shouldGetApplicationInfoAsUser() throws NameNotFoundException {
final String PACKAGE_NAME = "com.test.package";
when(mPackageManager.getDefaultBrowserPackageNameAsUser(anyInt())).thenReturn(PACKAGE_NAME);
mController.getDefaultAppInfo();
verify(mPackageManager).getApplicationInfoAsUser(eq(PACKAGE_NAME), anyInt(), anyInt());
}
@Test
public void isBrowserDefault_onlyApp_shouldReturnTrue() {
when(mPackageManager.getDefaultBrowserPackageNameAsUser(anyInt())).thenReturn(null);
final List<ResolveInfo> resolveInfos = new ArrayList<>();
final String PACKAGE_ONE = "pkg";
resolveInfos.add(createResolveInfo(PACKAGE_ONE));
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(resolveInfos);
assertThat(mController.isBrowserDefault("pkg", 0)).isTrue();
}
@Test
public void getCandidates_shouldNotIncludeDuplicatePackageName() throws NameNotFoundException {
final List<ResolveInfo> resolveInfos = new ArrayList<>();
final String PACKAGE_ONE = "com.first.package";
final String PACKAGE_TWO = "com.second.package";
resolveInfos.add(createResolveInfo(PACKAGE_ONE));
resolveInfos.add(createResolveInfo(PACKAGE_TWO));
resolveInfos.add(createResolveInfo(PACKAGE_ONE));
resolveInfos.add(createResolveInfo(PACKAGE_TWO));
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(resolveInfos);
when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_ONE), anyInt(), anyInt()))
.thenReturn(createApplicationInfo(PACKAGE_ONE));
when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_TWO), anyInt(), anyInt()))
.thenReturn(createApplicationInfo(PACKAGE_TWO));
final List<ResolveInfo> defaultBrowserInfo =
DefaultBrowserPreferenceController.getCandidates(mPackageManager, 0 /* userId */);
assertThat(defaultBrowserInfo.size()).isEqualTo(2);
}
@Test
public void getCandidates_shouldQueryActivityWithMatchAll() {
DefaultBrowserPreferenceController.getCandidates(mPackageManager, 0 /* userId */);
verify(mPackageManager).queryIntentActivitiesAsUser(
any(Intent.class), eq(PackageManager.MATCH_ALL), eq(0) /* userId */);
}
@Test
public void getOnlyAppIcon_shouldGetApplicationInfoAsUser() throws NameNotFoundException {
final List<ResolveInfo> resolveInfos = new ArrayList<>();
final String PACKAGE_NAME = "com.test.package";
resolveInfos.add(createResolveInfo(PACKAGE_NAME));
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(resolveInfos);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
when(mContext.getResources()).thenReturn(mock(Resources.class));
mController.getOnlyAppIcon();
verify(mPackageManager).getApplicationInfoAsUser(
eq(PACKAGE_NAME), eq(0) /* flags */, eq(0) /* userId */);
}
@Test
public void hasBrowserPreference_shouldQueryIntentActivitiesAsUser() {
when(mContext.getPackageManager()).thenReturn(mPackageManager);
DefaultBrowserPreferenceController
.hasBrowserPreference("com.test.package", mContext, 0 /* userId */);
verify(mPackageManager).queryIntentActivitiesAsUser(
any(Intent.class), eq(0) /* flags */, eq(0) /* userId */);
}
private ResolveInfo createResolveInfo(String packageName) {
final ResolveInfo info = new ResolveInfo();
info.handleAllWebDataURI = true;
info.activityInfo = new ActivityInfo();
info.activityInfo.packageName = packageName;
info.activityInfo.applicationInfo = createApplicationInfo(packageName);
return info;
}
private ApplicationInfo createApplicationInfo(String packageName) {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = packageName;
return info;
}
}

View File

@@ -1,97 +0,0 @@
/*
* 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.applications.defaultapps;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.app.role.RoleManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.os.UserManager;
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.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@RunWith(RobolectricTestRunner.class)
public class DefaultEmergencyPickerTest {
private static final String TAG = DefaultEmergencyPickerTest.class.getSimpleName();
private static final String TEST_APP_KEY = "test_app";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private UserManager mUserManager;
@Mock
private PackageManager mPackageManager;
@Mock
private RoleManager mRoleManager;
private DefaultEmergencyPicker mPicker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
shadowApplication.setSystemService(Context.ROLE_SERVICE, mRoleManager);
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mPicker = spy(new DefaultEmergencyPicker());
mPicker.onAttach(mActivity);
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
when(mPicker.getContext()).thenReturn(RuntimeEnvironment.application);
}
@Test
public void setDefaultAppKey_shouldUpdateDefault() {
mPicker.setDefaultKey(TEST_APP_KEY);
verify(mRoleManager).addRoleHolderAsUser(
eq(RoleManager.ROLE_EMERGENCY),
eq(TEST_APP_KEY),
eq(0),
any(UserHandle.class),
any(Executor.class),
any(Consumer.class));
}
@Test
public void getDefaultAppKey_shouldReturnDefault() {
when(mRoleManager.getRoleHolders(RoleManager.ROLE_EMERGENCY))
.thenReturn(Arrays.asList(TEST_APP_KEY));
assertThat(mPicker.getDefaultKey()).isEqualTo(TEST_APP_KEY);
}
}

View File

@@ -1,168 +0,0 @@
/*
* 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.applications.defaultapps;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
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.Activity;
import android.app.AppOpsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.os.Build;
import android.os.UserManager;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.applications.DefaultAppInfo;
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.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class DefaultHomePickerTest {
private static final String TEST_APP_KEY = "com.android.settings/DefaultEmergencyPickerTest";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private UserManager mUserManager;
@Mock
private AppOpsManager mAppOpsManager;
@Mock
private PackageManager mPackageManager;
private Context mContext;
private DefaultHomePicker mPicker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest();
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
when(mActivity.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
when(mActivity.getApplicationContext()).thenReturn(RuntimeEnvironment.application);
mPicker = spy(new DefaultHomePicker());
mPicker.onAttach((Context) mActivity);
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
mContext = spy(RuntimeEnvironment.application);
doReturn(mContext).when(mPicker).getContext();
}
@Test
public void setDefaultAppKey_shouldUpdateDefault() {
assertThat(mPicker.setDefaultKey(TEST_APP_KEY)).isTrue();
verify(mPackageManager).replacePreferredActivity(any(IntentFilter.class),
anyInt(), any(ComponentName[].class), any(ComponentName.class));
verify(mContext).startActivity(any());
}
@Test
public void getDefaultAppKey_shouldReturnDefault() {
final ComponentName cn = mock(ComponentName.class);
when(mPackageManager.getHomeActivities(anyList())).thenReturn(cn);
mPicker.getDefaultKey();
verify(cn).flattenToString();
}
@Test
public void getCandidates_allLaunchersAvailableIfNoManagedProfile() {
addLaunchers();
List<DefaultAppInfo> candidates = mPicker.getCandidates();
assertThat(candidates.size()).isEqualTo(2);
assertThat(candidates.get(0).summary).isNull();
assertThat(candidates.get(0).enabled).isTrue();
assertThat(candidates.get(1).summary).isNull();
assertThat(candidates.get(1).enabled).isTrue();
}
@Test
public void getCandidates_onlyLollipopPlusLaunchersAvailableIfManagedProfile() {
List<UserInfo> profiles = new ArrayList<>();
profiles.add(new UserInfo(/*id=*/ 10, "TestUserName", UserInfo.FLAG_MANAGED_PROFILE));
when(mUserManager.getProfiles(anyInt())).thenReturn(profiles);
addLaunchers();
List<DefaultAppInfo> candidates = mPicker.getCandidates();
assertThat(candidates.size()).isEqualTo(2);
DefaultAppInfo lollipopPlusLauncher = candidates.get(0);
assertThat(lollipopPlusLauncher.summary).isNull();
assertThat(lollipopPlusLauncher.enabled).isTrue();
DefaultAppInfo preLollipopLauncher = candidates.get(1);
assertThat(preLollipopLauncher.summary).isNotNull();
assertThat(preLollipopLauncher.enabled).isFalse();
}
private ResolveInfo createLauncher(
String packageName, String className, int targetSdk) throws NameNotFoundException {
ResolveInfo launcher = new ResolveInfo();
launcher.activityInfo = new ActivityInfo();
launcher.activityInfo.packageName = packageName;
launcher.activityInfo.name = className;
ApplicationInfo launcherAppInfo = new ApplicationInfo();
launcherAppInfo.targetSdkVersion = targetSdk;
when(mPackageManager.getApplicationInfo(eq(launcher.activityInfo.packageName), anyInt()))
.thenReturn(launcherAppInfo);
return launcher;
}
private void addLaunchers() {
doAnswer(invocation -> {
// The result of this method is stored in the first parameter...
List<ResolveInfo> parameter = (List<ResolveInfo>) invocation.getArguments()[0];
parameter.add(createLauncher(
"package.1", "LollipopPlusLauncher", Build.VERSION_CODES.LOLLIPOP));
parameter.add(createLauncher(
"package.2", "PreLollipopLauncher", Build.VERSION_CODES.KITKAT));
return null;
})
.when(mPackageManager).getHomeActivities(anyList());
}
}

View File

@@ -1,170 +0,0 @@
/*
* 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.applications.defaultapps;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.atLeastOnce;
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.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserManager;
import androidx.preference.Preference;
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.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class DefaultHomePreferenceControllerTest {
private static final String TEST_PACKAGE = "test.pkg";
private static final String TEST_CLASS = "class";
@Mock
private UserManager mUserManager;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PackageManager mPackageManager;
private Context mContext;
private DefaultHomePreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = spy(new DefaultHomePreferenceController(mContext));
ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager);
}
@Test
public void testDefaultHome_byDefault_shouldBeShown() {
assertThat(mController.isAvailable()).isTrue();
}
@Test
@Config(qualifiers = "mcc999")
public void testDefaultHome_ifDisabled_shouldNotBeShown() {
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void getDefaultApp_shouldGetDefaultBrowserPackage() {
assertThat(mController.getDefaultAppInfo()).isNotNull();
verify(mPackageManager).getHomeActivities(anyList());
}
@Test
public void getDefaultApp_noDefaultHome_shouldReturnNull() {
when(mPackageManager.getHomeActivities(anyList())).thenReturn(null);
assertThat(mController.getDefaultAppInfo()).isNull();
}
@Test
public void updateState_noDefaultApp_shouldAskPackageManagerForOnlyApp() {
when(mPackageManager.getHomeActivities(anyList())).thenReturn(null);
mController.updateState(mock(Preference.class));
verify(mPackageManager, atLeastOnce()).getHomeActivities(anyList());
}
@Test
public void testIsHomeDefault_noDefaultSet_shouldReturnTrue() {
when(mPackageManager.getHomeActivities(anyList())).thenReturn(null);
assertThat(DefaultHomePreferenceController.isHomeDefault(TEST_PACKAGE, mPackageManager))
.isTrue();
}
@Test
public void testIsHomeDefault_defaultSetToPkg_shouldReturnTrue() {
final String pkgName = TEST_PACKAGE;
final ComponentName defaultHome = new ComponentName(pkgName, TEST_CLASS);
when(mPackageManager.getHomeActivities(anyList())).thenReturn(defaultHome);
assertThat(DefaultHomePreferenceController.isHomeDefault(pkgName, mPackageManager))
.isTrue();
}
@Test
public void testIsHomeDefault_defaultSetToOtherPkg_shouldReturnFalse() {
final String pkgName = TEST_PACKAGE;
final ComponentName defaultHome = new ComponentName("not" + pkgName, TEST_CLASS);
when(mPackageManager.getHomeActivities(anyList())).thenReturn(defaultHome);
assertThat(DefaultHomePreferenceController.isHomeDefault(pkgName, mPackageManager))
.isFalse();
}
@Test
public void testGetSettingIntent_homeHasNoSetting_shouldNotReturnSettingIntent() {
when(mPackageManager.getHomeActivities(anyList()))
.thenReturn(new ComponentName(TEST_PACKAGE, TEST_CLASS));
when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
.thenReturn(null);
assertThat(mController.getSettingIntent(mController.getDefaultAppInfo())).isNull();
}
@Test
public void testGetSettingIntent_homeHasOneSetting_shouldReturnSettingIntent() {
when(mPackageManager.getHomeActivities(anyList()))
.thenReturn(new ComponentName(TEST_PACKAGE, TEST_CLASS));
final ResolveInfo info = mock(ResolveInfo.class);
info.activityInfo = mock(ActivityInfo.class);
info.activityInfo.name = TEST_CLASS;
info.activityInfo.applicationInfo = mock(ApplicationInfo.class);
info.activityInfo.applicationInfo.packageName = TEST_PACKAGE;
when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
.thenReturn(info);
Intent intent = mController.getSettingIntent(mController.getDefaultAppInfo());
assertThat(intent).isNotNull();
assertThat(intent.getPackage()).isEqualTo(TEST_PACKAGE);
}
@Test
public void testGetSettingIntent_noDefauldHome_shouldReturnNull() {
when(mPackageManager.getHomeActivities(anyList())).thenReturn(null);
assertThat(mController.getSettingIntent(mController.getDefaultAppInfo())).isNull();
}
}

View File

@@ -1,104 +0,0 @@
/*
* 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.applications.defaultapps;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserManager;
import com.android.settings.fuelgauge.BatteryUtils;
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.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class DefaultPhonePickerTest {
private static final String TEST_APP_KEY = "com.android.settings/PickerTest";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private UserManager mUserManager;
@Mock
private DefaultPhonePicker.DefaultKeyUpdater mDefaultKeyUpdater;
@Mock
private PackageManager mPackageManager;
@Mock
private BatteryUtils mBatteryUtils;
private DefaultPhonePicker mPicker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
when(mActivity.getSystemService(Context.TELECOM_SERVICE)).thenReturn(null);
mPicker = spy(new DefaultPhonePicker());
mPicker.onAttach(mActivity);
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
ReflectionHelpers.setField(mPicker, "mDefaultKeyUpdater", mDefaultKeyUpdater);
ReflectionHelpers.setField(mPicker, "mBatteryUtils", mBatteryUtils);
doReturn(RuntimeEnvironment.application).when(mPicker).getContext();
}
@Test
public void getSystemDefaultPackage_shouldAskDefaultKeyUpdater() {
mPicker.getSystemDefaultKey();
verify(mDefaultKeyUpdater).getSystemDialerPackage();
}
@Test
public void setDefaultAppKey_shouldUpdateDefault() {
mPicker.setDefaultKey(TEST_APP_KEY);
verify(mDefaultKeyUpdater)
.setDefaultDialerApplication(any(Context.class), eq(TEST_APP_KEY), anyInt());
}
@Test
public void getDefaultAppKey_shouldReturnDefault() {
mPicker.getDefaultKey();
verify(mDefaultKeyUpdater).getDefaultDialerApplication(any(Context.class), anyInt());
}
@Test
public void setDefaultKey_shouldUnrestrictApp() {
mPicker.setDefaultKey(TEST_APP_KEY);
verify(mBatteryUtils).clearForceAppStandby(TEST_APP_KEY);
}
}

View File

@@ -1,94 +0,0 @@
/*
* 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.applications.defaultapps;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserManager;
import com.android.settings.fuelgauge.BatteryUtils;
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.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class DefaultSmsPickerTest {
private static final String TEST_APP_KEY = "com.android.settings/PickerTest";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
private UserManager mUserManager;
@Mock
private DefaultSmsPicker.DefaultKeyUpdater mDefaultKeyUpdater;
@Mock
private PackageManager mPackageManager;
@Mock
private BatteryUtils mBatteryUtils;
private DefaultSmsPicker mPicker;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mPicker = spy(new DefaultSmsPicker());
mPicker.onAttach(mActivity);
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
ReflectionHelpers.setField(mPicker, "mDefaultKeyUpdater", mDefaultKeyUpdater);
ReflectionHelpers.setField(mPicker, "mBatteryUtils", mBatteryUtils);
doReturn(RuntimeEnvironment.application).when(mPicker).getContext();
}
@Test
public void setDefaultAppKey_shouldUpdateDefault() {
mPicker.setDefaultKey(TEST_APP_KEY);
verify(mDefaultKeyUpdater).setDefaultApplication(any(Context.class), eq(TEST_APP_KEY));
}
@Test
public void getDefaultAppKey_shouldReturnDefault() {
mPicker.getDefaultKey();
verify(mDefaultKeyUpdater).getDefaultApplication(any(Context.class));
}
@Test
public void setDefaultKey_shouldUnrestrictApp() {
mPicker.setDefaultKey(TEST_APP_KEY);
verify(mBatteryUtils).clearForceAppStandby(TEST_APP_KEY);
}
}

View File

@@ -14,13 +14,11 @@
* limitations under the License.
*/
package com.android.settings.applications.defaultapps;
package com.android.settings.applications.specialaccess;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -28,17 +26,12 @@ import android.content.pm.PackageManager;
import android.nfc.NfcAdapter;
import android.os.UserManager;
import androidx.preference.Preference;
import com.android.settings.nfc.PaymentBackend;
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.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
@@ -52,11 +45,8 @@ public class DefaultPaymentSettingsPreferenceControllerTest {
private UserManager mUserManager;
@Mock
private PackageManager mPackageManager;
@Mock
private PaymentBackend mPaymentBackend;
private DefaultPaymentSettingsPreferenceController mController;
private Preference mPreference;
@Before
public void setUp() {
@@ -64,11 +54,9 @@ public class DefaultPaymentSettingsPreferenceControllerTest {
when(mContext.getApplicationContext()).thenReturn(mContext);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = new DefaultPaymentSettingsPreferenceController(mContext);
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
mController = new DefaultPaymentSettingsPreferenceController(mContext, "key");
ReflectionHelpers.setField(mController, "mNfcAdapter", mNfcAdapter);
mPreference = new Preference(RuntimeEnvironment.application);
}
@Test
@@ -88,17 +76,4 @@ public class DefaultPaymentSettingsPreferenceControllerTest {
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void updateState_shouldSetSummaryToDefaultPaymentApp() {
final PaymentBackend.PaymentAppInfo defaultApp = mock(PaymentBackend.PaymentAppInfo.class);
defaultApp.label = "test_payment_app";
when(mPaymentBackend.getDefaultApp()).thenReturn(defaultApp);
ReflectionHelpers.setField(mController, "mPaymentBackend", mPaymentBackend);
mController.updateState(mPreference);
verify(mPaymentBackend).refresh();
assertThat(mPreference.getSummary()).isEqualTo(defaultApp.label);
}
}

View File

@@ -209,6 +209,18 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{
verify(mBluetoothAdapter, never()).unregisterMetadataListener(mBluetoothDevice);
}
@Test
public void onDestroy_isAvailable_recycleBitmap() {
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET))
.thenReturn("true");
mController.mIconCache.put(ICON_URI, mBitmap);
mController.onDestroy();
assertThat(mController.mIconCache).isEmpty();
verify(mBitmap).recycle();
}
private void assertBatteryLevel(LinearLayout linearLayout, int batteryLevel) {
final TextView textView = linearLayout.findViewById(R.id.bt_battery_summary);
assertThat(textView.getText().toString()).isEqualTo(

View File

@@ -39,14 +39,13 @@ 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 java.util.ArrayList;
import java.util.List;
import org.robolectric.annotation.Config;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class TopLevelDisplayPreferenceControllerTest {
private Context mContext;
@@ -88,6 +87,19 @@ public class TopLevelDisplayPreferenceControllerTest {
.isEqualTo(mContext.getText(R.string.display_dashboard_summary));
}
@Test
public void getSummary_hasWallpaperWithStyles_shouldReturnWallpaperSummary() {
when(mContext.getString(R.string.config_styles_and_wallpaper_picker_class))
.thenReturn("any.nonempty.class");
final List<ResolveInfo> resolveInfos = new ArrayList<>();
resolveInfos.add(mock(ResolveInfo.class));
when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt()))
.thenReturn(resolveInfos);
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.display_dashboard_summary_with_style));
}
@Test
public void getSummary_hasWallpaper_shouldReturnNoWallpaperSummary() {
final List<ResolveInfo> resolveInfos = new ArrayList<>();

View File

@@ -18,74 +18,132 @@ package com.android.settings.display;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowPackageManager;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {SettingsShadowResources.class})
public class WallpaperPreferenceControllerTest {
private static final String WALLPAPER_PACKAGE = "TestPkg";
private static final String WALLPAPER_CLASS = "TestCls";
private static final String TEST_KEY = "test_key";
@Mock
private Context mContext;
@Mock
private PackageManager mPackageManager;
private Intent mWallpaperIntent;
private Intent mStylesAndWallpaperIntent;
private FragmentActivity mContext;
private ShadowPackageManager mShadowPackageManager;
private WallpaperPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getString(R.string.config_wallpaper_picker_package))
.thenReturn(WALLPAPER_PACKAGE);
when(mContext.getString(R.string.config_wallpaper_picker_class))
.thenReturn(WALLPAPER_CLASS);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
mContext = Robolectric.buildActivity(FragmentActivity.class).get();
SettingsShadowResources.overrideResource(
R.string.config_wallpaper_picker_package, "bogus.package.for.testing");
SettingsShadowResources.overrideResource(
R.string.config_styles_and_wallpaper_picker_class, "bogus.package.class");
mWallpaperIntent = new Intent().setComponent(new ComponentName(
mContext.getString(R.string.config_wallpaper_picker_package),
mContext.getString(R.string.config_wallpaper_picker_class)));
mStylesAndWallpaperIntent = new Intent().setComponent(new ComponentName(
mContext.getString(R.string.config_wallpaper_picker_package),
mContext.getString(R.string.config_styles_and_wallpaper_picker_class)));
mShadowPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mController = new WallpaperPreferenceController(mContext, TEST_KEY);
}
@Test
public void isAvailable_wallpaperPickerEnabled_shouldReturnTrue() {
final List<ResolveInfo> resolveInfos = new ArrayList<>();
resolveInfos.add(mock(ResolveInfo.class));
when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt()))
.thenReturn(resolveInfos);
mShadowPackageManager.setResolveInfosForIntent(
mWallpaperIntent, Lists.newArrayList(mock(ResolveInfo.class)));
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_wallpaperPickerDisabled_shouldReturnFalse() {
when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt())).thenReturn(null);
assertThat(mController.isAvailable()).isFalse();
final List<ResolveInfo> resolveInfos = new ArrayList<>();
when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt()))
.thenReturn(resolveInfos);
mShadowPackageManager.setResolveInfosForIntent(
mWallpaperIntent, Lists.newArrayList());
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void areStylesAvailable_noComponentSpecified() {
SettingsShadowResources.overrideResource(
R.string.config_styles_and_wallpaper_picker_class, "");
mShadowPackageManager.setResolveInfosForIntent(
mStylesAndWallpaperIntent, Lists.newArrayList());
assertThat(mController.areStylesAvailable()).isFalse();
}
@Test
public void areStylesAvailable_componentUnresolveable() {
mShadowPackageManager.setResolveInfosForIntent(
mStylesAndWallpaperIntent, Lists.newArrayList());
assertThat(mController.areStylesAvailable()).isFalse();
}
@Test
public void areStylesAvailable_componentResolved() {
mShadowPackageManager.setResolveInfosForIntent(
mStylesAndWallpaperIntent,
Lists.newArrayList(mock(ResolveInfo.class)));
assertThat(mController.areStylesAvailable()).isTrue();
}
@Test
public void handlePreferenceTreeClick_wallpaperOnly() {
mShadowPackageManager.setResolveInfosForIntent(
mWallpaperIntent, Lists.newArrayList(mock(ResolveInfo.class)));
mShadowPackageManager.setResolveInfosForIntent(
mStylesAndWallpaperIntent, Lists.newArrayList());
Preference preference = new Preference(mContext);
preference.setKey(TEST_KEY);
mController.handlePreferenceTreeClick(preference);
assertThat(Shadows.shadowOf(mContext)
.getNextStartedActivityForResult().intent.getComponent().getClassName())
.isEqualTo(mContext.getString(R.string.config_wallpaper_picker_class));
}
@Test
public void handlePreferenceTreeClick_stylesAndWallpaper() {
mShadowPackageManager.setResolveInfosForIntent(
mWallpaperIntent, Lists.newArrayList());
mShadowPackageManager.setResolveInfosForIntent(
mStylesAndWallpaperIntent, Lists.newArrayList(mock(ResolveInfo.class)));
Preference preference = new Preference(mContext);
preference.setKey(TEST_KEY);
mController.handlePreferenceTreeClick(preference);
assertThat(Shadows.shadowOf(mContext)
.getNextStartedActivityForResult().intent.getComponent().getClassName())
.isEqualTo(mContext.getString(R.string.config_styles_and_wallpaper_picker_class));
}
}

View File

@@ -22,12 +22,15 @@ import static com.android.settings.homepage.contextualcards.ContextualCardLoader
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.net.Uri;
@@ -182,8 +185,10 @@ public class ContextualCardLoaderTest {
mContextualCardLoader.getDisplayableCards(new ArrayList<>());
verify(mFakeFeatureFactory.mContextualCardFeatureProvider).logContextualCardDisplay(
anyList(), anyList());
verify(mFakeFeatureFactory.metricsFeatureProvider).action(any(),
eq(SettingsEnums.ACTION_CONTEXTUAL_CARD_SHOW), any(String.class));
verify(mFakeFeatureFactory.metricsFeatureProvider).action(any(),
eq(SettingsEnums.ACTION_CONTEXTUAL_CARD_NOT_SHOW), any(String.class));
}
@Test

View File

@@ -0,0 +1,100 @@
/*
* 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.homepage.contextualcards.logging;
import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import com.android.settings.homepage.contextualcards.ContextualCard;
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 ContextualCardLogUtilsTest {
private static final String TEST_URI = "content://test/test2";
private static final double TEST_SCORE = 0.12345f;
private static final ContextualCard TEST_CARD =
new ContextualCard.Builder()
.setSliceUri(Uri.parse(TEST_URI))
.setRankingScore(TEST_SCORE)
.build();
@Test
public void parseCardDismissLog_notValid_returnNull() {
assertThat(ContextualCardLogUtils.parseCardDismissLog(TEST_URI + "|" + TEST_URI)).isNull();
}
@Test
public void parseCardDismissLog_isValid_returnCorrectData() {
final String log = ContextualCardLogUtils.buildCardDismissLog(TEST_CARD);
final ContextualCardLogUtils.CardLog cardLog = ContextualCardLogUtils.parseCardDismissLog(
log);
assertThat(cardLog.getSliceUri()).isEqualTo(TEST_URI);
assertThat(cardLog.getRankingScore()).isEqualTo(TEST_SCORE);
}
@Test
public void parseCardClickLog_isValid_returnCorrectData() {
final int row = 1;
final int target = 2;
final int position = 3;
final String log = ContextualCardLogUtils.buildCardClickLog(TEST_CARD, row, target,
position);
final ContextualCardLogUtils.CardClickLog cardClickLog =
ContextualCardLogUtils.parseCardClickLog(log);
assertThat(cardClickLog.getSliceUri()).isEqualTo(TEST_URI);
assertThat(cardClickLog.getRankingScore()).isEqualTo(TEST_SCORE);
assertThat(cardClickLog.getSliceRow()).isEqualTo(row);
assertThat(cardClickLog.getSliceTapTarget()).isEqualTo(
ContextualCardLogUtils.actionTypeToTapTarget(target));
assertThat(cardClickLog.getUiPosition()).isEqualTo(position);
}
@Test
public void parseCardClickList_isValid_returnCorrectData() {
final ContextualCard testcard =
new ContextualCard.Builder()
.setSliceUri(Uri.parse("testtest"))
.setRankingScore(-1d)
.build();
final List<ContextualCard> cardList = new ArrayList<>();
cardList.add(TEST_CARD);
cardList.add(testcard);
final String log = ContextualCardLogUtils.buildCardListLog(cardList);
final List<ContextualCardLogUtils.CardLog> cardClickLogList =
ContextualCardLogUtils.parseCardListLog(log);
assertThat(cardClickLogList.size()).isEqualTo(2);
assertThat(cardClickLogList.get(0).getSliceUri()).isEqualTo(TEST_URI);
assertThat(cardClickLogList.get(0).getRankingScore()).isEqualTo(TEST_SCORE);
assertThat(cardClickLogList.get(1).getSliceUri()).isEqualTo("testtest");
assertThat(cardClickLogList.get(1).getRankingScore()).isEqualTo(-1d);
}
}

View File

@@ -18,17 +18,23 @@ package com.android.settings.homepage.contextualcards.slices;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import com.android.settings.R;
import com.android.settings.homepage.contextualcards.CardContentProvider;
import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
import com.android.settings.homepage.contextualcards.ContextualCard;
@@ -48,6 +54,7 @@ import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity;
import org.robolectric.shadows.ShadowContentResolver;
import org.robolectric.shadows.androidx.fragment.FragmentController;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class SliceContextualCardControllerTest {
@@ -91,15 +98,17 @@ public class SliceContextualCardControllerTest {
cr.close();
assertThat(qryDismissed).isEqualTo(1);
verify(mFeatureFactory.mContextualCardFeatureProvider).logContextualCardDismiss(card);
verify(mFeatureFactory.metricsFeatureProvider).action(any(),
eq(SettingsEnums.ACTION_CONTEXTUAL_CARD_DISMISS), any(String.class));
}
@Test
public void onDismissed_noFeedbackEmail_shouldNotShowFeedbackDialog() {
public void onDismissed_feedbackDisabled_shouldNotShowFeedbackDialog() {
mResolver.insert(CardContentProvider.REFRESH_CARD_URI, generateOneRow());
final ContextualCardsFragment fragment =
FragmentController.of(new ContextualCardsFragment()).create().get();
final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity());
doReturn(false).when(mController).isFeedbackEnabled(anyString());
mController.onDismissed(getTestSliceCard());
@@ -107,12 +116,12 @@ public class SliceContextualCardControllerTest {
}
@Test
@Config(qualifiers = "mcc999")
public void onDismissed_hasFeedbackEmail_shouldShowFeedbackDialog() {
public void onDismissed_feedbackEnabled_shouldShowFeedbackDialog() {
mResolver.insert(CardContentProvider.REFRESH_CARD_URI, generateOneRow());
final ContextualCardsFragment fragment =
FragmentController.of(new ContextualCardsFragment()).create().get();
final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity());
doReturn(true).when(mController).isFeedbackEnabled(anyString());
mController.onDismissed(getTestSliceCard());
@@ -120,6 +129,40 @@ public class SliceContextualCardControllerTest {
.isEqualTo(ContextualCardFeedbackDialog.class.getName());
}
@Test
@Config(qualifiers = "mcc999")
public void isFeedbackEnabled_hasFeedbackEmail_debug_returnTrue() {
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
final String email = mContext.getString(R.string.config_contextual_card_feedback_email);
assertThat(mController.isFeedbackEnabled(email)).isTrue();
}
@Test
@Config(qualifiers = "mcc999")
public void isFeedbackEnabled_hasFeedbackEmail_user_returnFalse() {
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", false);
final String email = mContext.getString(R.string.config_contextual_card_feedback_email);
assertThat(mController.isFeedbackEnabled(email)).isFalse();
}
@Test
public void isFeedbackEnabled_noFeedbackEmail_debug_returnFalse() {
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
final String email = mContext.getString(R.string.config_contextual_card_feedback_email);
assertThat(mController.isFeedbackEnabled(email)).isFalse();
}
@Test
public void isFeedbackEnabled_noFeedbackEmail_user_returnFalse() {
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", false);
final String email = mContext.getString(R.string.config_contextual_card_feedback_email);
assertThat(mController.isFeedbackEnabled(email)).isFalse();
}
private ContentValues generateOneRow() {
final ContentValues values = new ContentValues();
values.put(CardDatabaseHelper.CardColumns.NAME, TEST_CARD_NAME);

View File

@@ -28,14 +28,12 @@ import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ViewFlipper;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.slice.Slice;
import androidx.slice.widget.SliceView;
import com.android.settings.R;
import com.android.settings.homepage.contextualcards.ContextualCard;
@@ -116,16 +114,15 @@ public class SliceContextualCardRendererTest {
}
@Test
public void bindView_isPendingDismiss_shouldFlipToDismissalView() {
public void bindView_isPendingDismiss_shouldShowDismissalView() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
final View dismissalView = viewHolder.itemView.findViewById(R.id.dismissal_view);
final ContextualCard card = buildContextualCard(
TEST_SLICE_URI).mutate().setIsPendingDismiss(true).build();
mRenderer.bindView(viewHolder, card);
assertThat(viewFlipper.getCurrentView()).isEqualTo(dismissalView);
assertThat(dismissalView.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
@@ -140,24 +137,29 @@ public class SliceContextualCardRendererTest {
}
@Test
public void viewClick_keepCard_shouldFlipBackToSlice() {
public void viewClick_keepCard_shouldShowSlice() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
final View sliceView = viewHolder.itemView.findViewById(R.id.slice_view);
final View dismissalView = viewHolder.itemView.findViewById(R.id.dismissal_view);
final Button btnKeep = viewHolder.itemView.findViewById(R.id.keep);
final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
viewFlipper.setDisplayedChild(1);
final ContextualCard card = buildContextualCard(
TEST_SLICE_URI).mutate().setIsPendingDismiss(true).build();
mRenderer.bindView(viewHolder, card);
btnKeep.performClick();
assertThat(viewFlipper.getCurrentView()).isInstanceOf(SliceView.class);
assertThat(dismissalView.getVisibility()).isEqualTo(View.GONE);
assertThat(sliceView.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
public void viewClick_keepCard_shouldRemoveViewHolderFromSet() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
final Button btnKeep = viewHolder.itemView.findViewById(R.id.keep);
mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
mRenderer.mFlippedCardSet.add(viewHolder);
final ContextualCard card = buildContextualCard(
TEST_SLICE_URI).mutate().setIsPendingDismiss(true).build();
mRenderer.bindView(viewHolder, card);
assertThat(mRenderer.mFlippedCardSet).contains(viewHolder);
btnKeep.performClick();
@@ -168,11 +170,12 @@ public class SliceContextualCardRendererTest {
public void viewClick_removeCard_shouldRemoveViewHolderFromSet() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
final Button btnRemove = viewHolder.itemView.findViewById(R.id.remove);
final ContextualCard contextualCard = buildContextualCard(TEST_SLICE_URI);
mRenderer.bindView(viewHolder, contextualCard);
final ContextualCard card = buildContextualCard(
TEST_SLICE_URI).mutate().setIsPendingDismiss(true).build();
mRenderer.bindView(viewHolder, card);
assertThat(mRenderer.mFlippedCardSet).contains(viewHolder);
doReturn(mController).when(mControllerRendererPool).getController(mActivity,
ContextualCard.CardType.SLICE);
mRenderer.mFlippedCardSet.add(viewHolder);
btnRemove.performClick();
@@ -195,16 +198,19 @@ public class SliceContextualCardRendererTest {
}
@Test
public void onStop_cardIsFlipped_shouldFlipBack() {
public void onStop_cardIsInDismissalView_shouldResetToSliceView() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
viewFlipper.setDisplayedChild(1);
mRenderer.mFlippedCardSet.add(viewHolder);
final View sliceView = viewHolder.itemView.findViewById(R.id.slice_view);
final View dismissalView = viewHolder.itemView.findViewById(R.id.dismissal_view);
final ContextualCard card = buildContextualCard(
TEST_SLICE_URI).mutate().setIsPendingDismiss(true).build();
mRenderer.bindView(viewHolder, card);
assertThat(mRenderer.mFlippedCardSet).contains(viewHolder);
mRenderer.onStop();
assertThat(viewFlipper.getCurrentView()).isInstanceOf(SliceView.class);
assertThat(sliceView.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(dismissalView.getVisibility()).isEqualTo(View.GONE);
}
private RecyclerView.ViewHolder getSliceViewHolder() {

View File

@@ -28,7 +28,6 @@ import static org.mockito.Mockito.verify;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ViewFlipper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -68,7 +67,7 @@ public class SwipeDismissalDelegateTest {
activityController.create();
mRecyclerView = new RecyclerView(mActivity);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
mDismissalDelegate = new SwipeDismissalDelegate(mActivity, mDismissalDelegateListener);
mDismissalDelegate = new SwipeDismissalDelegate(mDismissalDelegateListener);
}
@Test
@@ -86,22 +85,16 @@ public class SwipeDismissalDelegateTest {
@Test
public void getMovementFlags_dismissalView_shouldDisableSwipe() {
final RecyclerView.ViewHolder holder = getSliceViewHolder();
final ViewFlipper viewFlipper = holder.itemView.findViewById(R.id.view_flipper);
viewFlipper.showNext();
final View dismissalView = holder.itemView.findViewById(R.id.dismissal_view);
holder.itemView.findViewById(R.id.dismissal_view).setVisibility(View.VISIBLE);
assertThat(viewFlipper.getCurrentView()).isEqualTo(dismissalView);
assertThat(mDismissalDelegate.getMovementFlags(mRecyclerView, holder)).isEqualTo(0);
}
@Test
public void getMovementFlags_SliceViewHolder_shouldEnableSwipe() {
final RecyclerView.ViewHolder holder = getSliceViewHolder();
final ViewFlipper viewFlipper = holder.itemView.findViewById(R.id.view_flipper);
viewFlipper.setDisplayedChild(0);
final View sliceView = holder.itemView.findViewById(R.id.slice_view);
holder.itemView.findViewById(R.id.dismissal_view).setVisibility(View.GONE);
assertThat(viewFlipper.getCurrentView()).isEqualTo(sliceView);
assertThat(mDismissalDelegate.getMovementFlags(mRecyclerView, getSliceViewHolder()))
.isNotEqualTo(0);
}

View File

@@ -21,7 +21,6 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -31,7 +30,9 @@ import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccManager;
import org.junit.After;
@@ -52,6 +53,8 @@ import androidx.preference.PreferenceScreen;
@RunWith(RobolectricTestRunner.class)
public class MobileNetworkListControllerTest {
@Mock
TelephonyManager mTelephonyManager;
@Mock
EuiccManager mEuiccManager;
@@ -69,7 +72,9 @@ public class MobileNetworkListControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(Robolectric.setupActivity(Activity.class));
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
when(mContext.getSystemService(EuiccManager.class)).thenReturn(mEuiccManager);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.EUICC_PROVISIONED, 1);
when(mPreferenceScreen.getContext()).thenReturn(mContext);
mAddMorePreference = new Preference(mContext);
when(mPreferenceScreen.findPreference(MobileNetworkListController.KEY_ADD_MORE)).thenReturn(
@@ -99,6 +104,7 @@ public class MobileNetworkListControllerTest {
@Test
public void displayPreference_eSimSupported_addMoreLinkIsVisible() {
when(mEuiccManager.isEnabled()).thenReturn(true);
when(mTelephonyManager.getNetworkCountryIso()).thenReturn("");
mController.displayPreference(mPreferenceScreen);
mController.onResume();
assertThat(mAddMorePreference.isVisible()).isTrue();

View File

@@ -33,6 +33,7 @@ import android.content.Intent;
import android.net.ConnectivityManager;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
@@ -59,6 +60,8 @@ public class MobileNetworkSummaryControllerTest {
@Mock
private Lifecycle mLifecycle;
@Mock
private TelephonyManager mTelephonyManager;
@Mock
private EuiccManager mEuiccManager;
@Mock
private PreferenceScreen mPreferenceScreen;
@@ -71,8 +74,11 @@ public class MobileNetworkSummaryControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(Robolectric.setupActivity(Activity.class));
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
when(mContext.getSystemService(EuiccManager.class)).thenReturn(mEuiccManager);
when(mTelephonyManager.getNetworkCountryIso()).thenReturn("");
when(mEuiccManager.isEnabled()).thenReturn(true);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.EUICC_PROVISIONED, 1);
mController = new MobileNetworkSummaryController(mContext, mLifecycle);
mPreference = spy(new AddPreference(mContext, null));

View File

@@ -18,6 +18,7 @@ package com.android.settings.network;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -108,4 +109,32 @@ public class SubscriptionUtilTest {
assertThat(subs.get(0).getSubscriptionId()).isEqualTo(1);
assertThat(subs.get(1).getSubscriptionId()).isEqualTo(4);
}
@Test
public void getActiveSubscriptions_nullInfoFromSubscriptionManager_nonNullResult() {
when(mManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(null);
final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mManager);
assertThat(subs).isNotNull();
assertThat(subs).isEmpty();
}
@Test
public void getActiveSubscriptions_oneSubscription_oneResult() {
final SubscriptionInfo info = mock(SubscriptionInfo.class);
when(mManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(Arrays.asList(info));
final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mManager);
assertThat(subs).isNotNull();
assertThat(subs).hasSize(1);
}
@Test
public void getActiveSubscriptions_twoSubscriptions_twoResults() {
final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
when(mManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(
Arrays.asList(info1, info2));
final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mManager);
assertThat(subs).isNotNull();
assertThat(subs).hasSize(2);
}
}

View File

@@ -103,19 +103,19 @@ public class SubscriptionsPreferenceControllerTest {
@After
public void tearDown() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(null);
SubscriptionUtil.setActiveSubscriptionsForTesting(null);
}
@Test
public void isAvailable_oneSubscription_availableFalse() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(
SubscriptionUtil.setActiveSubscriptionsForTesting(
Arrays.asList(mock(SubscriptionInfo.class)));
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_twoSubscriptions_availableTrue() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(
SubscriptionUtil.setActiveSubscriptionsForTesting(
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
assertThat(mController.isAvailable()).isTrue();
}
@@ -126,13 +126,13 @@ public class SubscriptionsPreferenceControllerTest {
for (int i = 0; i < 5; i++) {
subs.add(mock(SubscriptionInfo.class));
}
SubscriptionUtil.setAvailableSubscriptionsForTesting(subs);
SubscriptionUtil.setActiveSubscriptionsForTesting(subs);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_airplaneModeOn_availableFalse() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(
SubscriptionUtil.setActiveSubscriptionsForTesting(
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
assertThat(mController.isAvailable()).isTrue();
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
@@ -141,7 +141,7 @@ public class SubscriptionsPreferenceControllerTest {
@Test
public void onAirplaneModeChanged_airplaneModeTurnedOn_eventFired() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(
SubscriptionUtil.setActiveSubscriptionsForTesting(
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
mController.onResume();
mController.displayPreference(mScreen);
@@ -157,7 +157,7 @@ public class SubscriptionsPreferenceControllerTest {
@Test
public void onAirplaneModeChanged_airplaneModeTurnedOff_eventFired() {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
SubscriptionUtil.setAvailableSubscriptionsForTesting(
SubscriptionUtil.setActiveSubscriptionsForTesting(
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
mController.onResume();
mController.displayPreference(mScreen);
@@ -174,13 +174,13 @@ public class SubscriptionsPreferenceControllerTest {
public void onSubscriptionsChanged_countBecameTwo_eventFired() {
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1));
mController.onResume();
mController.displayPreference(mScreen);
assertThat(mController.isAvailable()).isFalse();
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.onSubscriptionsChanged();
assertThat(mController.isAvailable()).isTrue();
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
@@ -192,14 +192,14 @@ public class SubscriptionsPreferenceControllerTest {
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(1);
when(sub2.getSubscriptionId()).thenReturn(2);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.onResume();
mController.displayPreference(mScreen);
assertThat(mController.isAvailable()).isTrue();
verify(mPreferenceCategory, times(2)).addPreference(any(Preference.class));
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1));
mController.onSubscriptionsChanged();
assertThat(mController.isAvailable()).isFalse();
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
@@ -221,7 +221,7 @@ public class SubscriptionsPreferenceControllerTest {
when(sub3.getSubscriptionId()).thenReturn(3);
// Start out with only sub1 and sub2.
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.onResume();
mController.displayPreference(mScreen);
final ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
@@ -233,7 +233,7 @@ public class SubscriptionsPreferenceControllerTest {
// Now replace sub2 with sub3, and make sure the old preference was removed and the new
// preference was added.
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub3));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub3));
mController.onSubscriptionsChanged();
assertThat(mController.isAvailable()).isTrue();
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
@@ -259,7 +259,7 @@ public class SubscriptionsPreferenceControllerTest {
doReturn(i + 1).when(sub).getSubscriptionId();
subscriptions.add(sub);
}
SubscriptionUtil.setAvailableSubscriptionsForTesting(subscriptions);
SubscriptionUtil.setActiveSubscriptionsForTesting(subscriptions);
mController.displayPreference(mScreen);
final ArgumentCaptor<Preference> prefCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mPreferenceCategory, times(subscriptionCount)).addPreference(prefCaptor.capture());
@@ -303,7 +303,7 @@ public class SubscriptionsPreferenceControllerTest {
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(11);
when(sub2.getSubscriptionId()).thenReturn(22);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
@@ -324,7 +324,7 @@ public class SubscriptionsPreferenceControllerTest {
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(11);
when(sub2.getSubscriptionId()).thenReturn(22);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
@@ -346,7 +346,7 @@ public class SubscriptionsPreferenceControllerTest {
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(11);
when(sub2.getSubscriptionId()).thenReturn(22);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(22);

View File

@@ -73,19 +73,19 @@ public class DefaultSubscriptionControllerTest {
@After
public void tearDown() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(null);
SubscriptionUtil.setActiveSubscriptionsForTesting(null);
}
@Test
public void getAvailabilityStatus_onlyOneSubscription_notAvailable() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(
createMockSub(1, "sub1")));
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_twoSubscriptions_isAvailable() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(
createMockSub(1, "sub1"),
createMockSub(2, "sub2")));
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
@@ -95,7 +95,7 @@ public class DefaultSubscriptionControllerTest {
public void displayPreference_twoSubscriptionsSub1Default_correctListPreferenceValues() {
final SubscriptionInfo sub1 = createMockSub(111, "sub1");
final SubscriptionInfo sub2 = createMockSub(222, "sub2");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
mController.displayPreference(mScreen);
@@ -123,7 +123,7 @@ public class DefaultSubscriptionControllerTest {
public void displayPreference_twoSubscriptionsSub2Default_correctListPreferenceValues() {
final SubscriptionInfo sub1 = createMockSub(111, "sub1");
final SubscriptionInfo sub2 = createMockSub(222, "sub2");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
doReturn(sub2.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
mController.displayPreference(mScreen);
@@ -156,7 +156,7 @@ public class DefaultSubscriptionControllerTest {
// Mark sub2 as opportunistic; then it should not appear in the list of entries/entryValues.
when(sub2.isOpportunistic()).thenReturn(true);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2, sub3));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2, sub3));
doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
mController.displayPreference(mScreen);
@@ -179,7 +179,7 @@ public class DefaultSubscriptionControllerTest {
public void onPreferenceChange_prefChangedToSub2_callbackCalledCorrectly() {
final SubscriptionInfo sub1 = createMockSub(111, "sub1");
final SubscriptionInfo sub2 = createMockSub(222, "sub2");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
mController.displayPreference(mScreen);
@@ -192,7 +192,7 @@ public class DefaultSubscriptionControllerTest {
public void onPreferenceChange_prefChangedToAlwaysAsk_callbackCalledCorrectly() {
final SubscriptionInfo sub1 = createMockSub(111, "sub1");
final SubscriptionInfo sub2 = createMockSub(222, "sub2");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
mController.displayPreference(mScreen);
@@ -207,7 +207,7 @@ public class DefaultSubscriptionControllerTest {
public void onSubscriptionsChanged_twoSubscriptionsDefaultChanges_selectedEntryGetsUpdated() {
final SubscriptionInfo sub1 = createMockSub(111, "sub1");
final SubscriptionInfo sub2 = createMockSub(222, "sub2");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
mController.displayPreference(mScreen);
@@ -224,14 +224,14 @@ public class DefaultSubscriptionControllerTest {
public void onSubscriptionsChanged_goFromTwoSubscriptionsToOne_prefDisappears() {
final SubscriptionInfo sub1 = createMockSub(111, "sub1");
final SubscriptionInfo sub2 = createMockSub(222, "sub2");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
mController.displayPreference(mScreen);
assertThat(mController.isAvailable()).isTrue();
assertThat(mListPreference.isVisible()).isTrue();
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1));
mController.onSubscriptionsChanged();
assertThat(mController.isAvailable()).isFalse();
@@ -242,14 +242,14 @@ public class DefaultSubscriptionControllerTest {
public void onSubscriptionsChanged_goFromOneSubscriptionToTwo_prefAppears() {
final SubscriptionInfo sub1 = createMockSub(111, "sub1");
final SubscriptionInfo sub2 = createMockSub(222, "sub2");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1));
doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
mController.displayPreference(mScreen);
assertThat(mController.isAvailable()).isFalse();
assertThat(mListPreference.isVisible()).isFalse();
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.onSubscriptionsChanged();
assertThat(mController.isAvailable()).isTrue();
@@ -261,13 +261,13 @@ public class DefaultSubscriptionControllerTest {
final SubscriptionInfo sub1 = createMockSub(111, "sub1");
final SubscriptionInfo sub2 = createMockSub(222, "sub2");
final SubscriptionInfo sub3 = createMockSub(333, "sub3");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId();
mController.displayPreference(mScreen);
assertThat(mListPreference.getEntries().length).isEqualTo(3);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2, sub3));
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2, sub3));
mController.onSubscriptionsChanged();
assertThat(mController.isAvailable()).isTrue();

View File

@@ -12,6 +12,7 @@ import androidx.annotation.ArrayRes;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.annotation.Resetter;
import org.robolectric.shadows.ShadowResources;
import org.robolectric.util.ReflectionHelpers.ClassParameter;
@@ -40,6 +41,7 @@ public class SettingsShadowResources extends ShadowResources {
overrideResource(resId, value);
}
@Resetter
public static void reset() {
sResourceOverrides.clear();
}

View File

@@ -36,6 +36,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
@@ -69,6 +70,7 @@ import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.FeatureFlags;
import com.android.settings.development.featureflags.FeatureFlagPersistent;
import com.android.settings.Utils;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.widget.EntityHeaderController;
@@ -1458,6 +1460,36 @@ public class WifiDetailPreferenceControllerTest {
verify(mockSignalStrengthPref, times(2)).setVisible(false);
}
@Test
public void testRedrawIconForHeader_shouldEnlarge() {
ArgumentCaptor<BitmapDrawable> drawableCaptor =
ArgumentCaptor.forClass(BitmapDrawable.class);
Drawable original = mContext.getDrawable(Utils.getWifiIconResource(LEVEL)).mutate();
when(mockIconInjector.getIcon(anyInt())).thenReturn(original);
displayAndResume();
verify(mockHeaderController, times(1)).setIcon(drawableCaptor.capture());
int expectedSize = mContext.getResources().getDimensionPixelSize(
R.dimen.wifi_detail_page_header_image_size);
BitmapDrawable icon = drawableCaptor.getValue();
assertThat(icon.getMinimumWidth()).isEqualTo(expectedSize);
assertThat(icon.getMinimumHeight()).isEqualTo(expectedSize);
}
@Test
public void testRedrawIconForHeader_shouldNotEnlargeIfNotVectorDrawable() {
ArgumentCaptor<ColorDrawable> drawableCaptor =
ArgumentCaptor.forClass(ColorDrawable.class);
displayAndResume();
verify(mockHeaderController, times(1)).setIcon(drawableCaptor.capture());
ColorDrawable icon = drawableCaptor.getValue();
assertThat(icon).isNotNull();
}
private ActionButtonsPreference createMock() {
final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
when(pref.setButton1Text(anyInt())).thenReturn(pref);

View File

@@ -16,9 +16,16 @@
package com.android.settings.wifi.dpp;
import static com.android.settings.wifi.dpp.WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER;
import static com.google.common.truth.Truth.assertThat;
import android.app.Instrumentation;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import androidx.fragment.app.FragmentManager;
import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
@@ -38,6 +45,7 @@ public class WifiDppQrCodeScannerFragmentTest {
Intent intent = new Intent(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
intent.putExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY, "password");
mActivityRule.launchActivity(intent);
}
@@ -48,4 +56,21 @@ public class WifiDppQrCodeScannerFragmentTest {
mActivityRule.getActivity().setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
@Test
public void onPause_shouldNotDecodeQrCode() {
final WifiDppConfiguratorActivity hostActivity =
(WifiDppConfiguratorActivity) mActivityRule.getActivity();
final FragmentManager fragmentManager = hostActivity.getSupportFragmentManager();
final WifiDppQrCodeScannerFragment scannerFragment =
(WifiDppQrCodeScannerFragment) fragmentManager
.findFragmentByTag(TAG_FRAGMENT_QR_CODE_SCANNER);
final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.runOnMainSync(() -> {
instrumentation.callActivityOnPause(hostActivity);
assertThat(scannerFragment.isDecodeTaskAlive()).isEqualTo(false);
});
}
}

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