Snap for 8590907 from 36693d8096 to tm-release
Change-Id: I6f4a4d6bcffef25a6b3371df9c093e3caae09a40
This commit is contained in:
@@ -4474,6 +4474,16 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<activity
|
||||
android:name="com.android.settings.bluetooth.QrCodeScanModeActivity"
|
||||
android:permission="android.permission.BLUETOOTH_CONNECT"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.settings.BLUETOOTH_LE_AUDIO_QR_CODE_SCANNER"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- This is the longest AndroidManifest.xml ever. -->
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
23
res/drawable/ic_qr_code_scanner.xml
Normal file
23
res/drawable/ic_qr_code_scanner.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
|
||||
android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path android:fillColor="@android:color/white"
|
||||
android:pathData="M2,7V2H7V4H4V7ZM2,22V17H4V20H7V22ZM17,22V20H20V17H22V22ZM20,7V4H17V2H22V7ZM17.5,17.5H19V19H17.5ZM17.5,14.5H19V16H17.5ZM16,16H17.5V17.5H16ZM14.5,17.5H16V19H14.5ZM13,16H14.5V17.5H13ZM16,13H17.5V14.5H16ZM14.5,14.5H16V16H14.5ZM13,13H14.5V14.5H13ZM19,5V11H13V5ZM11,13V19H5V13ZM11,5V11H5V5ZM9.5,17.5V14.5H6.5V17.5ZM9.5,9.5V6.5H6.5V9.5ZM17.5,9.5V6.5H14.5V9.5Z"/>
|
||||
</vector>
|
||||
30
res/layout/qrcode_scan_mode_activity.xml
Normal file
30
res/layout/qrcode_scan_mode_activity.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</LinearLayout>
|
||||
102
res/layout/qrcode_scanner_fragment.xml
Normal file
102
res/layout/qrcode_scanner_fragment.xml
Normal file
@@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/sud_layout_icon_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="3"
|
||||
android:layout_marginBottom="35dp">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
<ImageView
|
||||
android:id="@+id/sud_layout_icon"
|
||||
android:src="@drawable/ic_qr_code_scanner"
|
||||
android:tint="?androidprv:attr/colorAccentPrimaryVariant"
|
||||
android:layout_width="@dimen/qrcode_icon_size"
|
||||
android:layout_height="@dimen/qrcode_icon_size"
|
||||
android:contentDescription="@null"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sud_layout_title"
|
||||
style="@style/QrCodeScanner"
|
||||
android:textSize="24sp"
|
||||
android:text="@string/bluetooth_find_broadcast_button_scan"
|
||||
android:gravity="center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="19dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sud_layout_subtitle"
|
||||
style="@style/QrCodeScanner"
|
||||
android:text="@string/bt_le_audio_scan_qr_code_scanner"
|
||||
android:gravity="center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="7"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:gravity="center"
|
||||
android:clipChildren="true">
|
||||
<TextureView
|
||||
android:id="@+id/preview_view"
|
||||
android:layout_marginStart="@dimen/qrcode_preview_margin"
|
||||
android:layout_marginEnd="@dimen/qrcode_preview_margin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/qrcode_preview_size"/>
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error_message"
|
||||
style="@style/TextAppearance.ErrorText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginStart="?attr/sudMarginStart"
|
||||
android:layout_marginEnd="?attr/sudMarginEnd"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="invisible"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -21,12 +21,6 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.android.settings.widget.SettingsMainSwitchBar
|
||||
android:id="@+id/switch_bar"
|
||||
android:title="@string/wifi_calling_main_switch_title"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@android:id/tabcontent"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -485,4 +485,9 @@
|
||||
<!-- Sims/Data mobile/Calls/SMS select dialog-->
|
||||
<dimen name="sims_select_margin_bottom">24dp</dimen>
|
||||
<dimen name="sims_select_margin_top">8dp</dimen>
|
||||
|
||||
<!-- QR code picture size -->
|
||||
<dimen name="qrcode_preview_margin">40dp</dimen>
|
||||
<dimen name="qrcode_preview_radius">30dp</dimen>
|
||||
<dimen name="qrcode_icon_size">27dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -518,6 +518,9 @@
|
||||
<!-- Description for the disclaimer of per app language. [CHAR LIMIT=NONE]-->
|
||||
<string name="desc_app_locale_disclaimer">Language may differ from languages available in the app. Some apps may not support this setting.</string>
|
||||
|
||||
<!-- Description for introduction of the locale selection supported of app list [CHAR LIMIT=NONE]-->
|
||||
<string name="desc_app_locale_selection_supported">Only apps that support language selection are shown here.</string>
|
||||
|
||||
<!-- The title of the confirmation dialog shown when the user selects one / several languages and tries to remove them [CHAR LIMIT=60] -->
|
||||
<plurals name="dlg_remove_locales_title">
|
||||
<item quantity="one">Remove selected language?</item>
|
||||
@@ -1297,7 +1300,10 @@
|
||||
<string name="security_advanced_settings_no_work_profile_settings_summary">Encryption, credentials, and more</string>
|
||||
<!-- Search keywords for the "More security settings" section in security settings. [CHAR_LIMIT=NONE] -->
|
||||
<string name="security_advanced_settings_keywords">security, more security settings, more settings, advanced security settings</string>
|
||||
|
||||
<!-- Title for the section that has additional privacy settings. [CHAR LIMIT=60] -->
|
||||
<string name="privacy_advanced_settings">More privacy settings</string>
|
||||
<!-- Title for the section that has additional privacy settings. [CHAR LIMIT=60] -->
|
||||
<string name="privacy_advanced_settings_summary">Autofill, activity controls, and more</string>
|
||||
|
||||
<!-- Text shown when "Add fingerprint" button is disabled -->
|
||||
<string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string>
|
||||
@@ -8973,6 +8979,9 @@
|
||||
<!-- Configure Notifications: Work profile section header [CHAR LIMIT=30] -->
|
||||
<string name="profile_section_header">Work notifications</string>
|
||||
|
||||
<!-- Configure Notifications: Work profile section header [CHAR LIMIT=30] -->
|
||||
<string name="profile_section_header_for_advanced_privacy">Work profile</string>
|
||||
|
||||
<!-- Configure Notifications: section header for prioritizer settings [CHAR LIMIT=80] -->
|
||||
<string name="smart_notifications_title">Adaptive notifications</string>
|
||||
|
||||
@@ -13649,7 +13658,9 @@
|
||||
<string name="default_active_sim_mobile_data">mobile data</string>
|
||||
<!-- Provider Model: Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off and Wi-Fi
|
||||
scanning is on. To mark a link to bring the user to "scanning settings" screen. [CHAR LIMIT=NONE]-->
|
||||
<string name="wifi_scan_notify_message">To improve device experience, apps and services can still scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. This can be used, for example, to improve location-based features and services. You can change this in Wi\u2011Fi scanning settings. <annotation id="link">Change</annotation></string>
|
||||
<string name="wifi_scan_notify_message">To improve device experience, apps and services can still scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. This can be used, for example, to improve location-based features and services. You can change this in Wi\u2011Fi scanning settings.</string>
|
||||
<!-- Provider Model: Link text to bring the user to "scanning settings" screen. [CHAR LIMIT=NONE]-->
|
||||
<string name="wifi_scan_change">Change</string>
|
||||
|
||||
<!-- Summary text separator for preferences including a short description
|
||||
(eg. "Connected / 5G"). [CHAR LIMIT=50] -->
|
||||
@@ -14163,4 +14174,11 @@
|
||||
<string name="find_broadcast_password_dialog_connection_error">Can\u2019t connect. Try again.</string>
|
||||
<!-- The error message of enter password dialog in bluetooth find broadcast page [CHAR LIMIT=none] -->
|
||||
<string name="find_broadcast_password_dialog_password_error">Wrong password</string>
|
||||
|
||||
|
||||
<!-- [CHAR LIMIT=NONE] Le audio QR code scanner sub-title -->
|
||||
<string name="bt_le_audio_scan_qr_code_scanner">To start listening, center the QR code below</string>
|
||||
<!-- [CHAR LIMIT=NONE] Hint for QR code process failure -->
|
||||
<string name="bt_le_audio_qr_code_is_not_valid_format">QR code isn\u0027t a valid format</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -962,4 +962,11 @@
|
||||
<item name="android:minWidth">0dp</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
</style>
|
||||
|
||||
<style name="QrCodeScanner">
|
||||
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
|
||||
<item name="android:textSize">16sp</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
<item name="android:textDirection">locale</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@@ -46,6 +46,11 @@
|
||||
android:key="action_buttons"
|
||||
settings:allowDividerBelow="true"/>
|
||||
|
||||
<com.android.settings.slices.SlicePreference
|
||||
android:key="bt_extra_control"
|
||||
settings:controller="com.android.settings.slices.SlicePreferenceController"
|
||||
settings:allowDividerAbove="true"/>
|
||||
|
||||
<com.android.settings.slices.SlicePreference
|
||||
android:key="bt_device_slice"
|
||||
settings:controller="com.android.settings.slices.BlockingSlicePrefController"
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="usage_amount">
|
||||
android:key="usage_amount"
|
||||
android:title="@string/summary_placeholder">
|
||||
|
||||
<com.android.settings.datausage.ChartDataUsagePreference
|
||||
android:key="chart_data" />
|
||||
|
||||
96
res/xml/privacy_advanced_settings.xml
Normal file
96
res/xml/privacy_advanced_settings.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:key="privacy_dashboard_page"
|
||||
android:title="@string/privacy_advanced_settings">
|
||||
|
||||
<!-- Work Policy info -->
|
||||
<Preference
|
||||
android:key="work_policy_info"
|
||||
android:title="@string/work_policy_privacy_settings"
|
||||
android:summary="@string/work_policy_privacy_settings_summary"
|
||||
settings:controller="com.android.settings.privacy.WorkPolicyInfoPreferenceController"/>
|
||||
|
||||
<!-- Connected work and personal apps -->
|
||||
<Preference
|
||||
android:key="interact_across_profiles_privacy"
|
||||
android:title="@string/interact_across_profiles_title"
|
||||
android:fragment="com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesSettings"
|
||||
settings:searchable="false"
|
||||
settings:controller="com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesController" />
|
||||
|
||||
<!-- Accessibility usage -->
|
||||
<Preference
|
||||
android:key="privacy_accessibility_usage"
|
||||
android:title="@string/accessibility_usage_title"
|
||||
settings:controller="com.android.settings.privacy.AccessibilityUsagePreferenceController">
|
||||
<intent android:action="android.intent.action.REVIEW_ACCESSIBILITY_SERVICES"/>
|
||||
</Preference>
|
||||
|
||||
<!-- On lock screen notifications -->
|
||||
<com.android.settings.RestrictedListPreference
|
||||
android:key="privacy_lock_screen_notifications"
|
||||
android:title="@string/lock_screen_notifs_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:searchable="false"/>
|
||||
|
||||
<!-- Privacy Service -->
|
||||
<PreferenceCategory
|
||||
android:key="privacy_services"
|
||||
android:layout="@layout/preference_category_no_label"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="dashboard_tile_placeholder"/>
|
||||
|
||||
<!-- Work profile settings are at the bottom with high order value to avoid users thinking that
|
||||
any of the above settings (including dynamic) are specific to the work profile. -->
|
||||
<PreferenceCategory
|
||||
android:key="privacy_work_profile_notifications_category"
|
||||
android:title="@string/profile_section_header_for_advanced_privacy"
|
||||
android:order="998">
|
||||
|
||||
<com.android.settings.RestrictedListPreference
|
||||
android:key="privacy_lock_screen_work_profile_notifications"
|
||||
android:title="@string/locked_work_profile_notification_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:order="999"
|
||||
settings:searchable="false"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<!-- Content Capture -->
|
||||
|
||||
<!-- NOTE: content capture has a different preference, depending whether or not the
|
||||
ContentCaptureService implementations defines a custom settings activitiy on its manifest.
|
||||
Hence, we show both here, but the controller itself will decide if it's available or not.
|
||||
-->
|
||||
|
||||
<SwitchPreference
|
||||
android:key="content_capture"
|
||||
android:title="@string/content_capture"
|
||||
android:summary="@string/content_capture_summary"
|
||||
settings:controller="com.android.settings.privacy.EnableContentCapturePreferenceController"/>
|
||||
|
||||
<com.android.settingslib.PrimarySwitchPreference
|
||||
android:key="content_capture_custom_settings"
|
||||
android:title="@string/content_capture"
|
||||
android:summary="@string/content_capture_summary"
|
||||
settings:controller="com.android.settings.privacy.EnableContentCaptureWithServiceSettingsPreferenceController"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -19,6 +19,10 @@
|
||||
android:key="wifi_calling_settings"
|
||||
android:title="@string/wifi_calling_settings_title">
|
||||
|
||||
<com.android.settings.widget.SettingsMainSwitchPreference
|
||||
android:key="wifi_calling_switch_bar"
|
||||
android:title="@string/wifi_calling_main_switch_title" />
|
||||
|
||||
<com.android.settings.wifi.calling.ListWithEntrySummaryPreference
|
||||
android:key="wifi_calling_mode"
|
||||
isPreferenceVisible="false"
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import static android.provider.Settings.ACTION_PRIVACY_SETTINGS;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -214,7 +216,8 @@ public class Settings extends SettingsActivity {
|
||||
/** Redirects to SafetyCenter if enabled. */
|
||||
@VisibleForTesting
|
||||
public void handleSafetyCenterRedirection() {
|
||||
if (SafetyCenterManagerWrapper.get().isEnabled(this)) {
|
||||
if (ACTION_PRIVACY_SETTINGS.equals(getIntent().getAction())
|
||||
&& SafetyCenterManagerWrapper.get().isEnabled(this)) {
|
||||
try {
|
||||
startActivity(new Intent(Intent.ACTION_SAFETY_CENTER));
|
||||
finish();
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.content.SharedPreferences;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.graphics.drawable.Icon;
|
||||
@@ -152,6 +153,8 @@ public class SettingsActivity extends SettingsBaseActivity
|
||||
*/
|
||||
public static final String EXTRA_IS_FROM_SLICE = "is_from_slice";
|
||||
|
||||
public static final String EXTRA_USER_HANDLE = "user_handle";
|
||||
|
||||
/**
|
||||
* Personal or Work profile tab of {@link ProfileSelectFragment}
|
||||
* <p>0: Personal tab.
|
||||
@@ -427,7 +430,14 @@ public class SettingsActivity extends SettingsBaseActivity
|
||||
}
|
||||
|
||||
try {
|
||||
startActivity(trampolineIntent);
|
||||
final UserManager um = getSystemService(UserManager.class);
|
||||
final UserInfo userInfo = um.getUserInfo(getUser().getIdentifier());
|
||||
if (userInfo.isManagedProfile()) {
|
||||
trampolineIntent.putExtra(EXTRA_USER_HANDLE, getUser());
|
||||
startActivityAsUser(trampolineIntent, um.getPrimaryUser().getUserHandle());
|
||||
} else {
|
||||
startActivity(trampolineIntent);
|
||||
}
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Log.e(LOG_TAG, "Deep link homepage is not available to show 2-pane UI");
|
||||
return false;
|
||||
|
||||
@@ -27,8 +27,11 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.settingslib.widget.LayoutPreference;
|
||||
|
||||
import com.google.android.setupdesign.GlifPreferenceLayout;
|
||||
import com.google.android.setupdesign.util.LayoutStyler;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link androidx.preference.PreferenceFragmentCompat} that displays the settings page related
|
||||
@@ -47,6 +50,8 @@ public class TextReadingPreferenceFragmentForSetupWizard extends TextReadingPref
|
||||
icon.setTintList(Utils.getColorAttr(getContext(), android.R.attr.colorPrimary));
|
||||
AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title,
|
||||
/* description= */ null, icon);
|
||||
|
||||
updateResetButtonPadding();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,4 +71,14 @@ public class TextReadingPreferenceFragmentForSetupWizard extends TextReadingPref
|
||||
// Hides help center in action bar and footer bar in SuW
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the padding of the reset button to meet for SetupWizard style.
|
||||
*/
|
||||
private void updateResetButtonPadding() {
|
||||
final LayoutPreference resetPreference = (LayoutPreference) findPreference(RESET_KEY);
|
||||
final ViewGroup parentView =
|
||||
(ViewGroup) resetPreference.findViewById(R.id.reset_button).getParent();
|
||||
LayoutStyler.applyPartnerCustomizationLayoutPaddingStyle(parentView);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ public class ToggleScreenReaderPreferenceFragmentForSetupWizard
|
||||
if (mTopIntroPreference != null) {
|
||||
mTopIntroPreference.setVisible(false);
|
||||
}
|
||||
|
||||
mToggleServiceSwitchPreference.applyPartnerCustomizationPaddingStyle();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -85,6 +85,14 @@ public class ApplicationViewHolder extends RecyclerView.ViewHolder {
|
||||
return view;
|
||||
}
|
||||
|
||||
static View newHeader(ViewGroup parent, int resText) {
|
||||
ViewGroup view = (ViewGroup) LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.preference_app_header, parent, false);
|
||||
TextView textView = view.findViewById(R.id.apps_top_intro_text);
|
||||
textView.setText(resText);
|
||||
return view;
|
||||
}
|
||||
|
||||
void setSummary(CharSequence summary) {
|
||||
mSummary.setText(summary);
|
||||
}
|
||||
|
||||
@@ -824,14 +824,16 @@ public class ManageApplications extends InstrumentedFragment
|
||||
if (mApplications == null) {
|
||||
return;
|
||||
}
|
||||
final int position = mRecyclerView.getChildAdapterPosition(view);
|
||||
final int applicationPosition =
|
||||
ApplicationsAdapter.getApplicationPosition(
|
||||
mListType, mRecyclerView.getChildAdapterPosition(view));
|
||||
|
||||
if (position == RecyclerView.NO_POSITION) {
|
||||
if (applicationPosition == RecyclerView.NO_POSITION) {
|
||||
Log.w(TAG, "Cannot find position for child, skipping onClick handling");
|
||||
return;
|
||||
}
|
||||
if (mApplications.getApplicationCount() > position) {
|
||||
ApplicationsState.AppEntry entry = mApplications.getAppEntry(position);
|
||||
if (mApplications.getApplicationCount() > applicationPosition) {
|
||||
ApplicationsState.AppEntry entry = mApplications.getAppEntry(applicationPosition);
|
||||
mCurrentPkgName = entry.info.packageName;
|
||||
mCurrentUid = entry.info.uid;
|
||||
startApplicationDetailsActivity();
|
||||
@@ -1058,6 +1060,7 @@ public class ManageApplications extends InstrumentedFragment
|
||||
private static final String STATE_LAST_SCROLL_INDEX = "state_last_scroll_index";
|
||||
private static final int VIEW_TYPE_APP = 0;
|
||||
private static final int VIEW_TYPE_EXTRA_VIEW = 1;
|
||||
private static final int VIEW_TYPE_APP_HEADER = 2;
|
||||
|
||||
private final ApplicationsState mState;
|
||||
private final ApplicationsState.Session mSession;
|
||||
@@ -1229,7 +1232,11 @@ public class ManageApplications extends InstrumentedFragment
|
||||
@Override
|
||||
public ApplicationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
final View view;
|
||||
if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
|
||||
if (mManageApplications.mListType == LIST_TYPE_APPS_LOCALE
|
||||
&& viewType == VIEW_TYPE_APP_HEADER) {
|
||||
view = ApplicationViewHolder.newHeader(parent,
|
||||
R.string.desc_app_locale_selection_supported);
|
||||
} else if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
|
||||
view = ApplicationViewHolder.newView(parent, true /* twoTarget */);
|
||||
} else {
|
||||
view = ApplicationViewHolder.newView(parent, false /* twoTarget */);
|
||||
@@ -1239,6 +1246,9 @@ public class ManageApplications extends InstrumentedFragment
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == 0 && mManageApplications.mListType == LIST_TYPE_APPS_LOCALE) {
|
||||
return VIEW_TYPE_APP_HEADER;
|
||||
}
|
||||
return VIEW_TYPE_APP;
|
||||
}
|
||||
|
||||
@@ -1472,10 +1482,11 @@ public class ManageApplications extends InstrumentedFragment
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
if (mEntries == null) {
|
||||
return 0;
|
||||
int count = getApplicationCount();
|
||||
if (count != 0 && mManageApplications.mListType == LIST_TYPE_APPS_LOCALE) {
|
||||
count++;
|
||||
}
|
||||
return mEntries.size();
|
||||
return count;
|
||||
}
|
||||
|
||||
public int getApplicationCount() {
|
||||
@@ -1483,15 +1494,18 @@ public class ManageApplications extends InstrumentedFragment
|
||||
}
|
||||
|
||||
public AppEntry getAppEntry(int position) {
|
||||
return mEntries.get(position);
|
||||
return mEntries.get(
|
||||
getApplicationPosition(mManageApplications.mListType, position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
if (position == mEntries.size()) {
|
||||
int applicationPosition =
|
||||
getApplicationPosition(mManageApplications.mListType, position);
|
||||
if (applicationPosition == mEntries.size()) {
|
||||
return -1;
|
||||
}
|
||||
return mEntries.get(position).id;
|
||||
return mEntries.get(applicationPosition).id;
|
||||
}
|
||||
|
||||
public boolean isEnabled(int position) {
|
||||
@@ -1499,7 +1513,9 @@ public class ManageApplications extends InstrumentedFragment
|
||||
|| mManageApplications.mListType != LIST_TYPE_HIGH_POWER) {
|
||||
return true;
|
||||
}
|
||||
ApplicationsState.AppEntry entry = mEntries.get(position);
|
||||
ApplicationsState.AppEntry entry =
|
||||
mEntries.get(
|
||||
getApplicationPosition(mManageApplications.mListType, position));
|
||||
|
||||
return !mBackend.isSysAllowlisted(entry.info.packageName)
|
||||
&& !mBackend.isDefaultActiveApp(entry.info.packageName);
|
||||
@@ -1507,8 +1523,15 @@ public class ManageApplications extends InstrumentedFragment
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ApplicationViewHolder holder, int position) {
|
||||
if (getItemViewType(position) == VIEW_TYPE_APP_HEADER) {
|
||||
// It does not bind holder here, due to header view.
|
||||
return;
|
||||
}
|
||||
|
||||
// Bind the data efficiently with the holder
|
||||
final ApplicationsState.AppEntry entry = mEntries.get(position);
|
||||
final ApplicationsState.AppEntry entry =
|
||||
mEntries.get(
|
||||
getApplicationPosition(mManageApplications.mListType, position));
|
||||
synchronized (entry) {
|
||||
mState.ensureLabelDescription(entry);
|
||||
holder.setTitle(entry.label, entry.labelDescription);
|
||||
@@ -1608,6 +1631,22 @@ public class ManageApplications extends InstrumentedFragment
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts position if this list adds a header.
|
||||
* TODO(b/232533002) Add a header view on adapter of RecyclerView may not a good idea since
|
||||
* ManageApplication is a generic purpose. In the future, here shall look for
|
||||
* a better way to add a header without using recyclerView or any other ways
|
||||
* to achieve the goal.
|
||||
*/
|
||||
public static int getApplicationPosition(int listType, int position) {
|
||||
int applicationPosition = position;
|
||||
// Adjust position due to header added.
|
||||
if (position > 0 && listType == LIST_TYPE_APPS_LOCALE) {
|
||||
applicationPosition = position - 1;
|
||||
}
|
||||
return applicationPosition;
|
||||
}
|
||||
|
||||
public static class OnScrollListener extends RecyclerView.OnScrollListener {
|
||||
private int mScrollState = SCROLL_STATE_IDLE;
|
||||
private boolean mDelayNotifyDataChange;
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import android.bluetooth.BluetoothLeAudioContentMetadata;
|
||||
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||
import android.bluetooth.BluetoothLeBroadcastSubgroup;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -43,16 +45,15 @@ class BluetoothBroadcastSourcePreference extends Preference {
|
||||
private static final int RESOURCE_ID_ICON = R.drawable.settings_input_antenna;
|
||||
|
||||
private BluetoothLeBroadcastMetadata mBluetoothLeBroadcastMetadata;
|
||||
private BluetoothLeBroadcastReceiveState mBluetoothLeBroadcastReceiveState;
|
||||
private ImageView mFrictionImageView;
|
||||
private String mTitle;
|
||||
private boolean mStatus;
|
||||
private boolean mIsEncrypted;
|
||||
|
||||
BluetoothBroadcastSourcePreference(@NonNull Context context,
|
||||
@NonNull BluetoothLeBroadcastMetadata source) {
|
||||
BluetoothBroadcastSourcePreference(@NonNull Context context) {
|
||||
super(context);
|
||||
initUi();
|
||||
updateMetadataAndRefreshUi(source, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,7 +69,7 @@ class BluetoothBroadcastSourcePreference extends Preference {
|
||||
private void initUi() {
|
||||
setLayoutResource(R.layout.preference_access_point);
|
||||
setWidgetLayoutResource(R.layout.access_point_friction_widget);
|
||||
|
||||
mTitle = getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO);
|
||||
mStatus = false;
|
||||
final Drawable drawable = getContext().getDrawable(RESOURCE_ID_ICON);
|
||||
if (drawable != null) {
|
||||
@@ -105,9 +106,20 @@ class BluetoothBroadcastSourcePreference extends Preference {
|
||||
*/
|
||||
public void updateMetadataAndRefreshUi(BluetoothLeBroadcastMetadata source, boolean status) {
|
||||
mBluetoothLeBroadcastMetadata = source;
|
||||
mTitle = getBroadcastMetadataProgramInfo();
|
||||
mTitle = getProgramInfo();
|
||||
mIsEncrypted = mBluetoothLeBroadcastMetadata.isEncrypted();
|
||||
mStatus = status;
|
||||
mStatus = status || mBluetoothLeBroadcastReceiveState != null;
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the title and status from BluetoothLeBroadcastReceiveState.
|
||||
*/
|
||||
public void updateReceiveStateAndRefreshUi(BluetoothLeBroadcastReceiveState receiveState) {
|
||||
mBluetoothLeBroadcastReceiveState = receiveState;
|
||||
mTitle = getProgramInfo();
|
||||
mStatus = true;
|
||||
|
||||
refresh();
|
||||
}
|
||||
@@ -124,7 +136,17 @@ class BluetoothBroadcastSourcePreference extends Preference {
|
||||
updateStatusButton();
|
||||
}
|
||||
|
||||
private String getBroadcastMetadataProgramInfo() {
|
||||
private String getProgramInfo() {
|
||||
if (mBluetoothLeBroadcastReceiveState != null) {
|
||||
List<BluetoothLeAudioContentMetadata> bluetoothLeAudioContentMetadata =
|
||||
mBluetoothLeBroadcastReceiveState.getSubgroupMetadata();
|
||||
if (!bluetoothLeAudioContentMetadata.isEmpty()) {
|
||||
return bluetoothLeAudioContentMetadata.stream()
|
||||
.map(i -> i.getProgramInfo())
|
||||
.findFirst().orElse(
|
||||
getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO));
|
||||
}
|
||||
}
|
||||
if (mBluetoothLeBroadcastMetadata == null) {
|
||||
return getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO);
|
||||
}
|
||||
@@ -138,4 +160,24 @@ class BluetoothBroadcastSourcePreference extends Preference {
|
||||
.filter(i -> !TextUtils.isEmpty(i))
|
||||
.findFirst().orElse(getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the broadcast source is encrypted or not.
|
||||
* @return If true, the broadcast source needs the broadcast code. If false, the broadcast
|
||||
* source does not need the broadcast code.
|
||||
*/
|
||||
public boolean isEncrypted() {
|
||||
return mIsEncrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the BluetoothLeBroadcastReceiveState and reset the state when the user clicks the
|
||||
* "leave broadcast" button.
|
||||
*/
|
||||
public void clearReceiveState() {
|
||||
mBluetoothLeBroadcastReceiveState = null;
|
||||
mTitle = getProgramInfo();
|
||||
mStatus = false;
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,12 +22,18 @@ import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
@@ -36,12 +42,14 @@ import com.android.settings.core.SettingsUIDeviceConfig;
|
||||
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.slices.BlockingSlicePrefController;
|
||||
import com.android.settings.slices.SlicePreferenceController;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.IllegalFormatException;
|
||||
import java.util.List;
|
||||
|
||||
public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment {
|
||||
@@ -61,6 +69,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
||||
@VisibleForTesting
|
||||
interface TestDataFactory {
|
||||
CachedBluetoothDevice getDevice(String deviceAddress);
|
||||
|
||||
LocalBluetoothManager getManager(Context context);
|
||||
}
|
||||
|
||||
@@ -127,6 +136,49 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
||||
use(BlockingSlicePrefController.class).setSliceUri(sliceEnabled
|
||||
? featureProvider.getBluetoothDeviceSettingsUri(mCachedDevice.getDevice())
|
||||
: null);
|
||||
updateExtraControlUri(/* viewWidth */ 0);
|
||||
}
|
||||
|
||||
private void updateExtraControlUri(int viewWidth) {
|
||||
BluetoothFeatureProvider featureProvider = FeatureFactory.getFactory(
|
||||
getContext()).getBluetoothFeatureProvider(getContext());
|
||||
boolean sliceEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_SLICE_SETTINGS_ENABLED, true);
|
||||
Uri controlUri = null;
|
||||
String uri = featureProvider.getBluetoothDeviceControlUri(mCachedDevice.getDevice());
|
||||
if (!TextUtils.isEmpty(uri)) {
|
||||
try {
|
||||
controlUri = Uri.parse(String.format(uri, viewWidth));
|
||||
} catch (IllegalFormatException | NullPointerException exception) {
|
||||
Log.d(TAG, "unable to parse uri");
|
||||
controlUri = null;
|
||||
}
|
||||
}
|
||||
use(SlicePreferenceController.class).setSliceUri(sliceEnabled ? controlUri : null);
|
||||
}
|
||||
|
||||
private final ViewTreeObserver.OnGlobalLayoutListener mOnGlobalLayoutListener =
|
||||
new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
View view = getView();
|
||||
if (view == null) {
|
||||
return;
|
||||
}
|
||||
updateExtraControlUri(view.getWidth());
|
||||
view.getViewTreeObserver().removeOnGlobalLayoutListener(
|
||||
mOnGlobalLayoutListener);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||
if (view != null) {
|
||||
view.getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,8 +26,17 @@ public interface BluetoothFeatureProvider {
|
||||
|
||||
/**
|
||||
* Get the {@link Uri} that represents extra settings for a specific bluetooth device
|
||||
*
|
||||
* @param bluetoothDevice bluetooth device
|
||||
* @return {@link Uri} for extra settings
|
||||
*/
|
||||
Uri getBluetoothDeviceSettingsUri(BluetoothDevice bluetoothDevice);
|
||||
|
||||
/**
|
||||
* Get the {@link Uri} that represents extra control for a specific bluetooth device
|
||||
*
|
||||
* @param bluetoothDevice bluetooth device
|
||||
* @return {@link String} uri string for extra control
|
||||
*/
|
||||
String getBluetoothDeviceControlUri(BluetoothDevice bluetoothDevice);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
|
||||
/**
|
||||
* Impl of {@link BluetoothFeatureProvider}
|
||||
*/
|
||||
@@ -37,4 +39,9 @@ public class BluetoothFeatureProviderImpl implements BluetoothFeatureProvider {
|
||||
BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI);
|
||||
return uriByte == null ? null : Uri.parse(new String(uriByte));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBluetoothDeviceControlUri(BluetoothDevice bluetoothDevice) {
|
||||
return BluetoothUtils.getControlUriMetaData(bluetoothDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,9 +86,7 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment
|
||||
@Override
|
||||
public void onSearchStarted(int reason) {
|
||||
Log.d(TAG, "onSearchStarted: " + reason);
|
||||
|
||||
getActivity().runOnUiThread(
|
||||
() -> cacheRemoveAllPrefs(mBroadcastSourceListCategory));
|
||||
getActivity().runOnUiThread(() -> handleSearchStarted());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,7 +107,8 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment
|
||||
@Override
|
||||
public void onSourceFound(@NonNull BluetoothLeBroadcastMetadata source) {
|
||||
Log.d(TAG, "onSourceFound:");
|
||||
getActivity().runOnUiThread(() -> updateListCategory(source, false));
|
||||
getActivity().runOnUiThread(
|
||||
() -> updateListCategoryFromBroadcastMetadata(source, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,7 +118,7 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment
|
||||
Log.w(TAG, "onSourceAdded: mSelectedPreference == null!");
|
||||
return;
|
||||
}
|
||||
getActivity().runOnUiThread(() -> updateListCategory(
|
||||
getActivity().runOnUiThread(() -> updateListCategoryFromBroadcastMetadata(
|
||||
mSelectedPreference.getBluetoothLeBroadcastMetadata(), true));
|
||||
}
|
||||
|
||||
@@ -144,6 +143,7 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment
|
||||
public void onSourceRemoved(@NonNull BluetoothDevice sink, int sourceId,
|
||||
int reason) {
|
||||
Log.d(TAG, "onSourceRemoved:");
|
||||
getActivity().runOnUiThread(() -> handleSourceRemoved());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -215,6 +215,8 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment
|
||||
//check assistant status. Start searching...
|
||||
if (mLeBroadcastAssistant != null && !mLeBroadcastAssistant.isSearchInProgress()) {
|
||||
mLeBroadcastAssistant.startSearchingForSources(getScanFilter());
|
||||
} else {
|
||||
addConnectedSourcePreference();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,11 +312,13 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private void updateListCategory(BluetoothLeBroadcastMetadata source, boolean isConnected) {
|
||||
private void updateListCategoryFromBroadcastMetadata(BluetoothLeBroadcastMetadata source,
|
||||
boolean isConnected) {
|
||||
BluetoothBroadcastSourcePreference item = mBroadcastSourceListCategory.findPreference(
|
||||
Integer.toString(source.getBroadcastId()));
|
||||
if (item == null) {
|
||||
item = createBluetoothBroadcastSourcePreference(source);
|
||||
item = createBluetoothBroadcastSourcePreference();
|
||||
item.setKey(Integer.toString(source.getBroadcastId()));
|
||||
mBroadcastSourceListCategory.addPreference(item);
|
||||
}
|
||||
item.updateMetadataAndRefreshUi(source, isConnected);
|
||||
@@ -326,13 +330,36 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment
|
||||
}
|
||||
}
|
||||
|
||||
private BluetoothBroadcastSourcePreference createBluetoothBroadcastSourcePreference(
|
||||
BluetoothLeBroadcastMetadata source) {
|
||||
private void updateListCategoryFromBroadcastReceiveState(
|
||||
BluetoothLeBroadcastReceiveState receiveState) {
|
||||
BluetoothBroadcastSourcePreference item = mBroadcastSourceListCategory.findPreference(
|
||||
Integer.toString(receiveState.getBroadcastId()));
|
||||
if (item == null) {
|
||||
item = createBluetoothBroadcastSourcePreference();
|
||||
item.setKey(Integer.toString(receiveState.getBroadcastId()));
|
||||
mBroadcastSourceListCategory.addPreference(item);
|
||||
}
|
||||
item.updateReceiveStateAndRefreshUi(receiveState);
|
||||
item.setOrder(0);
|
||||
|
||||
setSourceId(receiveState.getSourceId());
|
||||
mSelectedPreference = item;
|
||||
|
||||
//refresh the header
|
||||
if (mBluetoothFindBroadcastsHeaderController != null) {
|
||||
mBluetoothFindBroadcastsHeaderController.refreshUi();
|
||||
}
|
||||
}
|
||||
|
||||
private BluetoothBroadcastSourcePreference createBluetoothBroadcastSourcePreference() {
|
||||
BluetoothBroadcastSourcePreference pref = new BluetoothBroadcastSourcePreference(
|
||||
getContext(), source);
|
||||
pref.setKey(Integer.toString(source.getBroadcastId()));
|
||||
getContext());
|
||||
pref.setOnPreferenceClickListener(preference -> {
|
||||
if (source.isEncrypted()) {
|
||||
if (pref.getBluetoothLeBroadcastMetadata() == null) {
|
||||
Log.d(TAG, "BluetoothLeBroadcastMetadata is null, do nothing.");
|
||||
return false;
|
||||
}
|
||||
if (pref.isEncrypted()) {
|
||||
launchBroadcastCodeDialog(pref);
|
||||
} else {
|
||||
addSource(pref);
|
||||
@@ -383,6 +410,10 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment
|
||||
.setPositiveButton(R.string.bluetooth_connect_access_dialog_positive,
|
||||
(d, w) -> {
|
||||
Log.d(TAG, "setPositiveButton: clicked");
|
||||
if (pref.getBluetoothLeBroadcastMetadata() == null) {
|
||||
Log.d(TAG, "BluetoothLeBroadcastMetadata is null, do nothing.");
|
||||
return;
|
||||
}
|
||||
addBroadcastCodeIntoPreference(pref, editText.getText().toString());
|
||||
addSource(pref);
|
||||
})
|
||||
@@ -392,6 +423,30 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment
|
||||
alertDialog.show();
|
||||
}
|
||||
|
||||
private void handleSearchStarted() {
|
||||
cacheRemoveAllPrefs(mBroadcastSourceListCategory);
|
||||
addConnectedSourcePreference();
|
||||
}
|
||||
|
||||
private void handleSourceRemoved() {
|
||||
if (mSelectedPreference != null) {
|
||||
if (mSelectedPreference.getBluetoothLeBroadcastMetadata() == null) {
|
||||
mBroadcastSourceListCategory.removePreference(mSelectedPreference);
|
||||
} else {
|
||||
mSelectedPreference.clearReceiveState();
|
||||
}
|
||||
}
|
||||
mSelectedPreference = null;
|
||||
}
|
||||
|
||||
private void addConnectedSourcePreference() {
|
||||
List<BluetoothLeBroadcastReceiveState> receiveStateList =
|
||||
mLeBroadcastAssistant.getAllSources(mCachedDevice.getDevice());
|
||||
if (!receiveStateList.isEmpty()) {
|
||||
updateListCategoryFromBroadcastReceiveState(receiveStateList.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
public int getSourceId() {
|
||||
return mSourceId;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.qrcode.QrCodeScanModeActivity;
|
||||
import com.android.settingslib.widget.LayoutPreference;
|
||||
|
||||
/**
|
||||
@@ -135,7 +134,7 @@ public class BluetoothFindBroadcastsHeaderController extends BluetoothDetailsCon
|
||||
private void launchQrCodeScanner() {
|
||||
final Intent intent = new Intent(mContext, QrCodeScanModeActivity.class);
|
||||
intent.setAction(BluetoothBroadcastUtils.ACTION_BLUETOOTH_LE_AUDIO_QR_CODE_SCANNER)
|
||||
.putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_SINK_IS_GROUP, false)
|
||||
.putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_SINK_IS_GROUP, true)
|
||||
.putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_DEVICE_SINK,
|
||||
mCachedDevice.getDevice());
|
||||
mContext.startActivity(intent);
|
||||
|
||||
111
src/com/android/settings/bluetooth/QrCodeScanModeActivity.java
Normal file
111
src/com/android/settings/bluetooth/QrCodeScanModeActivity.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import static com.android.settingslib.bluetooth.BluetoothBroadcastUtils.EXTRA_BLUETOOTH_DEVICE_SINK;
|
||||
import static com.android.settingslib.bluetooth.BluetoothBroadcastUtils.EXTRA_BLUETOOTH_SINK_IS_GROUP;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
import com.android.settingslib.bluetooth.BluetoothBroadcastUtils;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
|
||||
//TODO (b/232365943): Add test case for tthe QrCode UI.
|
||||
public class QrCodeScanModeActivity extends QrCodeScanModeBaseActivity {
|
||||
private static final boolean DEBUG = BluetoothUtils.D;
|
||||
private static final String TAG = "QrCodeScanModeActivity";
|
||||
|
||||
private boolean mIsGroupOp;
|
||||
private BluetoothDevice mSink;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleIntent(Intent intent) {
|
||||
String action = intent != null ? intent.getAction() : null;
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "handleIntent(), action = " + action);
|
||||
}
|
||||
|
||||
if (action == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case BluetoothBroadcastUtils.ACTION_BLUETOOTH_LE_AUDIO_QR_CODE_SCANNER:
|
||||
showQrCodeScannerFragment(intent);
|
||||
break;
|
||||
default:
|
||||
if (DEBUG) {
|
||||
Log.e(TAG, "Launch with an invalid action");
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
protected void showQrCodeScannerFragment(Intent intent) {
|
||||
if (intent == null) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "intent is null, can not get bluetooth information from intent.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "showQrCodeScannerFragment");
|
||||
}
|
||||
|
||||
mSink = intent.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE_SINK);
|
||||
mIsGroupOp = intent.getBooleanExtra(EXTRA_BLUETOOTH_SINK_IS_GROUP, false);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "get extra from intent");
|
||||
}
|
||||
|
||||
QrCodeScanModeFragment fragment =
|
||||
(QrCodeScanModeFragment) mFragmentManager.findFragmentByTag(
|
||||
BluetoothBroadcastUtils.TAG_FRAGMENT_QR_CODE_SCANNER);
|
||||
|
||||
if (fragment == null) {
|
||||
fragment = new QrCodeScanModeFragment(mIsGroupOp, mSink);
|
||||
} else {
|
||||
if (fragment.isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// When the fragment in back stack but not on top of the stack, we can simply pop
|
||||
// stack because current fragment transactions are arranged in an order
|
||||
mFragmentManager.popBackStackImmediate();
|
||||
return;
|
||||
}
|
||||
final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
|
||||
|
||||
fragmentTransaction.replace(R.id.fragment_container, fragment,
|
||||
BluetoothBroadcastUtils.TAG_FRAGMENT_QR_CODE_SCANNER);
|
||||
fragmentTransaction.commit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
import com.android.settingslib.core.lifecycle.ObservableActivity;
|
||||
|
||||
public abstract class QrCodeScanModeBaseActivity extends ObservableActivity {
|
||||
|
||||
protected FragmentManager mFragmentManager;
|
||||
|
||||
protected abstract void handleIntent(Intent intent);
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setTheme(R.style.SudThemeGlifV3_DayNight);
|
||||
|
||||
setContentView(R.layout.qrcode_scan_mode_activity);
|
||||
mFragmentManager = getSupportFragmentManager();
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
handleIntent(getIntent());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastMetadata;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
|
||||
public class QrCodeScanModeController {
|
||||
|
||||
private static final boolean DEBUG = BluetoothUtils.D;
|
||||
private static final String TAG = "QrCodeScanModeController";
|
||||
|
||||
private LocalBluetoothLeBroadcastMetadata mLocalBroadcastMetadata;
|
||||
private LocalBluetoothLeBroadcastAssistant mLocalBroadcastAssistant;
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
private LocalBluetoothProfileManager mProfileManager;
|
||||
|
||||
public QrCodeScanModeController(Context context) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "QrCodeScanModeController constructor.");
|
||||
}
|
||||
mLocalBluetoothManager = Utils.getLocalBtManager(context);
|
||||
mProfileManager = mLocalBluetoothManager.getProfileManager();
|
||||
mLocalBroadcastMetadata = new LocalBluetoothLeBroadcastMetadata();
|
||||
CachedBluetoothDeviceManager cachedDeviceManager = new CachedBluetoothDeviceManager(context,
|
||||
mLocalBluetoothManager);
|
||||
mLocalBroadcastAssistant = new LocalBluetoothLeBroadcastAssistant(context,
|
||||
cachedDeviceManager, mProfileManager);
|
||||
}
|
||||
|
||||
private BluetoothLeBroadcastMetadata convertToBroadcastMetadata(String qrCodeString) {
|
||||
return mLocalBroadcastMetadata.convertToBroadcastMetadata(qrCodeString);
|
||||
}
|
||||
|
||||
public void addSource(BluetoothDevice sink, String sourceMetadata,
|
||||
boolean isGroupOp) {
|
||||
mLocalBroadcastAssistant.addSource(sink,
|
||||
convertToBroadcastMetadata(sourceMetadata), isGroupOp);
|
||||
}
|
||||
}
|
||||
243
src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
Normal file
243
src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
Normal file
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.TextureView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settings.core.InstrumentedFragment;
|
||||
import com.android.settingslib.R;
|
||||
import com.android.settingslib.bluetooth.BluetoothBroadcastUtils;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.core.lifecycle.ObservableFragment;
|
||||
import com.android.settingslib.qrcode.QrCamera;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
public class QrCodeScanModeFragment extends InstrumentedFragment implements
|
||||
TextureView.SurfaceTextureListener,
|
||||
QrCamera.ScannerCallback {
|
||||
private static final boolean DEBUG = BluetoothUtils.D;
|
||||
private static final String TAG = "QrCodeScanModeFragment";
|
||||
|
||||
/** Message sent to hide error message */
|
||||
private static final int MESSAGE_HIDE_ERROR_MESSAGE = 1;
|
||||
/** Message sent to show error message */
|
||||
private static final int MESSAGE_SHOW_ERROR_MESSAGE = 2;
|
||||
/** Message sent to broadcast QR code */
|
||||
private static final int MESSAGE_SCAN_BROADCAST_SUCCESS = 3;
|
||||
|
||||
private static final long SHOW_ERROR_MESSAGE_INTERVAL = 10000;
|
||||
private static final long SHOW_SUCCESS_SQUARE_INTERVAL = 1000;
|
||||
|
||||
private boolean mIsGroupOp;
|
||||
private int mCornerRadius;
|
||||
private BluetoothDevice mSink;
|
||||
private String mBroadcastMetadata;
|
||||
private Context mContext;
|
||||
private QrCamera mCamera;
|
||||
private QrCodeScanModeController mController;
|
||||
private TextureView mTextureView;
|
||||
private TextView mSummary;
|
||||
private TextView mErrorMessage;
|
||||
|
||||
public QrCodeScanModeFragment(boolean isGroupOp, BluetoothDevice sink) {
|
||||
mIsGroupOp = isGroupOp;
|
||||
mSink = sink;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mContext = getContext();
|
||||
mController = new QrCodeScanModeController(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.qrcode_scanner_fragment, container,
|
||||
/* attachToRoot */ false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
mTextureView = view.findViewById(R.id.preview_view);
|
||||
mCornerRadius = mContext.getResources().getDimensionPixelSize(
|
||||
R.dimen.qrcode_preview_radius);
|
||||
mTextureView.setSurfaceTextureListener(this);
|
||||
mTextureView.setOutlineProvider(new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
outline.setRoundRect(0,0, view.getWidth(), view.getHeight(), mCornerRadius);
|
||||
}
|
||||
});
|
||||
mTextureView.setClipToOutline(true);
|
||||
mErrorMessage = view.findViewById(R.id.error_message);
|
||||
}
|
||||
|
||||
private void initCamera(SurfaceTexture surface) {
|
||||
// Check if the camera has already created.
|
||||
if (mCamera == null) {
|
||||
mCamera = new QrCamera(mContext, this);
|
||||
mCamera.start(surface);
|
||||
}
|
||||
}
|
||||
|
||||
private void destroyCamera() {
|
||||
if (mCamera != null) {
|
||||
mCamera.stop();
|
||||
mCamera = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
|
||||
initCamera(surface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width,
|
||||
int height) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
|
||||
destroyCamera();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSuccessfulResult(String qrCode) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "handleSuccessfulResult(), get the qr code string.");
|
||||
}
|
||||
mBroadcastMetadata = qrCode;
|
||||
handleBtLeAudioScanner();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCameraFailure() {
|
||||
destroyCamera();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size getViewSize() {
|
||||
return new Size(mTextureView.getWidth(), mTextureView.getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect getFramePosition(Size previewSize, int cameraOrientation) {
|
||||
return new Rect(0, 0, previewSize.getHeight(), previewSize.getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransform(Matrix transform) {
|
||||
mTextureView.setTransform(transform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(String qrCode) {
|
||||
if (qrCode.startsWith(BluetoothBroadcastUtils.SCHEME_BT_BROADCAST_METADATA)) {
|
||||
return true;
|
||||
} else {
|
||||
showErrorMessage(R.string.bt_le_audio_qr_code_is_not_valid_format);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isDecodeTaskAlive() {
|
||||
return mCamera != null && mCamera.isDecodeTaskAlive();
|
||||
}
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MESSAGE_HIDE_ERROR_MESSAGE:
|
||||
mErrorMessage.setVisibility(View.INVISIBLE);
|
||||
break;
|
||||
|
||||
case MESSAGE_SHOW_ERROR_MESSAGE:
|
||||
final String errorMessage = (String) msg.obj;
|
||||
|
||||
mErrorMessage.setVisibility(View.VISIBLE);
|
||||
mErrorMessage.setText(errorMessage);
|
||||
mErrorMessage.sendAccessibilityEvent(
|
||||
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
|
||||
// Cancel any pending messages to hide error view and requeue the message so
|
||||
// user has time to see error
|
||||
removeMessages(MESSAGE_HIDE_ERROR_MESSAGE);
|
||||
sendEmptyMessageDelayed(MESSAGE_HIDE_ERROR_MESSAGE,
|
||||
SHOW_ERROR_MESSAGE_INTERVAL);
|
||||
break;
|
||||
|
||||
case MESSAGE_SCAN_BROADCAST_SUCCESS:
|
||||
mController.addSource(mSink, mBroadcastMetadata, mIsGroupOp);
|
||||
updateSummary();
|
||||
mSummary.sendAccessibilityEvent(
|
||||
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void showErrorMessage(@StringRes int messageResId) {
|
||||
final Message message = mHandler.obtainMessage(MESSAGE_SHOW_ERROR_MESSAGE,
|
||||
getString(messageResId));
|
||||
message.sendToTarget();
|
||||
}
|
||||
|
||||
private void handleBtLeAudioScanner() {
|
||||
Message message = mHandler.obtainMessage(MESSAGE_SCAN_BROADCAST_SUCCESS);
|
||||
mHandler.sendMessageDelayed(message, SHOW_SUCCESS_SQUARE_INTERVAL);
|
||||
}
|
||||
|
||||
private void updateSummary() {
|
||||
mSummary.setText(getString(R.string.bt_le_audio_scan_qr_code_scanner,
|
||||
null /* broadcast_name*/));;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.LE_AUDIO_BROADCAST_SCAN_QR_CODE;
|
||||
}
|
||||
}
|
||||
@@ -84,10 +84,19 @@ public class ProfileSelectStorageFragment extends ProfileSelectFragment {
|
||||
}
|
||||
|
||||
final StorageEntry changedStorageEntry = new StorageEntry(getContext(), volumeInfo);
|
||||
switch (volumeInfo.getState()) {
|
||||
final int volumeState = volumeInfo.getState();
|
||||
switch (volumeState) {
|
||||
case VolumeInfo.STATE_REMOVED:
|
||||
case VolumeInfo.STATE_BAD_REMOVAL:
|
||||
// Remove removed storage from list and don't show it on spinner.
|
||||
if (!mStorageEntries.remove(changedStorageEntry)) {
|
||||
break;
|
||||
}
|
||||
case VolumeInfo.STATE_MOUNTED:
|
||||
case VolumeInfo.STATE_MOUNTED_READ_ONLY:
|
||||
case VolumeInfo.STATE_UNMOUNTABLE:
|
||||
case VolumeInfo.STATE_UNMOUNTED:
|
||||
case VolumeInfo.STATE_EJECTING:
|
||||
// Add mounted or unmountable storage in the list and show it on spinner.
|
||||
// Unmountable storages are the storages which has a problem format and android
|
||||
// is not able to mount it automatically.
|
||||
@@ -95,25 +104,15 @@ public class ProfileSelectStorageFragment extends ProfileSelectFragment {
|
||||
mStorageEntries.removeIf(storageEntry -> {
|
||||
return storageEntry.equals(changedStorageEntry);
|
||||
});
|
||||
mStorageEntries.add(changedStorageEntry);
|
||||
if (volumeState != VolumeInfo.STATE_REMOVED
|
||||
&& volumeState != VolumeInfo.STATE_BAD_REMOVAL) {
|
||||
mStorageEntries.add(changedStorageEntry);
|
||||
}
|
||||
if (changedStorageEntry.equals(mSelectedStorageEntry)) {
|
||||
mSelectedStorageEntry = changedStorageEntry;
|
||||
}
|
||||
refreshUi();
|
||||
break;
|
||||
case VolumeInfo.STATE_REMOVED:
|
||||
case VolumeInfo.STATE_UNMOUNTED:
|
||||
case VolumeInfo.STATE_BAD_REMOVAL:
|
||||
case VolumeInfo.STATE_EJECTING:
|
||||
// Remove removed storage from list and don't show it on spinner.
|
||||
if (mStorageEntries.remove(changedStorageEntry)) {
|
||||
if (changedStorageEntry.equals(mSelectedStorageEntry)) {
|
||||
mSelectedStorageEntry =
|
||||
StorageEntry.getDefaultInternalStorageEntry(getContext());
|
||||
}
|
||||
refreshUi();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.android.settingslib.net.NetworkCycleData;
|
||||
import com.android.settingslib.widget.SettingsSpinnerAdapter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class CycleAdapter extends SettingsSpinnerAdapter<CycleAdapter.CycleItem> {
|
||||
|
||||
@@ -67,7 +66,7 @@ public class CycleAdapter extends SettingsSpinnerAdapter<CycleAdapter.CycleItem>
|
||||
* Rebuild list based on network data. Always selects the newest item,
|
||||
* updating the inspection range on chartData.
|
||||
*/
|
||||
public boolean updateCycleList(List<? extends NetworkCycleData> cycleData) {
|
||||
public void updateCycleList(List<? extends NetworkCycleData> cycleData) {
|
||||
mSpinner.setOnItemSelectedListener(mListener);
|
||||
// stash away currently selected cycle to try restoring below
|
||||
final CycleAdapter.CycleItem previousItem = (CycleAdapter.CycleItem)
|
||||
@@ -83,16 +82,7 @@ public class CycleAdapter extends SettingsSpinnerAdapter<CycleAdapter.CycleItem>
|
||||
if (getCount() > 0) {
|
||||
final int position = findNearestPosition(previousItem);
|
||||
mSpinner.setSelection(position);
|
||||
|
||||
// only force-update cycle when changed; skipping preserves any
|
||||
// user-defined inspection region.
|
||||
final CycleAdapter.CycleItem selectedItem = getItem(position);
|
||||
if (!Objects.equals(selectedItem, previousItem)) {
|
||||
mListener.onItemSelected(null, null, position, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -69,6 +69,7 @@ import com.android.settingslib.net.UidDetailProvider;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Panel showing data usage history across various networks, including options
|
||||
@@ -111,7 +112,11 @@ public class DataUsageList extends DataUsageBaseFragment
|
||||
|
||||
private ChartDataUsagePreference mChart;
|
||||
private List<NetworkCycleChartData> mCycleData;
|
||||
// Caches the cycles for startAppDataUsage usage, which need be cleared when resumed.
|
||||
private ArrayList<Long> mCycles;
|
||||
// Spinner will keep the selected cycle even after paused, this only keeps the displayed cycle,
|
||||
// which need be cleared when resumed.
|
||||
private CycleAdapter.CycleItem mLastDisplayedCycle;
|
||||
private UidDetailProvider mUidDetailProvider;
|
||||
private CycleAdapter mCycleAdapter;
|
||||
private Preference mUsageAmount;
|
||||
@@ -199,13 +204,15 @@ public class DataUsageList extends DataUsageBaseFragment
|
||||
|
||||
mLoadingViewController = new LoadingViewController(
|
||||
getView().findViewById(R.id.loading_container), getListView());
|
||||
mLoadingViewController.showLoadingViewDelayed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mLoadingViewController.showLoadingViewDelayed();
|
||||
mDataStateListener.start(mSubId);
|
||||
mCycles = null;
|
||||
mLastDisplayedCycle = null;
|
||||
|
||||
// kick off loader for network history
|
||||
// TODO: consider chaining two loaders together instead of reloading
|
||||
@@ -319,9 +326,46 @@ public class DataUsageList extends DataUsageBaseFragment
|
||||
}
|
||||
|
||||
// generate cycle list based on policy and available history
|
||||
if (mCycleAdapter.updateCycleList(mCycleData)) {
|
||||
updateDetailData();
|
||||
mCycleAdapter.updateCycleList(mCycleData);
|
||||
updateSelectedCycle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the chart and detail data when initial loaded or selected cycle changed.
|
||||
*/
|
||||
private void updateSelectedCycle() {
|
||||
// Avoid from updating UI after #onStop.
|
||||
if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Avoid from updating UI when async query still on-going.
|
||||
// This could happen when a request from #onMobileDataEnabledChange.
|
||||
if (mCycleData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int position = mCycleSpinner.getSelectedItemPosition();
|
||||
if (mCycleAdapter.getCount() == 0 || position < 0) {
|
||||
return;
|
||||
}
|
||||
final CycleAdapter.CycleItem cycle = mCycleAdapter.getItem(position);
|
||||
if (Objects.equals(cycle, mLastDisplayedCycle)) {
|
||||
// Avoid duplicate update to avoid page flash.
|
||||
return;
|
||||
}
|
||||
mLastDisplayedCycle = cycle;
|
||||
|
||||
if (LOGD) {
|
||||
Log.d(TAG, "showing cycle " + cycle + ", [start=" + cycle.start + ", end="
|
||||
+ cycle.end + "]");
|
||||
}
|
||||
|
||||
// update chart to show selected cycle, and update detail data
|
||||
// to match updated sweep bounds.
|
||||
mChart.setNetworkCycleData(mCycleData.get(position));
|
||||
|
||||
updateDetailData();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -495,33 +539,10 @@ public class DataUsageList extends DataUsageBaseFragment
|
||||
return Math.max(largest, item.total);
|
||||
}
|
||||
|
||||
private OnItemSelectedListener mCycleListener = new OnItemSelectedListener() {
|
||||
private final OnItemSelectedListener mCycleListener = new OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem)
|
||||
mCycleSpinner.getSelectedItem();
|
||||
|
||||
if (LOGD) {
|
||||
Log.d(TAG, "showing cycle " + cycle + ", start=" + cycle.start + ", end="
|
||||
+ cycle.end + "]");
|
||||
}
|
||||
|
||||
// Avoid from updating UI after #onStop.
|
||||
if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Avoid from updating UI when async query still on-going.
|
||||
// This could happen when a request from #onMobileDataEnabledChange.
|
||||
if (mCycleData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update chart to show selected cycle, and update detail data
|
||||
// to match updated sweep bounds.
|
||||
mChart.setNetworkCycleData(mCycleData.get(position));
|
||||
|
||||
updateDetailData();
|
||||
updateSelectedCycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package com.android.settings.datausage;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
@@ -28,6 +29,7 @@ import com.android.settings.R;
|
||||
public class SpinnerPreference extends Preference implements CycleAdapter.SpinnerInterface {
|
||||
|
||||
private CycleAdapter mAdapter;
|
||||
@Nullable
|
||||
private AdapterView.OnItemSelectedListener mListener;
|
||||
private Object mCurrentObject;
|
||||
private int mPosition;
|
||||
@@ -88,19 +90,24 @@ public class SpinnerPreference extends Preference implements CycleAdapter.Spinne
|
||||
view.findViewById(R.id.cycles_spinner).performClick();
|
||||
}
|
||||
|
||||
private final AdapterView.OnItemSelectedListener mOnSelectedListener
|
||||
= new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (mPosition == position) return;
|
||||
mPosition = position;
|
||||
mCurrentObject = mAdapter.getItem(position);
|
||||
mListener.onItemSelected(parent, view, position, id);
|
||||
}
|
||||
private final AdapterView.OnItemSelectedListener mOnSelectedListener =
|
||||
new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(
|
||||
AdapterView<?> parent, View view, int position, long id) {
|
||||
if (mPosition == position) return;
|
||||
mPosition = position;
|
||||
mCurrentObject = mAdapter.getItem(position);
|
||||
if (mListener != null) {
|
||||
mListener.onItemSelected(parent, view, position, id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
mListener.onNothingSelected(parent);
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
if (mListener != null) {
|
||||
mListener.onNothingSelected(parent);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -115,10 +115,19 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
}
|
||||
|
||||
final StorageEntry changedStorageEntry = new StorageEntry(getContext(), volumeInfo);
|
||||
switch (volumeInfo.getState()) {
|
||||
final int volumeState = volumeInfo.getState();
|
||||
switch (volumeState) {
|
||||
case VolumeInfo.STATE_REMOVED:
|
||||
case VolumeInfo.STATE_BAD_REMOVAL:
|
||||
// Remove removed storage from list and don't show it on spinner.
|
||||
if (!mStorageEntries.remove(changedStorageEntry)) {
|
||||
break;
|
||||
}
|
||||
case VolumeInfo.STATE_MOUNTED:
|
||||
case VolumeInfo.STATE_MOUNTED_READ_ONLY:
|
||||
case VolumeInfo.STATE_UNMOUNTABLE:
|
||||
case VolumeInfo.STATE_UNMOUNTED:
|
||||
case VolumeInfo.STATE_EJECTING:
|
||||
// Add mounted or unmountable storage in the list and show it on spinner.
|
||||
// Unmountable storages are the storages which has a problem format and android
|
||||
// is not able to mount it automatically.
|
||||
@@ -126,25 +135,15 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
mStorageEntries.removeIf(storageEntry -> {
|
||||
return storageEntry.equals(changedStorageEntry);
|
||||
});
|
||||
mStorageEntries.add(changedStorageEntry);
|
||||
if (volumeState != VolumeInfo.STATE_REMOVED
|
||||
&& volumeState != VolumeInfo.STATE_BAD_REMOVAL) {
|
||||
mStorageEntries.add(changedStorageEntry);
|
||||
}
|
||||
if (changedStorageEntry.equals(mSelectedStorageEntry)) {
|
||||
mSelectedStorageEntry = changedStorageEntry;
|
||||
}
|
||||
refreshUi();
|
||||
break;
|
||||
case VolumeInfo.STATE_REMOVED:
|
||||
case VolumeInfo.STATE_UNMOUNTED:
|
||||
case VolumeInfo.STATE_BAD_REMOVAL:
|
||||
case VolumeInfo.STATE_EJECTING:
|
||||
// Remove removed storage from list and don't show it on spinner.
|
||||
if (mStorageEntries.remove(changedStorageEntry)) {
|
||||
if (changedStorageEntry.equals(mSelectedStorageEntry)) {
|
||||
mSelectedStorageEntry =
|
||||
StorageEntry.getDefaultInternalStorageEntry(getContext());
|
||||
}
|
||||
refreshUi();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.os.UserManager;
|
||||
import android.os.storage.DiskInfo;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
@@ -53,6 +54,8 @@ import java.util.Objects;
|
||||
public class VolumeOptionMenuController implements LifecycleObserver, OnCreateOptionsMenu,
|
||||
OnPrepareOptionsMenu, OnOptionsItemSelected {
|
||||
|
||||
private static final String TAG = "VolumeOptionMenuController";
|
||||
|
||||
@VisibleForTesting
|
||||
MenuItem mRename;
|
||||
@VisibleForTesting
|
||||
@@ -103,6 +106,17 @@ public class VolumeOptionMenuController implements LifecycleObserver, OnCreateOp
|
||||
mFree = menu.findItem(R.id.storage_free);
|
||||
mForget = menu.findItem(R.id.storage_forget);
|
||||
|
||||
updateOptionsMenu();
|
||||
}
|
||||
|
||||
private void updateOptionsMenu() {
|
||||
if (mRename == null || mMount == null || mUnmount == null || mFormat == null
|
||||
|| mFormatAsPortable == null || mFormatAsInternal == null || mMigrate == null
|
||||
|| mFree == null || mForget == null) {
|
||||
Log.d(TAG, "Menu items are not available");
|
||||
return;
|
||||
}
|
||||
|
||||
mRename.setVisible(false);
|
||||
mMount.setVisible(false);
|
||||
mUnmount.setVisible(false);
|
||||
@@ -252,5 +266,7 @@ public class VolumeOptionMenuController implements LifecycleObserver, OnCreateOp
|
||||
|
||||
public void setSelectedStorageEntry(StorageEntry storageEntry) {
|
||||
mStorageEntry = storageEntry;
|
||||
|
||||
updateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import static android.provider.Settings.ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY
|
||||
import static android.provider.Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_HIGHLIGHT_MENU_KEY;
|
||||
import static android.provider.Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI;
|
||||
|
||||
import static com.android.settings.SettingsActivity.EXTRA_USER_HANDLE;
|
||||
|
||||
import android.animation.LayoutTransition;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
@@ -27,6 +29,7 @@ import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.FeatureFlagUtils;
|
||||
@@ -449,7 +452,13 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
SplitRule.FINISH_ALWAYS,
|
||||
SplitRule.FINISH_ALWAYS,
|
||||
true /* clearTop */);
|
||||
startActivity(targetIntent);
|
||||
|
||||
final UserHandle user = intent.getParcelableExtra(EXTRA_USER_HANDLE, UserHandle.class);
|
||||
if (user != null) {
|
||||
startActivityAsUser(targetIntent, user);
|
||||
} else {
|
||||
startActivity(targetIntent);
|
||||
}
|
||||
}
|
||||
|
||||
private String getHighlightMenuKey() {
|
||||
|
||||
@@ -118,6 +118,7 @@ public class AppLocalePickerActivity extends SettingsBaseActivity
|
||||
|
||||
/** Sets the app's locale to the supplied language tag */
|
||||
private void setAppDefaultLocale(String languageTag) {
|
||||
Log.d(TAG, "setAppDefaultLocale: " + languageTag);
|
||||
LocaleManager localeManager = mContextAsUser.getSystemService(LocaleManager.class);
|
||||
if (localeManager == null) {
|
||||
Log.w(TAG, "LocaleManager is null, cannot set default app locale");
|
||||
|
||||
@@ -67,7 +67,6 @@ import com.android.settings.datausage.DataUsagePreference;
|
||||
import com.android.settings.datausage.DataUsageUtils;
|
||||
import com.android.settings.location.WifiScanningFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.utils.AnnotationSpan;
|
||||
import com.android.settings.wifi.AddNetworkFragment;
|
||||
import com.android.settings.wifi.AddWifiNetworkPreference;
|
||||
import com.android.settings.wifi.ConfigureWifiEntryFragment;
|
||||
@@ -829,12 +828,10 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment
|
||||
return;
|
||||
}
|
||||
if (TextUtils.isEmpty(mWifiStatusMessagePreference.getTitle())) {
|
||||
AnnotationSpan.LinkInfo info = new AnnotationSpan.LinkInfo(
|
||||
AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION,
|
||||
v -> launchWifiScanningFragment());
|
||||
CharSequence text = AnnotationSpan.linkify(
|
||||
context.getText(R.string.wifi_scan_notify_message), info);
|
||||
mWifiStatusMessagePreference.setTitle(text);
|
||||
mWifiStatusMessagePreference.setTitle(R.string.wifi_scan_notify_message);
|
||||
mWifiStatusMessagePreference.setLearnMoreText(
|
||||
context.getString(R.string.wifi_scan_change));
|
||||
mWifiStatusMessagePreference.setLearnMoreAction(v -> launchWifiScanningFragment());
|
||||
}
|
||||
mWifiStatusMessagePreference.setVisible(true);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROF
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
@@ -36,6 +37,7 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@SearchIndexable
|
||||
@@ -72,12 +74,6 @@ public class PrivacyDashboardFragment extends DashboardFragment {
|
||||
replaceEnterpriseStringSummary("work_policy_info",
|
||||
WORK_PROFILE_PRIVACY_POLICY_INFO_SUMMARY,
|
||||
R.string.work_policy_privacy_settings_summary);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.privacy_dashboard_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,6 +86,19 @@ public class PrivacyDashboardFragment extends DashboardFragment {
|
||||
return buildPreferenceControllers(context, getSettingsLifecycle());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return getPreferenceScreenResId(getContext());
|
||||
}
|
||||
|
||||
private static int getPreferenceScreenResId(Context context) {
|
||||
if (SafetyCenterManagerWrapper.get().isEnabled(context)) {
|
||||
return R.xml.privacy_advanced_settings;
|
||||
} else {
|
||||
return R.xml.privacy_dashboard_settings;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(
|
||||
Context context, Lifecycle lifecycle) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
@@ -108,17 +117,19 @@ public class PrivacyDashboardFragment extends DashboardFragment {
|
||||
}
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.privacy_dashboard_settings) {
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
||||
Context context, boolean enabled) {
|
||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = getPreferenceScreenResId(context);
|
||||
return Arrays.asList(sir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractPreferenceController> createPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPageSearchEnabled(Context context) {
|
||||
return !SafetyCenterManagerWrapper.get().isEnabled(context);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -49,9 +49,9 @@ public class SafetySourceBroadcastReceiver extends BroadcastReceiver {
|
||||
if (ACTION_REFRESH_SAFETY_SOURCES.equals(intent.getAction())) {
|
||||
String[] sourceIdsExtra =
|
||||
intent.getStringArrayExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS);
|
||||
if (sourceIdsExtra != null && sourceIdsExtra.length > 0) {
|
||||
final String refreshBroadcastId = intent.getStringExtra(
|
||||
SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID);
|
||||
final String refreshBroadcastId = intent.getStringExtra(
|
||||
SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID);
|
||||
if (sourceIdsExtra != null && sourceIdsExtra.length > 0 && refreshBroadcastId != null) {
|
||||
final SafetyEvent safetyEvent = new SafetyEvent.Builder(
|
||||
SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
|
||||
.setRefreshBroadcastId(refreshBroadcastId).build();
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Switch;
|
||||
|
||||
import androidx.core.content.res.TypedArrayUtils;
|
||||
@@ -33,6 +34,8 @@ import com.android.settings.widget.SettingsMainSwitchBar.OnBeforeCheckedChangeLi
|
||||
import com.android.settingslib.RestrictedPreferenceHelper;
|
||||
import com.android.settingslib.widget.OnMainSwitchChangeListener;
|
||||
|
||||
import com.google.android.setupdesign.util.LayoutStyler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -48,6 +51,7 @@ public class SettingsMainSwitchPreference extends TwoStatePreference implements
|
||||
new ArrayList<>();
|
||||
private final List<OnMainSwitchChangeListener> mSwitchChangeListeners = new ArrayList<>();
|
||||
|
||||
private boolean mApplyPartnerCustomizationPaddingStyle;
|
||||
private SettingsMainSwitchBar mMainSwitchBar;
|
||||
private CharSequence mTitle;
|
||||
private EnforcedAdmin mEnforcedAdmin;
|
||||
@@ -95,6 +99,12 @@ public class SettingsMainSwitchPreference extends TwoStatePreference implements
|
||||
} else {
|
||||
mMainSwitchBar.hide();
|
||||
}
|
||||
|
||||
if (mApplyPartnerCustomizationPaddingStyle) {
|
||||
// TODO(b/232494666): Replace all margins of the root view with the padding
|
||||
final ViewGroup parentView = (ViewGroup) mMainSwitchBar.getParent();
|
||||
LayoutStyler.applyPartnerCustomizationLayoutPaddingStyle(parentView);
|
||||
}
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
@@ -241,6 +251,14 @@ public class SettingsMainSwitchPreference extends TwoStatePreference implements
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apples the padding style of the partner's customization. It's used in the SetupWizard.
|
||||
*/
|
||||
public void applyPartnerCustomizationPaddingStyle() {
|
||||
mApplyPartnerCustomizationPaddingStyle = true;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
private void initMainSwitchBar() {
|
||||
if (mMainSwitchBar != null) {
|
||||
mMainSwitchBar.setTitle(mTitle);
|
||||
|
||||
@@ -20,26 +20,30 @@ import android.app.Dialog;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settingslib.wifi.WifiPermissionChecker;
|
||||
|
||||
/**
|
||||
* This activity requests users permission to allow scanning even when Wi-Fi is turned off
|
||||
*/
|
||||
public class WifiScanModeActivity extends FragmentActivity {
|
||||
private DialogFragment mDialog;
|
||||
private String mApp;
|
||||
@VisibleForTesting
|
||||
String mApp;
|
||||
@VisibleForTesting
|
||||
WifiPermissionChecker mWifiPermissionChecker;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -50,13 +54,7 @@ public class WifiScanModeActivity extends FragmentActivity {
|
||||
if (savedInstanceState == null) {
|
||||
if (intent != null && WifiManager.ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE
|
||||
.equals(intent.getAction())) {
|
||||
ApplicationInfo ai;
|
||||
mApp = getCallingPackage();
|
||||
try {
|
||||
PackageManager pm = getPackageManager();
|
||||
ai = pm.getApplicationInfo(mApp, 0);
|
||||
mApp = (String)pm.getApplicationLabel(ai);
|
||||
} catch (PackageManager.NameNotFoundException e) { }
|
||||
refreshAppLabel();
|
||||
} else {
|
||||
finish();
|
||||
return;
|
||||
@@ -67,6 +65,19 @@ public class WifiScanModeActivity extends FragmentActivity {
|
||||
createDialog();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void refreshAppLabel() {
|
||||
if (mWifiPermissionChecker == null) {
|
||||
mWifiPermissionChecker = new WifiPermissionChecker(this);
|
||||
}
|
||||
String packageName = mWifiPermissionChecker.getLaunchedPackage();
|
||||
if (TextUtils.isEmpty(packageName)) {
|
||||
mApp = null;
|
||||
return;
|
||||
}
|
||||
mApp = Utils.getApplicationLabel(getApplicationContext(), packageName).toString();
|
||||
}
|
||||
|
||||
private void createDialog() {
|
||||
if (mDialog == null) {
|
||||
mDialog = AlertDialogFragment.newInstance(mApp);
|
||||
|
||||
@@ -30,13 +30,12 @@ import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
|
||||
import com.android.internal.util.CollectionUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.InstrumentedFragment;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.network.ActiveSubscriptionsListener;
|
||||
import com.android.settings.network.SubscriptionUtil;
|
||||
import com.android.settings.network.ims.WifiCallingQueryImsState;
|
||||
@@ -54,7 +53,8 @@ import java.util.List;
|
||||
* "Wi-Fi Calling settings" screen. This is the container fragment which holds
|
||||
* {@link WifiCallingSettingsForSub} fragments.
|
||||
*/
|
||||
public class WifiCallingSettings extends InstrumentedFragment implements HelpResourceProvider {
|
||||
public class WifiCallingSettings extends SettingsPreferenceFragment
|
||||
implements HelpResourceProvider {
|
||||
private static final String TAG = "WifiCallingSettings";
|
||||
private int mConstructionSubId;
|
||||
private List<SubscriptionInfo> mSil;
|
||||
@@ -317,17 +317,7 @@ public class WifiCallingSettings extends InstrumentedFragment implements HelpRes
|
||||
}
|
||||
|
||||
// close this fragment
|
||||
finish();
|
||||
}
|
||||
|
||||
protected void finish() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity == null) return;
|
||||
if (getFragmentManager().getBackStackEntryCount() > 0) {
|
||||
getFragmentManager().popBackStack();
|
||||
} else {
|
||||
activity.finish();
|
||||
}
|
||||
finishFragment();
|
||||
}
|
||||
|
||||
protected int [] subscriptionIdList(List<SubscriptionInfo> subInfoList) {
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyCallback;
|
||||
import android.telephony.TelephonyManager;
|
||||
@@ -40,7 +39,6 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.Preference;
|
||||
@@ -56,8 +54,7 @@ import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.network.ims.WifiCallingQueryImsState;
|
||||
import com.android.settings.widget.SettingsMainSwitchBar;
|
||||
import com.android.settings.wifi.calling.LinkifyDescriptionPreference;
|
||||
import com.android.settings.widget.SettingsMainSwitchPreference;
|
||||
import com.android.settingslib.widget.OnMainSwitchChangeListener;
|
||||
|
||||
import java.util.List;
|
||||
@@ -72,6 +69,7 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||
private static final String TAG = "WifiCallingForSub";
|
||||
|
||||
//String keys for preference lookup
|
||||
private static final String SWITCH_BAR = "wifi_calling_switch_bar";
|
||||
private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
|
||||
private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
|
||||
private static final String PREFERENCE_EMERGENCY_ADDRESS = "emergency_address_key";
|
||||
@@ -91,7 +89,7 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||
public static final int LAUCH_APP_UPDATE = 1;
|
||||
|
||||
//UI objects
|
||||
private SettingsMainSwitchBar mSwitchBar;
|
||||
private SettingsMainSwitchPreference mSwitchBar;
|
||||
private ListWithEntrySummaryPreference mButtonWfcMode;
|
||||
private ListWithEntrySummaryPreference mButtonWfcRoamingMode;
|
||||
private Preference mUpdateAddress;
|
||||
@@ -119,41 +117,57 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||
@Override
|
||||
public void onCallStateChanged(int state) {
|
||||
final SettingsActivity activity = (SettingsActivity) getActivity();
|
||||
final boolean isNonTtyOrTtyOnVolteEnabled =
|
||||
queryImsState(WifiCallingSettingsForSub.this.mSubId).isAllowUserControl();
|
||||
final boolean isWfcEnabled = mSwitchBar.isChecked()
|
||||
&& isNonTtyOrTtyOnVolteEnabled;
|
||||
boolean isCallStateIdle = getTelephonyManagerForSub(
|
||||
WifiCallingSettingsForSub.this.mSubId).getCallState()
|
||||
== TelephonyManager.CALL_STATE_IDLE;
|
||||
mSwitchBar.setEnabled(isCallStateIdle
|
||||
&& isNonTtyOrTtyOnVolteEnabled);
|
||||
|
||||
boolean isWfcEnabled = false;
|
||||
boolean isCallStateIdle = false;
|
||||
|
||||
final SettingsMainSwitchPreference prefSwitch = (SettingsMainSwitchPreference)
|
||||
getPreferenceScreen().findPreference(SWITCH_BAR);
|
||||
if (prefSwitch != null) {
|
||||
isWfcEnabled = prefSwitch.isChecked();
|
||||
isCallStateIdle = getTelephonyManagerForSub(
|
||||
WifiCallingSettingsForSub.this.mSubId).getCallState()
|
||||
== TelephonyManager.CALL_STATE_IDLE;
|
||||
|
||||
boolean isNonTtyOrTtyOnVolteEnabled = true;
|
||||
if (isWfcEnabled || isCallStateIdle) {
|
||||
isNonTtyOrTtyOnVolteEnabled =
|
||||
queryImsState(WifiCallingSettingsForSub.this.mSubId)
|
||||
.isAllowUserControl();
|
||||
}
|
||||
|
||||
isWfcEnabled = isWfcEnabled && isNonTtyOrTtyOnVolteEnabled;
|
||||
prefSwitch.setEnabled(isCallStateIdle && isNonTtyOrTtyOnVolteEnabled);
|
||||
}
|
||||
|
||||
boolean isWfcModeEditable = true;
|
||||
boolean isWfcRoamingModeEditable = false;
|
||||
final CarrierConfigManager configManager = (CarrierConfigManager)
|
||||
activity.getSystemService(Context.CARRIER_CONFIG_SERVICE);
|
||||
if (configManager != null) {
|
||||
PersistableBundle b =
|
||||
configManager.getConfigForSubId(WifiCallingSettingsForSub.this.mSubId);
|
||||
if (b != null) {
|
||||
isWfcModeEditable = b.getBoolean(
|
||||
CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
|
||||
isWfcRoamingModeEditable = b.getBoolean(
|
||||
CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
|
||||
if (isWfcEnabled && isCallStateIdle) {
|
||||
final CarrierConfigManager configManager = (CarrierConfigManager)
|
||||
activity.getSystemService(Context.CARRIER_CONFIG_SERVICE);
|
||||
if (configManager != null) {
|
||||
PersistableBundle b = configManager.getConfigForSubId(
|
||||
WifiCallingSettingsForSub.this.mSubId);
|
||||
if (b != null) {
|
||||
isWfcModeEditable = b.getBoolean(
|
||||
CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
|
||||
isWfcRoamingModeEditable = b.getBoolean(
|
||||
CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isWfcModeEditable = false;
|
||||
isWfcRoamingModeEditable = false;
|
||||
}
|
||||
|
||||
final Preference pref = getPreferenceScreen().findPreference(BUTTON_WFC_MODE);
|
||||
if (pref != null) {
|
||||
pref.setEnabled(isWfcEnabled && isWfcModeEditable
|
||||
&& isCallStateIdle);
|
||||
pref.setEnabled(isWfcModeEditable);
|
||||
}
|
||||
final Preference pref_roam =
|
||||
getPreferenceScreen().findPreference(BUTTON_WFC_ROAMING_MODE);
|
||||
if (pref_roam != null) {
|
||||
pref_roam.setEnabled(isWfcEnabled && isWfcRoamingModeEditable
|
||||
&& isCallStateIdle);
|
||||
pref_roam.setEnabled(isWfcRoamingModeEditable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,20 +198,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
mSwitchBar = getView().findViewById(R.id.switch_bar);
|
||||
mSwitchBar.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mSwitchBar.hide();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void showAlert(Intent intent) {
|
||||
final Context context = getActivity();
|
||||
@@ -292,6 +292,8 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||
mProvisioningManager = getImsProvisioningManager();
|
||||
mImsMmTelManager = getImsMmTelManager();
|
||||
|
||||
mSwitchBar = (SettingsMainSwitchPreference) findPreference(SWITCH_BAR);
|
||||
|
||||
mButtonWfcMode = findPreference(BUTTON_WFC_MODE);
|
||||
mButtonWfcMode.setOnPreferenceChangeListener(this);
|
||||
|
||||
|
||||
@@ -522,7 +522,7 @@ public class WifiP2pSettings extends DashboardFragment
|
||||
final LayoutInflater layoutInflater = LayoutInflater.from(getPrefContext());
|
||||
final View root = layoutInflater.inflate(R.layout.dialog_edittext, null /* root */);
|
||||
mDeviceNameText = root.findViewById(R.id.edittext);
|
||||
mDeviceNameText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(30)});
|
||||
mDeviceNameText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(22)});
|
||||
if (mSavedDeviceName != null) {
|
||||
mDeviceNameText.setText(mSavedDeviceName);
|
||||
mDeviceNameText.setSelection(mSavedDeviceName.length());
|
||||
|
||||
@@ -256,6 +256,7 @@ public class TetherService extends Service {
|
||||
}
|
||||
|
||||
private void disableTethering(final int tetheringType) {
|
||||
Log.w(TAG, "Disable tethering, type:" + tetheringType);
|
||||
final TetheringManager tm = (TetheringManager) getSystemService(Context.TETHERING_SERVICE);
|
||||
tm.stopTethering(tetheringType);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.net.ConnectivityManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.widget.Switch;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@@ -47,6 +48,8 @@ import com.android.settingslib.widget.OnMainSwitchChangeListener;
|
||||
*/
|
||||
public class WifiTetherSwitchBarController implements
|
||||
LifecycleObserver, OnStart, OnStop, DataSaverBackend.Listener, OnMainSwitchChangeListener {
|
||||
|
||||
private static final String TAG = "WifiTetherSBC";
|
||||
private static final IntentFilter WIFI_INTENT_FILTER;
|
||||
|
||||
private final Context mContext;
|
||||
@@ -63,8 +66,8 @@ public class WifiTetherSwitchBarController implements
|
||||
@Override
|
||||
public void onTetheringFailed() {
|
||||
super.onTetheringFailed();
|
||||
mSwitchBar.setChecked(false);
|
||||
updateWifiSwitch();
|
||||
Log.e(TAG, "Failed to start Wi-Fi Tethering.");
|
||||
handleWifiApStateChanged(mWifiManager.getWifiApState());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -111,16 +114,28 @@ public class WifiTetherSwitchBarController implements
|
||||
}
|
||||
|
||||
void stopTether() {
|
||||
if (!isWifiApActivated()) return;
|
||||
|
||||
mSwitchBar.setEnabled(false);
|
||||
mConnectivityManager.stopTethering(TETHERING_WIFI);
|
||||
}
|
||||
|
||||
void startTether() {
|
||||
if (isWifiApActivated()) return;
|
||||
|
||||
mSwitchBar.setEnabled(false);
|
||||
mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
|
||||
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
|
||||
}
|
||||
|
||||
private boolean isWifiApActivated() {
|
||||
final int wifiApState = mWifiManager.getWifiApState();
|
||||
if (wifiApState == WIFI_AP_STATE_ENABLED || wifiApState == WIFI_AP_STATE_ENABLING) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static com.android.settings.accessibility.TextReadingPreferenceFragment.RESET_KEY;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -25,6 +27,7 @@ import android.content.Context;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.widget.LayoutPreference;
|
||||
|
||||
import com.google.android.setupdesign.GlifPreferenceLayout;
|
||||
|
||||
@@ -51,6 +54,9 @@ public class TextReadingPreferenceFragmentForSetupWizardTest {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mFragment = spy(new TextReadingPreferenceFragmentForSetupWizard());
|
||||
final LayoutPreference resetPreference =
|
||||
new LayoutPreference(mContext, R.layout.accessibility_text_reading_reset_button);
|
||||
doReturn(resetPreference).when(mFragment).findPreference(RESET_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -33,6 +33,11 @@ import org.robolectric.RuntimeEnvironment;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class BluetoothFeatureProviderImplTest {
|
||||
private static final String SETTINGS_URI = "content://test.provider/settings_uri";
|
||||
private static final String CONTROL_METADATA =
|
||||
"<HEARABLE_CONTROL_SLICE_WITH_WIDTH>" + SETTINGS_URI
|
||||
+ "</HEARABLE_CONTROL_SLICE_WITH_WIDTH>";
|
||||
private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
|
||||
|
||||
private BluetoothFeatureProvider mBluetoothFeatureProvider;
|
||||
|
||||
@Mock
|
||||
@@ -54,4 +59,13 @@ public class BluetoothFeatureProviderImplTest {
|
||||
final Uri uri = mBluetoothFeatureProvider.getBluetoothDeviceSettingsUri(mBluetoothDevice);
|
||||
assertThat(uri.toString()).isEqualTo(SETTINGS_URI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBluetoothDeviceControlUri_returnsCorrectUri() {
|
||||
when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS)).thenReturn(
|
||||
CONTROL_METADATA.getBytes());
|
||||
assertThat(
|
||||
mBluetoothFeatureProvider.getBluetoothDeviceControlUri(mBluetoothDevice)).isEqualTo(
|
||||
SETTINGS_URI);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ public class DataUsageListTest {
|
||||
mMobileDataEnabledListener);
|
||||
ReflectionHelpers.setField(mDataUsageList, "services", mNetworkServices);
|
||||
doReturn(mLoaderManager).when(mDataUsageList).getLoaderManager();
|
||||
mDataUsageList.mLoadingViewController = mock(LoadingViewController.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -207,8 +208,6 @@ public class DataUsageListTest {
|
||||
|
||||
@Test
|
||||
public void onLoadFinished_networkCycleDataCallback_shouldShowCycleSpinner() {
|
||||
final LoadingViewController loadingViewController = mock(LoadingViewController.class);
|
||||
mDataUsageList.mLoadingViewController = loadingViewController;
|
||||
final Spinner spinner = getSpinner(getHeader());
|
||||
spinner.setVisibility(View.INVISIBLE);
|
||||
mDataUsageList.mCycleSpinner = spinner;
|
||||
|
||||
@@ -16,16 +16,75 @@
|
||||
|
||||
package com.android.settings.wifi;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
import com.android.settingslib.wifi.WifiPermissionChecker;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowUtils.class})
|
||||
public class WifiScanModeActivityTest {
|
||||
|
||||
static final String LAUNCHED_PACKAGE = "launched_package";
|
||||
static final String APP_LABEL = "app_label";
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Mock
|
||||
WifiPermissionChecker mWifiPermissionChecker;
|
||||
|
||||
WifiScanModeActivity mActivity;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mActivity = spy(Robolectric.setupActivity(WifiScanModeActivity.class));
|
||||
mActivity.mWifiPermissionChecker = mWifiPermissionChecker;
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowUtils.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchActivity_noIntentAction_shouldNotFatalException() {
|
||||
WifiScanModeActivity wifiScanModeActivity =
|
||||
Robolectric.setupActivity(WifiScanModeActivity.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshAppLabel_noPackageName_shouldNotFatalException() {
|
||||
when(mWifiPermissionChecker.getLaunchedPackage()).thenReturn(null);
|
||||
|
||||
mActivity.refreshAppLabel();
|
||||
|
||||
assertThat(TextUtils.isEmpty(mActivity.mApp)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshAppLabel_hasPackageName_shouldHasAppLabel() {
|
||||
ShadowUtils.setApplicationLabel(LAUNCHED_PACKAGE, APP_LABEL);
|
||||
when(mWifiPermissionChecker.getLaunchedPackage()).thenReturn(LAUNCHED_PACKAGE);
|
||||
|
||||
mActivity.refreshAppLabel();
|
||||
|
||||
assertThat(mActivity.mApp).isEqualTo(APP_LABEL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ import com.android.settings.network.ims.MockWifiCallingQueryImsState;
|
||||
import com.android.settings.network.ims.WifiCallingQueryImsState;
|
||||
import com.android.settings.testutils.shadow.ShadowFragment;
|
||||
import com.android.settings.widget.SettingsMainSwitchBar;
|
||||
import com.android.settings.widget.SettingsMainSwitchPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -72,6 +73,7 @@ import org.robolectric.util.ReflectionHelpers;
|
||||
public class WifiCallingSettingsForSubTest {
|
||||
private static final int SUB_ID = 2;
|
||||
|
||||
private static final String SWITCH_BAR = "wifi_calling_switch_bar";
|
||||
private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
|
||||
private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
|
||||
private static final String PREFERENCE_NO_OPTIONS_DESC = "no_options_description";
|
||||
@@ -100,6 +102,8 @@ public class WifiCallingSettingsForSubTest {
|
||||
@Mock
|
||||
private View mView;
|
||||
@Mock
|
||||
private SettingsMainSwitchPreference mSwitchBarPreference;
|
||||
@Mock
|
||||
private LinkifyDescriptionPreference mDescriptionView;
|
||||
@Mock
|
||||
private ListWithEntrySummaryPreference mButtonWfcMode;
|
||||
@@ -116,6 +120,7 @@ public class WifiCallingSettingsForSubTest {
|
||||
doReturn(mContext.getTheme()).when(mActivity).getTheme();
|
||||
|
||||
mFragment = spy(new TestFragment());
|
||||
mFragment.setSwitchBar(mSwitchBarPreference);
|
||||
doReturn(mActivity).when(mFragment).getActivity();
|
||||
doReturn(mContext).when(mFragment).getContext();
|
||||
doReturn(mock(Intent.class)).when(mActivity).getIntent();
|
||||
@@ -125,10 +130,6 @@ public class WifiCallingSettingsForSubTest {
|
||||
final Bundle bundle = new Bundle();
|
||||
when(mFragment.getArguments()).thenReturn(bundle);
|
||||
doNothing().when(mFragment).addPreferencesFromResource(anyInt());
|
||||
doReturn(mock(ListWithEntrySummaryPreference.class)).when(mFragment).findPreference(any());
|
||||
doReturn(mButtonWfcMode).when(mFragment).findPreference(BUTTON_WFC_MODE);
|
||||
doReturn(mButtonWfcRoamingMode).when(mFragment).findPreference(BUTTON_WFC_ROAMING_MODE);
|
||||
doReturn(mDescriptionView).when(mFragment).findPreference(PREFERENCE_NO_OPTIONS_DESC);
|
||||
doNothing().when(mFragment).finish();
|
||||
doReturn(mView).when(mFragment).getView();
|
||||
|
||||
@@ -344,6 +345,29 @@ public class WifiCallingSettingsForSubTest {
|
||||
}
|
||||
|
||||
protected class TestFragment extends WifiCallingSettingsForSub {
|
||||
private SettingsMainSwitchPreference mSwitchPref;
|
||||
|
||||
protected void setSwitchBar(SettingsMainSwitchPreference switchPref) {
|
||||
mSwitchPref = switchPref;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Preference> T findPreference(CharSequence key) {
|
||||
if (SWITCH_BAR.equals(key)) {
|
||||
return (T) mSwitchPref;
|
||||
}
|
||||
if (BUTTON_WFC_MODE.equals(key)) {
|
||||
return (T) mButtonWfcMode;
|
||||
}
|
||||
if (BUTTON_WFC_ROAMING_MODE.equals(key)) {
|
||||
return (T) mButtonWfcRoamingMode;
|
||||
}
|
||||
if (PREFERENCE_NO_OPTIONS_DESC.equals(key)) {
|
||||
return (T) mDescriptionView;
|
||||
}
|
||||
return (T) mock(ListWithEntrySummaryPreference.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getSystemService(final String name) {
|
||||
switch (name) {
|
||||
|
||||
@@ -83,8 +83,45 @@ public class WifiTetherSwitchBarControllerTest {
|
||||
mController.mDataSaverBackend = mDataSaverBackend;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startTether_wifiApIsActivated_doNothing() {
|
||||
when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_ENABLED);
|
||||
|
||||
mController.startTether();
|
||||
|
||||
verify(mConnectivityManager, never()).startTethering(anyInt(), anyBoolean(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startTether_wifiApNotActivated_startTethering() {
|
||||
when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_DISABLED);
|
||||
|
||||
mController.startTether();
|
||||
|
||||
verify(mConnectivityManager).startTethering(anyInt(), anyBoolean(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stopTether_wifiApIsActivated_stopTethering() {
|
||||
when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_ENABLED);
|
||||
|
||||
mController.stopTether();
|
||||
|
||||
verify(mConnectivityManager).stopTethering(anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stopTether_wifiApNotActivated_doNothing() {
|
||||
when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_DISABLED);
|
||||
|
||||
mController.stopTether();
|
||||
|
||||
verify(mConnectivityManager, never()).stopTethering(anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startTether_fail_resetSwitchBar() {
|
||||
when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_DISABLED);
|
||||
when(mDataSaverBackend.isDataSaverEnabled()).thenReturn(false);
|
||||
|
||||
mController.startTether();
|
||||
@@ -130,6 +167,7 @@ public class WifiTetherSwitchBarControllerTest {
|
||||
|
||||
@Test
|
||||
public void onSwitchChanged_isNotChecked_stopTethering() {
|
||||
when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_ENABLED);
|
||||
when(mSwitch.isChecked()).thenReturn(false);
|
||||
|
||||
mController.onSwitchChanged(mSwitch, mSwitch.isChecked());
|
||||
|
||||
@@ -44,54 +44,79 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class PrivacyDashboardActivityTest {
|
||||
|
||||
private static final String DEFAULT_FRAGMENT_CLASSNAME = "DefaultFragmentClassname";
|
||||
|
||||
@Mock
|
||||
private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
|
||||
private Settings.PrivacyDashboardActivity mActivity;
|
||||
private static final String ACTION_PRIVACY_ADVANCED_SETTINGS =
|
||||
"android.settings.PRIVACY_ADVANCED_SETTINGS";
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_whenSafetyCenterEnabled_redirectsToSafetyCenter() throws Exception {
|
||||
startActivityUsingIntent(android.provider.Settings.ACTION_PRIVACY_SETTINGS);
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true);
|
||||
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
mActivity.handleSafetyCenterRedirection();
|
||||
verify(mActivity).startActivity(intentCaptor.capture());
|
||||
assertThat(intentCaptor.getValue().getAction()).isEqualTo(Intent.ACTION_SAFETY_CENTER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreateWithAdvancedIntent_whenSafetyCenterEnabled_doesntRedirectToSafetyCenter()
|
||||
throws Exception {
|
||||
startActivityUsingIntent(ACTION_PRIVACY_ADVANCED_SETTINGS);
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true);
|
||||
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
mActivity.handleSafetyCenterRedirection();
|
||||
verify(mActivity, times(0)).startActivity(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_whenSafetyCenterDisabled_doesntRedirectToSafetyCenter() throws Exception {
|
||||
startActivityUsingIntent(android.provider.Settings.ACTION_PRIVACY_SETTINGS);
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false);
|
||||
mActivity.handleSafetyCenterRedirection();
|
||||
verify(mActivity, times(0)).startActivity(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreateWithAdvancedIntent_whenSafetyCenterDisabled_doesntRedirectToSafetyCenter()
|
||||
throws Exception {
|
||||
startActivityUsingIntent(ACTION_PRIVACY_ADVANCED_SETTINGS);
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true);
|
||||
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
mActivity.handleSafetyCenterRedirection();
|
||||
verify(mActivity, times(0)).startActivity(any());
|
||||
}
|
||||
|
||||
private void startActivityUsingIntent(String intentAction) throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper;
|
||||
final Intent intent = new Intent();
|
||||
intent.setAction(android.provider.Settings.ACTION_PRIVACY_SETTINGS);
|
||||
intent.setAction(intentAction);
|
||||
intent.setClass(InstrumentationRegistry.getInstrumentation().getTargetContext(),
|
||||
Settings.PrivacyDashboardActivity.class);
|
||||
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, DEFAULT_FRAGMENT_CLASSNAME);
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
|
||||
try {
|
||||
mActivity =
|
||||
spy((Settings.PrivacyDashboardActivity) InstrumentationRegistry
|
||||
Settings.PrivacyDashboardActivity activity =
|
||||
(Settings.PrivacyDashboardActivity) InstrumentationRegistry
|
||||
.getInstrumentation().newActivity(
|
||||
getClass().getClassLoader(),
|
||||
Settings.PrivacyDashboardActivity.class.getName(),
|
||||
intent));
|
||||
intent);
|
||||
activity.setIntent(intent);
|
||||
mActivity = spy(activity);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e); // nothing to do
|
||||
}
|
||||
});
|
||||
doNothing().when(mActivity).startActivity(any(Intent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_whenSafetyCenterEnabled_redirectsToSafetyCenter() {
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true);
|
||||
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
|
||||
mActivity.handleSafetyCenterRedirection();
|
||||
|
||||
verify(mActivity).startActivity(intentCaptor.capture());
|
||||
assertThat(intentCaptor.getValue().getAction()).isEqualTo(Intent.ACTION_SAFETY_CENTER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_whenSafetyCenterDisabled_doesntRedirectToSafetyCenter() {
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false);
|
||||
mActivity.handleSafetyCenterRedirection();
|
||||
|
||||
verify(mActivity, times(0)).startActivity(any());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,13 +54,13 @@ import java.util.List;
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SafetySourceBroadcastReceiverTest {
|
||||
|
||||
private static final String REFRESH_BROADCAST_ID = "REFRESH_BROADCAST_ID";
|
||||
|
||||
private Context mApplicationContext;
|
||||
|
||||
@Mock
|
||||
private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
|
||||
@Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
|
||||
|
||||
@Mock
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
@Mock private LockPatternUtils mLockPatternUtils;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -77,17 +77,6 @@ public class SafetySourceBroadcastReceiverTest {
|
||||
SafetyCenterManagerWrapper.sInstance = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoIntentAction_doesNotSetData() {
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||
Intent intent = new Intent().putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, new String[]{});
|
||||
|
||||
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||
|
||||
verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
|
||||
any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onReceive_onRefresh_whenSafetyCenterIsDisabled_doesNotSetData() {
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false);
|
||||
@@ -96,23 +85,43 @@ public class SafetySourceBroadcastReceiverTest {
|
||||
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
|
||||
.putExtra(
|
||||
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
|
||||
new String[]{ LockScreenSafetySource.SAFETY_SOURCE_ID });
|
||||
new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
|
||||
.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
|
||||
|
||||
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||
|
||||
verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
|
||||
any(), any(), any(), any());
|
||||
verify(mSafetyCenterManagerWrapper, never())
|
||||
.setSafetySourceData(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoIntentAction_doesNotSetData() {
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||
Intent intent =
|
||||
new Intent()
|
||||
.putExtra(
|
||||
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
|
||||
new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
|
||||
.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
|
||||
|
||||
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||
|
||||
verify(mSafetyCenterManagerWrapper, never())
|
||||
.setSafetySourceData(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNullSourceIds_doesNotSetData() {
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||
Intent intent = new Intent().setAction(ACTION_REFRESH_SAFETY_SOURCES);
|
||||
Intent intent =
|
||||
new Intent()
|
||||
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
|
||||
.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
|
||||
|
||||
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||
|
||||
verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
|
||||
any(), any(), any(), any());
|
||||
verify(mSafetyCenterManagerWrapper, never())
|
||||
.setSafetySourceData(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,12 +130,29 @@ public class SafetySourceBroadcastReceiverTest {
|
||||
Intent intent =
|
||||
new Intent()
|
||||
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
|
||||
.putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, new String[]{});
|
||||
.putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, new String[] {})
|
||||
.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
|
||||
|
||||
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||
|
||||
verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
|
||||
any(), any(), any(), any());
|
||||
verify(mSafetyCenterManagerWrapper, never())
|
||||
.setSafetySourceData(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoBroadcastId_doesNotSetData() {
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||
Intent intent =
|
||||
new Intent()
|
||||
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
|
||||
.putExtra(
|
||||
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
|
||||
new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID});
|
||||
|
||||
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||
|
||||
verify(mSafetyCenterManagerWrapper, never())
|
||||
.setSafetySourceData(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -137,38 +163,19 @@ public class SafetySourceBroadcastReceiverTest {
|
||||
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
|
||||
.putExtra(
|
||||
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
|
||||
new String[]{ LockScreenSafetySource.SAFETY_SOURCE_ID });
|
||||
new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
|
||||
.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
|
||||
|
||||
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||
ArgumentCaptor<SafetyEvent> captor = ArgumentCaptor.forClass(SafetyEvent.class);
|
||||
verify(mSafetyCenterManagerWrapper, times(1))
|
||||
.setSafetySourceData(any(), any(), any(), captor.capture());
|
||||
|
||||
assertThat(captor.getValue()).isEqualTo(
|
||||
new SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onReceive_onRefreshWithBroadcastId_setsRefreshEventWithBroadcastId() {
|
||||
final String refreshBroadcastId = "REFRESH_BROADCAST_ID";
|
||||
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||
Intent intent =
|
||||
new Intent()
|
||||
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
|
||||
.putExtra(
|
||||
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
|
||||
new String[]{ LockScreenSafetySource.SAFETY_SOURCE_ID })
|
||||
.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, refreshBroadcastId);
|
||||
|
||||
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||
ArgumentCaptor<SafetyEvent> captor = ArgumentCaptor.forClass(SafetyEvent.class);
|
||||
verify(mSafetyCenterManagerWrapper, times(1))
|
||||
.setSafetySourceData(any(), any(), any(), captor.capture());
|
||||
|
||||
assertThat(captor.getValue().getRefreshBroadcastId()).isEqualTo(refreshBroadcastId);
|
||||
assertThat(captor.getValue()).isEqualTo(
|
||||
new SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
|
||||
.setRefreshBroadcastId(refreshBroadcastId).build());
|
||||
assertThat(captor.getValue())
|
||||
.isEqualTo(
|
||||
new SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
|
||||
.setRefreshBroadcastId(REFRESH_BROADCAST_ID)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -179,7 +186,8 @@ public class SafetySourceBroadcastReceiverTest {
|
||||
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
|
||||
.putExtra(
|
||||
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
|
||||
new String[]{ LockScreenSafetySource.SAFETY_SOURCE_ID });
|
||||
new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
|
||||
.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
|
||||
|
||||
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||
@@ -197,7 +205,8 @@ public class SafetySourceBroadcastReceiverTest {
|
||||
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
|
||||
.putExtra(
|
||||
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
|
||||
new String[]{ BiometricsSafetySource.SAFETY_SOURCE_ID });
|
||||
new String[] {BiometricsSafetySource.SAFETY_SOURCE_ID})
|
||||
.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
|
||||
|
||||
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||
|
||||
Reference in New Issue
Block a user