Snap for 5452883 from dc4f7ce282 to qt-release
Change-Id: I67ecb7b174d2e9ea6cd363d8bcc7484fff1946f9
This commit is contained in:
@@ -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"
|
||||
|
||||
46
res/layout/dismissal_swipe_background.xml
Normal file
46
res/layout/dismissal_swipe_background.xml
Normal 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>
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
|
||||
@@ -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" />
|
||||
@@ -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" />
|
||||
@@ -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" />
|
||||
@@ -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" />
|
||||
@@ -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" />
|
||||
@@ -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" />
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */ }
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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<>();
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user