diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ae87edb5628..71c07a05148 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -4474,6 +4474,16 @@
+
+
+
+
+
+
+
diff --git a/res/drawable/ic_qr_code_scanner.xml b/res/drawable/ic_qr_code_scanner.xml
new file mode 100644
index 00000000000..f6f63c5ae7f
--- /dev/null
+++ b/res/drawable/ic_qr_code_scanner.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/qrcode_scan_mode_activity.xml b/res/layout/qrcode_scan_mode_activity.xml
new file mode 100644
index 00000000000..f0a182b3d67
--- /dev/null
+++ b/res/layout/qrcode_scan_mode_activity.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
diff --git a/res/layout/qrcode_scanner_fragment.xml b/res/layout/qrcode_scanner_fragment.xml
new file mode 100644
index 00000000000..2c543f23abf
--- /dev/null
+++ b/res/layout/qrcode_scanner_fragment.xml
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/wifi_calling_settings_preferences.xml b/res/layout/wifi_calling_settings_preferences.xml
index 9a6cbe6698b..bad90ad0434 100644
--- a/res/layout/wifi_calling_settings_preferences.xml
+++ b/res/layout/wifi_calling_settings_preferences.xml
@@ -21,12 +21,6 @@
android:layout_height="match_parent"
android:orientation="vertical">
-
-
24dp
8dp
+
+
+ 40dp
+ 30dp
+ 27dp
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9ab0cc2d301..1d01f14bb8e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -518,6 +518,9 @@
Language may differ from languages available in the app. Some apps may not support this setting.
+
+ Only apps that support language selection are shown here.
+
- Remove selected language?
@@ -1297,7 +1300,10 @@
Encryption, credentials, and more
security, more security settings, more settings, advanced security settings
-
+
+ More privacy settings
+
+ Autofill, activity controls, and more
You can add up to %d fingerprints
@@ -8973,6 +8979,9 @@
Work notifications
+
+ Work profile
+
Adaptive notifications
@@ -13649,7 +13658,9 @@
mobile data
- 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. Change
+ 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.
+
+ Change
@@ -14163,4 +14174,11 @@
Can\u2019t connect. Try again.
Wrong password
+
+
+
+ To start listening, center the QR code below
+
+ QR code isn\u0027t a valid format
+
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 7a879931a00..f147ce98903 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -962,4 +962,11 @@
- 0dp
- false
+
+
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index f6c0af662aa..b44a93db62f 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -46,6 +46,11 @@
android:key="action_buttons"
settings:allowDividerBelow="true"/>
+
+
+ android:key="usage_amount"
+ android:title="@string/summary_placeholder">
diff --git a/res/xml/privacy_advanced_settings.xml b/res/xml/privacy_advanced_settings.xml
new file mode 100644
index 00000000000..9f465d45566
--- /dev/null
+++ b/res/xml/privacy_advanced_settings.xml
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/xml/wifi_calling_settings.xml b/res/xml/wifi_calling_settings.xml
index 902ff1af2fa..c45f702ca13 100644
--- a/res/xml/wifi_calling_settings.xml
+++ b/res/xml/wifi_calling_settings.xml
@@ -19,6 +19,10 @@
android:key="wifi_calling_settings"
android:title="@string/wifi_calling_settings_title">
+
+
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;
diff --git a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
index 930fbe4c9c7..6ead3907a28 100644
--- a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
@@ -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);
+ }
}
diff --git a/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java
index f9a1113c054..0af8aa17524 100644
--- a/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java
@@ -49,6 +49,8 @@ public class ToggleScreenReaderPreferenceFragmentForSetupWizard
if (mTopIntroPreference != null) {
mTopIntroPreference.setVisible(false);
}
+
+ mToggleServiceSwitchPreference.applyPartnerCustomizationPaddingStyle();
}
@Override
diff --git a/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
index ef5b029a9d0..b91057865e4 100644
--- a/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
+++ b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
@@ -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);
}
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index a6abd10374f..24328a277e4 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -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;
diff --git a/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java b/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java
index 17b604c58ff..733a4a96e49 100644
--- a/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java
@@ -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 =
+ 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();
+ }
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index 6d443ee4044..fdf0f383dab 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -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
diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
index 582a26c182c..51ef8e2a649 100644
--- a/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
+++ b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
@@ -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);
}
diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java
index cd75951a482..04d3ec4cc1f 100644
--- a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java
+++ b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java
@@ -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);
+ }
}
diff --git a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
index 07a31560d24..13388b3ecd3 100644
--- a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
@@ -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 receiveStateList =
+ mLeBroadcastAssistant.getAllSources(mCachedDevice.getDevice());
+ if (!receiveStateList.isEmpty()) {
+ updateListCategoryFromBroadcastReceiveState(receiveStateList.get(0));
+ }
+ }
+
public int getSourceId() {
return mSourceId;
}
diff --git a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java
index 1527f2145fe..1282abda18e 100644
--- a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java
+++ b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java
@@ -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);
diff --git a/src/com/android/settings/bluetooth/QrCodeScanModeActivity.java b/src/com/android/settings/bluetooth/QrCodeScanModeActivity.java
new file mode 100644
index 00000000000..5c5b61f091c
--- /dev/null
+++ b/src/com/android/settings/bluetooth/QrCodeScanModeActivity.java
@@ -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();
+ }
+}
+
diff --git a/src/com/android/settings/bluetooth/QrCodeScanModeBaseActivity.java b/src/com/android/settings/bluetooth/QrCodeScanModeBaseActivity.java
new file mode 100644
index 00000000000..af8a6e9d97f
--- /dev/null
+++ b/src/com/android/settings/bluetooth/QrCodeScanModeBaseActivity.java
@@ -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());
+ }
+ }
+}
diff --git a/src/com/android/settings/bluetooth/QrCodeScanModeController.java b/src/com/android/settings/bluetooth/QrCodeScanModeController.java
new file mode 100644
index 00000000000..4504b4b71aa
--- /dev/null
+++ b/src/com/android/settings/bluetooth/QrCodeScanModeController.java
@@ -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);
+ }
+}
diff --git a/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java b/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
new file mode 100644
index 00000000000..dcf89ca9d0e
--- /dev/null
+++ b/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
@@ -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;
+ }
+}
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
index 57988c5d0dc..1473dd1c04c 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
@@ -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.
}
diff --git a/src/com/android/settings/datausage/CycleAdapter.java b/src/com/android/settings/datausage/CycleAdapter.java
index b41b6aad91b..2af40120864 100644
--- a/src/com/android/settings/datausage/CycleAdapter.java
+++ b/src/com/android/settings/datausage/CycleAdapter.java
@@ -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 {
@@ -67,7 +66,7 @@ public class CycleAdapter extends SettingsSpinnerAdapter
* 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
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;
}
/**
diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java
index 4a44a1674e0..9d8fbb14162 100644
--- a/src/com/android/settings/datausage/DataUsageList.java
+++ b/src/com/android/settings/datausage/DataUsageList.java
@@ -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 mCycleData;
+ // Caches the cycles for startAppDataUsage usage, which need be cleared when resumed.
private ArrayList 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
diff --git a/src/com/android/settings/datausage/SpinnerPreference.java b/src/com/android/settings/datausage/SpinnerPreference.java
index c4b7a4e18da..c6b5f9f8ecc 100644
--- a/src/com/android/settings/datausage/SpinnerPreference.java
+++ b/src/com/android/settings/datausage/SpinnerPreference.java
@@ -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);
+ }
+ }
+ };
}
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 77d4072956d..a4809c929fd 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -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.
}
diff --git a/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java b/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java
index 42a3a16da3e..4b87e422c1b 100644
--- a/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java
+++ b/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java
@@ -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();
}
}
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index 025168778bb..86b123be49b 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -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() {
diff --git a/src/com/android/settings/localepicker/AppLocalePickerActivity.java b/src/com/android/settings/localepicker/AppLocalePickerActivity.java
index 791a4e8e785..377a076ec63 100644
--- a/src/com/android/settings/localepicker/AppLocalePickerActivity.java
+++ b/src/com/android/settings/localepicker/AppLocalePickerActivity.java
@@ -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");
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index de4d127a84e..ec17dd371b1 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -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);
}
diff --git a/src/com/android/settings/privacy/PrivacyDashboardFragment.java b/src/com/android/settings/privacy/PrivacyDashboardFragment.java
index df59bd5f119..75ed225e3a6 100644
--- a/src/com/android/settings/privacy/PrivacyDashboardFragment.java
+++ b/src/com/android/settings/privacy/PrivacyDashboardFragment.java
@@ -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 buildPreferenceControllers(
Context context, Lifecycle lifecycle) {
final List 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 getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = getPreferenceScreenResId(context);
+ return Arrays.asList(sir);
+ }
@Override
public List createPreferenceControllers(
Context context) {
return buildPreferenceControllers(context, null);
}
-
- @Override
- protected boolean isPageSearchEnabled(Context context) {
- return !SafetyCenterManagerWrapper.get().isEnabled(context);
- }
};
}
diff --git a/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java b/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java
index 3ea23f3a897..0b556e74a37 100644
--- a/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java
+++ b/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java
@@ -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();
diff --git a/src/com/android/settings/widget/SettingsMainSwitchPreference.java b/src/com/android/settings/widget/SettingsMainSwitchPreference.java
index b7c69017404..92649113d82 100644
--- a/src/com/android/settings/widget/SettingsMainSwitchPreference.java
+++ b/src/com/android/settings/widget/SettingsMainSwitchPreference.java
@@ -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 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);
diff --git a/src/com/android/settings/wifi/WifiScanModeActivity.java b/src/com/android/settings/wifi/WifiScanModeActivity.java
index 9d502810d5a..d37213522aa 100644
--- a/src/com/android/settings/wifi/WifiScanModeActivity.java
+++ b/src/com/android/settings/wifi/WifiScanModeActivity.java
@@ -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);
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettings.java b/src/com/android/settings/wifi/calling/WifiCallingSettings.java
index 25508f73caf..b4951bf5c59 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettings.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettings.java
@@ -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 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 subInfoList) {
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
index 749af3ecbfc..492a2284edb 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
@@ -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);
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
index 5d28bccfa01..10ee24191e4 100644
--- a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
+++ b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
@@ -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());
diff --git a/src/com/android/settings/wifi/tether/TetherService.java b/src/com/android/settings/wifi/tether/TetherService.java
index 8a557ba0c3e..b0e8fd8338a 100644
--- a/src/com/android/settings/wifi/tether/TetherService.java
+++ b/src/com/android/settings/wifi/tether/TetherService.java
@@ -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);
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
index 580bc39937e..e88931cceff 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
@@ -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) {
diff --git a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
index 0418906aeaa..bddaed5aa9a 100644
--- a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
@@ -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
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java
index 9ab1d875183..3d40bfca597 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java
@@ -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 =
+ "" + SETTINGS_URI
+ + "";
+ 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);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
index e4f5b1fc9e9..a13cf6c7c8f 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
@@ -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;
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiScanModeActivityTest.java b/tests/robotests/src/com/android/settings/wifi/WifiScanModeActivityTest.java
index 3e6ba00eff5..1e3afdbf32f 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiScanModeActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiScanModeActivityTest.java
@@ -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);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
index 74bdddabbe5..e2c5ca33b4c 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
@@ -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 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) {
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
index 7c17c5fa9bd..ca0247fdd05 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
@@ -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());
diff --git a/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java b/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java
index 1cfee0f377a..ae42c849837 100644
--- a/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java
+++ b/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java
@@ -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 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 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 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 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());
- }
}
diff --git a/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java b/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java
index 8004d600e9e..3ad1874995b 100644
--- a/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java
+++ b/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java
@@ -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 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 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 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 captor = ArgumentCaptor.forClass(String.class);