diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 1aac149ecc9..8d410709d11 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -4064,6 +4064,20 @@
android:value="true"/>
+
+
+
+
+
+
+
+
+
+
diff --git a/src/com/android/settings/SettingsLicenseActivity.java b/src/com/android/settings/SettingsLicenseActivity.java
index 57b1f5c6cbb..598c97394c1 100644
--- a/src/com/android/settings/SettingsLicenseActivity.java
+++ b/src/com/android/settings/SettingsLicenseActivity.java
@@ -98,7 +98,9 @@ public class SettingsLicenseActivity extends FragmentActivity implements
intent.setDataAndType(uri, "text/html");
intent.putExtra(Intent.EXTRA_TITLE, getString(R.string.settings_license_activity_title));
if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.addFlags(
+ Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
}
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setPackage("com.android.htmlviewer");
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index d020f3386ac..00af9737b39 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -46,6 +46,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
+import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
@@ -133,6 +134,8 @@ import com.android.settings.notification.app.AppNotificationSettings;
import com.android.settings.widget.LoadingViewController;
import com.android.settings.wifi.AppStateChangeWifiStateBridge;
import com.android.settings.wifi.ChangeWifiStateDetails;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.applications.AppIconCacheManager;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
@@ -431,7 +434,7 @@ public class ManageApplications extends InstrumentedFragment
mResetAppsHelper.onRestoreInstanceState(savedInstanceState);
mAppBarLayout = getActivity().findViewById(R.id.app_bar);
- disableToolBarScrollableBehavior();
+ autoSetCollapsingToolbarLayoutScrolling();
return mRootView;
}
@@ -798,7 +801,18 @@ public class ManageApplications extends InstrumentedFragment
mShowSystem = !mShowSystem;
mApplications.rebuild();
} else if (i == R.id.reset_app_preferences) {
- mResetAppsHelper.buildResetDialog();
+ final boolean appsControlDisallowedBySystem =
+ RestrictedLockUtilsInternal.hasBaseUserRestriction(getActivity(),
+ UserManager.DISALLOW_APPS_CONTROL, UserHandle.myUserId());
+ final RestrictedLockUtils.EnforcedAdmin appsControlDisallowedAdmin =
+ RestrictedLockUtilsInternal.checkIfRestrictionEnforced(getActivity(),
+ UserManager.DISALLOW_APPS_CONTROL, UserHandle.myUserId());
+ if (appsControlDisallowedAdmin != null && !appsControlDisallowedBySystem) {
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
+ getActivity(), appsControlDisallowedAdmin);
+ } else {
+ mResetAppsHelper.buildResetDialog();
+ }
return true;
} else if (i == R.id.advanced) {
if (mListType == LIST_TYPE_NOTIFICATION) {
@@ -893,7 +907,7 @@ public class ManageApplications extends InstrumentedFragment
}
}
- private void disableToolBarScrollableBehavior() {
+ private void autoSetCollapsingToolbarLayoutScrolling() {
final CoordinatorLayout.LayoutParams params =
(CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
final AppBarLayout.Behavior behavior = new AppBarLayout.Behavior();
@@ -901,7 +915,8 @@ public class ManageApplications extends InstrumentedFragment
new AppBarLayout.Behavior.DragCallback() {
@Override
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
- return false;
+ return appBarLayout.getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_LANDSCAPE;
}
});
params.setBehavior(behavior);
diff --git a/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java b/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java
index b2636a63d30..dd06b679910 100644
--- a/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java
+++ b/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java
@@ -41,15 +41,18 @@ import com.android.settingslib.media.MediaOutputConstants;
* nearby broadcast sources.
*/
public class BluetoothBroadcastDialog extends InstrumentedDialogFragment {
+
public static final String KEY_APP_LABEL = "app_label";
public static final String KEY_DEVICE_ADDRESS =
BluetoothFindBroadcastsFragment.KEY_DEVICE_ADDRESS;
+ public static final String KEY_MEDIA_STREAMING = "media_streaming";
private static final String TAG = "BTBroadcastsDialog";
private static final CharSequence UNKNOWN_APP_LABEL = "unknown";
private Context mContext;
private CharSequence mCurrentAppLabel = UNKNOWN_APP_LABEL;
private String mDeviceAddress;
+ private boolean mIsMediaStreaming;
private LocalBluetoothManager mLocalBluetoothManager;
private AlertDialog mAlertDialog;
@@ -59,6 +62,7 @@ public class BluetoothBroadcastDialog extends InstrumentedDialogFragment {
mContext = getActivity();
mCurrentAppLabel = getActivity().getIntent().getCharSequenceExtra(KEY_APP_LABEL);
mDeviceAddress = getActivity().getIntent().getStringExtra(KEY_DEVICE_ADDRESS);
+ mIsMediaStreaming = getActivity().getIntent().getBooleanExtra(KEY_MEDIA_STREAMING, false);
mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
setShowsDialog(true);
}
@@ -75,16 +79,21 @@ public class BluetoothBroadcastDialog extends InstrumentedDialogFragment {
mContext.getString(R.string.bluetooth_broadcast_dialog_broadcast_message));
Button broadcastBtn = layout.findViewById(com.android.settingslib.R.id.positive_btn);
- if (TextUtils.isEmpty(mCurrentAppLabel)) {
- broadcastBtn.setText(mContext.getString(R.string.bluetooth_broadcast_dialog_title));
- } else {
- broadcastBtn.setText(mContext.getString(
+ if (isBroadcastSupported() && mIsMediaStreaming) {
+ broadcastBtn.setVisibility(View.VISIBLE);
+ if (TextUtils.isEmpty(mCurrentAppLabel)) {
+ broadcastBtn.setText(mContext.getString(R.string.bluetooth_broadcast_dialog_title));
+ } else {
+ broadcastBtn.setText(mContext.getString(
R.string.bluetooth_broadcast_dialog_broadcast_app,
String.valueOf(mCurrentAppLabel)));
+ }
+ broadcastBtn.setOnClickListener((view) -> {
+ launchMediaOutputBroadcastDialog();
+ });
+ } else {
+ broadcastBtn.setVisibility(View.GONE);
}
- broadcastBtn.setOnClickListener((view) -> {
- launchMediaOutputBroadcastDialog();
- });
Button findBroadcastBtn = layout.findViewById(com.android.settingslib.R.id.negative_btn);
findBroadcastBtn.setText(mContext.getString(R.string.bluetooth_find_broadcast));
@@ -169,4 +178,10 @@ public class BluetoothBroadcastDialog extends InstrumentedDialogFragment {
.setPackage(MediaOutputConstants.SETTINGS_PACKAGE_NAME)
.setAction(MediaOutputConstants.ACTION_CLOSE_PANEL));
}
+
+ boolean isBroadcastSupported() {
+ LocalBluetoothLeBroadcast broadcast =
+ mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
+ return broadcast != null;
+ }
}
diff --git a/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java b/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
index 7f58c0647b2..0253aa6b748 100644
--- a/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
+++ b/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
@@ -36,16 +36,15 @@ import android.view.ViewOutlineProvider;
import android.view.accessibility.AccessibilityEvent;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+
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 {
diff --git a/src/com/android/settings/core/SettingsBaseActivity.java b/src/com/android/settings/core/SettingsBaseActivity.java
index 5f15093259f..b4380ab4adc 100644
--- a/src/com/android/settings/core/SettingsBaseActivity.java
+++ b/src/com/android/settings/core/SettingsBaseActivity.java
@@ -22,6 +22,7 @@ import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.text.LineBreakConfig;
import android.os.Bundle;
@@ -117,7 +118,7 @@ public class SettingsBaseActivity extends FragmentActivity implements CategoryHa
LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE)
.build()));
}
- disableCollapsingToolbarLayoutScrollingBehavior();
+ autoSetCollapsingToolbarLayoutScrolling();
} else {
super.setContentView(R.layout.settings_base_layout);
}
@@ -252,7 +253,7 @@ public class SettingsBaseActivity extends FragmentActivity implements CategoryHa
return false;
}
- private void disableCollapsingToolbarLayoutScrollingBehavior() {
+ private void autoSetCollapsingToolbarLayoutScrolling() {
if (mAppBarLayout == null) {
return;
}
@@ -263,7 +264,9 @@ public class SettingsBaseActivity extends FragmentActivity implements CategoryHa
new AppBarLayout.Behavior.DragCallback() {
@Override
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
- return false;
+ // Header can be scrolling while device in landscape mode.
+ return appBarLayout.getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_LANDSCAPE;
}
});
params.setBehavior(behavior);
diff --git a/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java b/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java
index 6ce9f6f9ae8..f801cb9ec77 100644
--- a/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java
+++ b/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java
@@ -16,6 +16,7 @@
package com.android.settings.datetime.timezone;
+import android.content.res.Configuration;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -97,7 +98,7 @@ public abstract class BaseTimeZonePicker extends InstrumentedFragment
LinearLayoutManager.VERTICAL, /* reverseLayout */ false));
mRecyclerView.setAdapter(mAdapter);
mAppBarLayout = getActivity().findViewById(R.id.app_bar);
- disableToolBarScrollableBehavior();
+ autoSetCollapsingToolbarLayoutScrolling();
// Initialize TimeZoneDataLoader only when mRecyclerView is ready to avoid race
// during onDateLoaderReady callback.
@@ -193,7 +194,7 @@ public abstract class BaseTimeZonePicker extends InstrumentedFragment
void onListItemClick(T item);
}
- private void disableToolBarScrollableBehavior() {
+ private void autoSetCollapsingToolbarLayoutScrolling() {
CoordinatorLayout.LayoutParams params =
(CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
AppBarLayout.Behavior behavior = new AppBarLayout.Behavior();
@@ -201,7 +202,8 @@ public abstract class BaseTimeZonePicker extends InstrumentedFragment
new AppBarLayout.Behavior.DragCallback() {
@Override
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
- return false;
+ return appBarLayout.getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_LANDSCAPE;
}
});
params.setBehavior(behavior);
diff --git a/src/com/android/settings/development/qstile/DevelopmentTiles.java b/src/com/android/settings/development/qstile/DevelopmentTiles.java
index 0483aea861f..343ed24e0a1 100644
--- a/src/com/android/settings/development/qstile/DevelopmentTiles.java
+++ b/src/com/android/settings/development/qstile/DevelopmentTiles.java
@@ -476,4 +476,77 @@ public abstract class DevelopmentTiles extends TileService {
Settings.System.SHOW_TOUCHES, isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
}
}
+
+ /**
+ * Tile to enable desktop mode
+ */
+ public static class DesktopMode extends DevelopmentTiles {
+
+ private static final int SETTING_VALUE_ON = 1;
+ private static final int SETTING_VALUE_OFF = 0;
+ private Context mContext;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mContext = getApplicationContext();
+ }
+
+ @Override
+ protected boolean isEnabled() {
+ return Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.DESKTOP_MODE, SETTING_VALUE_OFF) == SETTING_VALUE_ON;
+ }
+
+ private boolean isDesktopModeFlagEnabled() {
+ return SystemProperties.getBoolean("persist.wm.debug.desktop_mode", false);
+ }
+
+ private boolean isFreeformFlagEnabled() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, SETTING_VALUE_OFF)
+ == SETTING_VALUE_ON;
+ }
+
+ private boolean isCaptionOnShellEnabled() {
+ return SystemProperties.getBoolean("persist.wm.debug.caption_on_shell", false);
+ }
+
+ @Override
+ protected void setIsEnabled(boolean isEnabled) {
+ if (isEnabled) {
+ // Check that all required features are enabled
+ if (!isDesktopModeFlagEnabled()) {
+ closeShade();
+ showMessage(
+ "Enable 'Desktop Windowing Proto 1' from the Flag Flipper app");
+ return;
+ }
+ if (!isCaptionOnShellEnabled()) {
+ closeShade();
+ showMessage("Enable 'Captions in Shell' from the Flag Flipper app");
+ return;
+ }
+ if (!isFreeformFlagEnabled()) {
+ closeShade();
+ showMessage(
+ "Enable freeform windows from developer settings");
+ return;
+ }
+ }
+
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.DESKTOP_MODE,
+ isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
+ closeShade();
+ }
+
+ private void closeShade() {
+ sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ }
+
+ private void showMessage(String message) {
+ Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
+ }
+ }
}
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index f888ea7c8e0..19222612f3a 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -107,7 +107,6 @@ public class ConfigureNotificationSettings extends DashboardFragment implements
mNotificationAssistantPreferenceController =
use(NotificationAssistantPreferenceController.class);
mNotificationAssistantPreferenceController.setFragment(this);
- mNotificationAssistantPreferenceController.setBackend(new NotificationBackend());
}
private static List buildPreferenceControllers(Context context,
diff --git a/src/com/android/settings/notification/MediaVolumePreferenceController.java b/src/com/android/settings/notification/MediaVolumePreferenceController.java
index 05c8e033930..2466b7747a3 100644
--- a/src/com/android/settings/notification/MediaVolumePreferenceController.java
+++ b/src/com/android/settings/notification/MediaVolumePreferenceController.java
@@ -29,6 +29,7 @@ import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.bluetooth.BluetoothBroadcastDialog;
@@ -90,13 +91,16 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
return R.drawable.ic_media_stream_off;
}
- private boolean isSupportEndItem() {
- return getWorker() != null
- && getWorker().getActiveLocalMediaController() != null
- && isConnectedBLEDevice();
+ @VisibleForTesting
+ boolean isSupportEndItem() {
+ return isConnectedBLEDevice();
}
private boolean isConnectedBLEDevice() {
+ if (getWorker() == null) {
+ Log.d(TAG, "The Worker is null");
+ return false;
+ }
mMediaDevice = getWorker().getCurrentConnectedMediaDevice();
if (mMediaDevice != null) {
return mMediaDevice.isBLEDevice();
@@ -133,6 +137,8 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
Utils.getApplicationLabel(mContext, getWorker().getPackageName()));
intent.putExtra(BluetoothBroadcastDialog.KEY_DEVICE_ADDRESS,
bluetoothDevice.getAddress());
+ intent.putExtra(BluetoothBroadcastDialog.KEY_MEDIA_STREAMING, getWorker() != null
+ && getWorker().getActiveLocalMediaController() != null);
pi = PendingIntent.getActivity(context, 0 /* requestCode */, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
diff --git a/src/com/android/settings/notification/NotificationAssistantPreferenceController.java b/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
index c25a7d55723..e8a66b6ba7f 100644
--- a/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
+++ b/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
@@ -43,6 +43,7 @@ public class NotificationAssistantPreferenceController extends TogglePreferenceC
public NotificationAssistantPreferenceController(Context context) {
super(context, KEY_NAS);
mUserManager = UserManager.get(context);
+ mNotificationBackend = new NotificationBackend();
}
@Override
@@ -100,4 +101,9 @@ public class NotificationAssistantPreferenceController extends TogglePreferenceC
void setBackend(NotificationBackend backend) {
mNotificationBackend = backend;
}
+
+ @Override
+ public boolean isSliceable() {
+ return (mFragment != null && mFragment instanceof ConfigureNotificationSettings);
+ }
}
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index 199d584cc5c..c4a3159e001 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -69,6 +69,7 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.ImeAwareEditText;
import android.widget.TextView;
@@ -214,6 +215,7 @@ public class ChooseLockPassword extends SettingsActivity {
ThemeHelper.trySetDynamicColor(this);
super.onCreate(savedInstanceState);
findViewById(R.id.content_parent).setFitsSystemWindows(false);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
public static class ChooseLockPasswordFragment extends InstrumentedFragment
diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java
index 65582627d9a..c39ef661a0f 100644
--- a/src/com/android/settings/password/ChooseLockPattern.java
+++ b/src/com/android/settings/password/ChooseLockPattern.java
@@ -41,6 +41,7 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
@@ -175,6 +176,7 @@ public class ChooseLockPattern extends SettingsActivity {
ThemeHelper.trySetDynamicColor(this);
super.onCreate(savedInstanceState);
findViewById(R.id.content_parent).setFitsSystemWindows(false);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
@Override
diff --git a/src/com/android/settings/privacy/WorkPolicyInfoPreferenceController.java b/src/com/android/settings/privacy/WorkPolicyInfoPreferenceController.java
index 55ba0646af5..2d1d9e18564 100644
--- a/src/com/android/settings/privacy/WorkPolicyInfoPreferenceController.java
+++ b/src/com/android/settings/privacy/WorkPolicyInfoPreferenceController.java
@@ -24,6 +24,8 @@ import androidx.preference.Preference;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
+
public class WorkPolicyInfoPreferenceController extends BasePreferenceController {
@@ -37,7 +39,12 @@ public class WorkPolicyInfoPreferenceController extends BasePreferenceController
@Override
public int getAvailabilityStatus() {
- return mEnterpriseProvider.hasWorkPolicyInfo() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ // Your Work policy info will be shown in the Safety Center.
+ // No need to show it in the privacy settings.
+ return !SafetyCenterManagerWrapper.get().isEnabled(mContext)
+ && mEnterpriseProvider.hasWorkPolicyInfo()
+ ? AVAILABLE
+ : UNSUPPORTED_ON_DEVICE;
}
@Override
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index c91f16c161d..4c5a4bfe3de 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -19,6 +19,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
import android.app.Activity;
import android.app.AlertDialog;
@@ -49,7 +50,6 @@ import android.os.Handler;
import android.provider.Telephony.CarrierId;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.FeatureFlagUtils;
import android.util.Log;
@@ -690,34 +690,17 @@ public class WifiDetailPreferenceController2 extends AbstractPreferenceControlle
// Checks if the SIM subscription is active.
final List activeSubscriptionInfos = mContext
.getSystemService(SubscriptionManager.class).getActiveSubscriptionInfoList();
- final int defaultDataSubscriptionId = SubscriptionManager.getDefaultDataSubscriptionId();
if (activeSubscriptionInfos != null) {
- CharSequence firstCarrierIdMatchedDisplayName = null;
- for (SubscriptionInfo subscriptionInfo : activeSubscriptionInfos) {
- final CharSequence displayName = SubscriptionUtil.getUniqueSubscriptionDisplayName(
- subscriptionInfo, mContext);
- if (firstCarrierIdMatchedDisplayName == null
- && config.carrierId == subscriptionInfo.getCarrierId()) {
- firstCarrierIdMatchedDisplayName = displayName;
- }
-
- // When it's UNKNOWN_CARRIER_ID or matched with configured CarrierId,
- // devices connects it with the SIM subscription of defaultDataSubscriptionId.
- if (defaultDataSubscriptionId == subscriptionInfo.getSubscriptionId()
- && (config.carrierId == subscriptionInfo.getCarrierId()
- || config.carrierId == TelephonyManager.UNKNOWN_CARRIER_ID)) {
- mEapSimSubscriptionPref.setSummary(displayName);
- return;
- }
- }
-
- if (firstCarrierIdMatchedDisplayName != null) {
- mEapSimSubscriptionPref.setSummary(firstCarrierIdMatchedDisplayName);
+ SubscriptionInfo info = fineSubscriptionInfo(config.carrierId, activeSubscriptionInfos,
+ SubscriptionManager.getDefaultDataSubscriptionId());
+ if (info != null) {
+ mEapSimSubscriptionPref.setSummary(
+ SubscriptionUtil.getUniqueSubscriptionDisplayName(info, mContext));
return;
}
}
- if (config.carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) {
+ if (config.carrierId == UNKNOWN_CARRIER_ID) {
mEapSimSubscriptionPref.setSummary(R.string.wifi_no_related_sim_card);
return;
}
@@ -736,6 +719,25 @@ public class WifiDetailPreferenceController2 extends AbstractPreferenceControlle
null /* orderBy */);
}
+ @VisibleForTesting
+ SubscriptionInfo fineSubscriptionInfo(int carrierId,
+ List activeSubscriptionInfos, int defaultDataSubscriptionId) {
+ SubscriptionInfo firstMatchedInfo = null;
+ for (SubscriptionInfo info : activeSubscriptionInfos) {
+ // When it's UNKNOWN_CARRIER_ID or matched with configured CarrierId,
+ // devices connects it with the SIM subscription of defaultDataSubscriptionId.
+ if (defaultDataSubscriptionId == info.getSubscriptionId()
+ && (carrierId == info.getCarrierId() || carrierId == UNKNOWN_CARRIER_ID)) {
+ return info;
+ }
+
+ if (firstMatchedInfo == null && carrierId == info.getCarrierId()) {
+ firstMatchedInfo = info;
+ }
+ }
+ return firstMatchedInfo;
+ }
+
private void refreshMacAddress() {
final String macAddress = mWifiEntry.getMacAddress();
if (TextUtils.isEmpty(macAddress)) {
diff --git a/tests/robotests/src/com/android/settings/SettingsLicenseActivityTest.java b/tests/robotests/src/com/android/settings/SettingsLicenseActivityTest.java
index e98ca311598..6b00255f3af 100644
--- a/tests/robotests/src/com/android/settings/SettingsLicenseActivityTest.java
+++ b/tests/robotests/src/com/android/settings/SettingsLicenseActivityTest.java
@@ -92,7 +92,8 @@ public class SettingsLicenseActivityTest {
"text/html");
intent.putExtra(Intent.EXTRA_TITLE, mActivity.getString(
R.string.settings_license_activity_title));
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.addFlags(
+ Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setPackage("com.android.htmlviewer");
diff --git a/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
index 7cfcaffb97d..56e83bb90ae 100644
--- a/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
@@ -16,29 +16,71 @@
package com.android.settings.notification;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_MEDIA_URI;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.Intent;
import android.media.AudioManager;
+import android.media.session.MediaController;
+import android.net.Uri;
+
+import androidx.slice.builders.SliceAction;
+
+import com.android.settings.media.MediaOutputIndicatorWorker;
+import com.android.settings.slices.SliceBackgroundWorker;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.media.BluetoothMediaDevice;
+import com.android.settingslib.media.MediaDevice;
+import com.android.settingslib.media.MediaOutputConstants;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = MediaVolumePreferenceControllerTest.ShadowSliceBackgroundWorker.class)
public class MediaVolumePreferenceControllerTest {
+ private static final String ACTION_LAUNCH_BROADCAST_DIALOG =
+ "android.settings.MEDIA_BROADCAST_DIALOG";
+ private static MediaOutputIndicatorWorker sMediaOutputIndicatorWorker;
+
private MediaVolumePreferenceController mController;
private Context mContext;
+ @Mock
+ private MediaController mMediaController;
+ @Mock
+ private MediaDevice mDevice1;
+ @Mock
+ private MediaDevice mDevice2;
+
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
mContext = RuntimeEnvironment.application;
mController = new MediaVolumePreferenceController(mContext);
+ sMediaOutputIndicatorWorker = spy(
+ new MediaOutputIndicatorWorker(mContext, VOLUME_MEDIA_URI));
+ when(mDevice1.isBLEDevice()).thenReturn(true);
+ when(mDevice2.isBLEDevice()).thenReturn(false);
}
@Test
@@ -68,4 +110,83 @@ public class MediaVolumePreferenceControllerTest {
public void isPublicSlice_returnTrue() {
assertThat(mController.isPublicSlice()).isTrue();
}
+
+ @Test
+ public void isSupportEndItem_withBleDevice_returnsTrue() {
+ doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
+
+ assertThat(mController.isSupportEndItem()).isTrue();
+ }
+
+ @Test
+ public void isSupportEndItem_withNonBleDevice_returnsFalse() {
+ doReturn(mDevice2).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
+
+ assertThat(mController.isSupportEndItem()).isFalse();
+ }
+
+ @Test
+ public void getSliceEndItem_NotSupportEndItem_getsNullSliceAction() {
+ doReturn(mDevice2).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
+
+ final SliceAction sliceAction = mController.getSliceEndItem(mContext);
+
+ assertThat(sliceAction).isNull();
+ }
+
+ @Test
+ public void getSliceEndItem_deviceIsBroadcasting_getsBroadcastIntent() {
+ doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
+ doReturn(true).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
+ doReturn(mMediaController).when(sMediaOutputIndicatorWorker)
+ .getActiveLocalMediaController();
+
+ final SliceAction sliceAction = mController.getSliceEndItem(mContext);
+
+ final PendingIntent endItemPendingIntent = sliceAction.getAction();
+ final PendingIntent expectedToggleIntent = getBroadcastIntent(
+ MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG);
+ assertThat(endItemPendingIntent).isEqualTo(expectedToggleIntent);
+ }
+
+ @Test
+ public void getSliceEndItem_deviceIsNotBroadcasting_getsActivityIntent() {
+ final MediaDevice device = mock(BluetoothMediaDevice.class);
+ final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
+ when(((BluetoothMediaDevice) device).getCachedDevice()).thenReturn(cachedDevice);
+ when(device.isBLEDevice()).thenReturn(true);
+ doReturn(device).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
+ doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
+ doReturn(mMediaController).when(sMediaOutputIndicatorWorker)
+ .getActiveLocalMediaController();
+
+ final SliceAction sliceAction = mController.getSliceEndItem(mContext);
+
+ final PendingIntent endItemPendingIntent = sliceAction.getAction();
+ final PendingIntent expectedPendingIntent =
+ getActivityIntent(ACTION_LAUNCH_BROADCAST_DIALOG);
+ assertThat(endItemPendingIntent).isEqualTo(expectedPendingIntent);
+ }
+
+ @Implements(SliceBackgroundWorker.class)
+ public static class ShadowSliceBackgroundWorker {
+
+ @Implementation
+ public static SliceBackgroundWorker getInstance(Uri uri) {
+ return sMediaOutputIndicatorWorker;
+ }
+ }
+
+ private PendingIntent getBroadcastIntent(String action) {
+ final Intent intent = new Intent(action);
+ intent.setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME);
+ return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ }
+
+ private PendingIntent getActivityIntent(String action) {
+ final Intent intent = new Intent(action);
+ return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
index 3c50c6bf2f4..43a49a1a1b3 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
@@ -27,6 +27,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static com.android.internal.widget.LockPatternUtils.PASSWORD_TYPE_KEY;
import static com.android.settings.password.ChooseLockGeneric.CONFIRM_CREDENTIALS;
@@ -158,6 +159,21 @@ public class ChooseLockPasswordTest {
.isNotNull();
}
+ @Test
+ public void activity_shouldHaveSecureFlag() {
+ PasswordPolicy policy = new PasswordPolicy();
+ policy.quality = PASSWORD_QUALITY_ALPHABETIC;
+ policy.length = 10;
+
+ Intent intent = createIntentForPasswordValidation(
+ /* minMetrics */ policy.getMinMetrics(),
+ /* minComplexity= */ PASSWORD_COMPLEXITY_NONE,
+ /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC);
+ ChooseLockPassword activity = buildChooseLockPasswordActivity(intent);
+ final int flags = activity.getWindow().getAttributes().flags;
+ assertThat(flags & FLAG_SECURE).isEqualTo(FLAG_SECURE);
+ }
+
@Test
public void processAndValidatePasswordRequirements_noMinPasswordComplexity() {
PasswordPolicy policy = new PasswordPolicy();
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
index f5cc39435ad..1fc10fc75f2 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
@@ -16,6 +16,8 @@
package com.android.settings.password;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -107,6 +109,14 @@ public class ChooseLockPatternTest {
assertThat(iconView.getVisibility()).isEqualTo(View.GONE);
}
+ @Test
+ public void activity_shouldHaveSecureFlag() {
+ final ChooseLockPattern activity = Robolectric.buildActivity(
+ ChooseLockPattern.class, new IntentBuilder(application).build()).setup().get();
+ final int flags = activity.getWindow().getAttributes().flags;
+ assertThat(flags & FLAG_SECURE).isEqualTo(FLAG_SECURE);
+ }
+
private ChooseLockPattern createActivity(boolean addFingerprintExtra) {
return Robolectric.buildActivity(
ChooseLockPattern.class,
diff --git a/tests/robotests/src/com/android/settings/privacy/WorkPolicyInfoPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/privacy/WorkPolicyInfoPreferenceControllerTest.java
index 82444aade07..a983228255e 100644
--- a/tests/robotests/src/com/android/settings/privacy/WorkPolicyInfoPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/privacy/WorkPolicyInfoPreferenceControllerTest.java
@@ -21,6 +21,7 @@ import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -30,6 +31,7 @@ import android.content.Context;
import androidx.preference.Preference;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
+import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
@@ -52,6 +54,7 @@ public class WorkPolicyInfoPreferenceControllerTest {
mContext = RuntimeEnvironment.application;
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
mEnterpriseProvider = mFakeFeatureFactory.getEnterprisePrivacyFeatureProvider(mContext);
+ SafetyCenterManagerWrapper.sInstance = mock(SafetyCenterManagerWrapper.class);
}
@Test
@@ -72,6 +75,15 @@ public class WorkPolicyInfoPreferenceControllerTest {
assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
+ @Test
+ public void getAvailabilityStatus_safetyCenterEnabled_shouldReturnUnsupported() {
+ when(SafetyCenterManagerWrapper.get().isEnabled(mContext)).thenReturn(true);
+ WorkPolicyInfoPreferenceController controller =
+ new WorkPolicyInfoPreferenceController(mContext, "test_key");
+
+ assertThat(controller.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
@Test
public void handlePreferenceTreeClick_nonMatchingKey_shouldDoNothing() {
when(mEnterpriseProvider.hasWorkPolicyInfo()).thenReturn(true);
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
index b0a50c81fa8..c86a0230351 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
@@ -59,6 +59,7 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.provider.Settings;
+import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.view.View;
import android.view.View.OnClickListener;
@@ -108,6 +109,7 @@ import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Arrays;
+import java.util.List;
import java.util.stream.Collectors;
// TODO(b/143326832): Should add test cases for connect button.
@@ -1791,4 +1793,74 @@ public class WifiDetailPreferenceController2Test {
return pref;
}
+
+ @Test
+ public void fineSubscriptionInfo_noMatchedCarrierId_returnNull() {
+ setUpSpyController();
+ SubscriptionInfo sub1 = mockSubscriptionInfo(1, "sim1", 1111);
+ SubscriptionInfo sub2 = mockSubscriptionInfo(2, "sim2", 2222);
+ List activeSubInfos = Arrays.asList(sub1, sub2);
+
+ SubscriptionInfo info = mController.fineSubscriptionInfo(3333, activeSubInfos, 1);
+
+ assertThat(info).isNull();
+
+ info = mController.fineSubscriptionInfo(3333, activeSubInfos, 2);
+
+ assertThat(info).isNull();
+ }
+
+ @Test
+ public void fineSubscriptionInfo_diffCarrierId_returnMatchedOne() {
+ setUpSpyController();
+ SubscriptionInfo sub1 = mockSubscriptionInfo(1, "sim1", 1111);
+ SubscriptionInfo sub2 = mockSubscriptionInfo(2, "sim2", 2222);
+ List activeSubInfos = Arrays.asList(sub1, sub2);
+
+ SubscriptionInfo info = mController.fineSubscriptionInfo(1111, activeSubInfos, 1);
+
+ assertThat(info).isNotNull();
+ assertThat(info.getDisplayName().toString()).isEqualTo("sim1");
+
+ info = mController.fineSubscriptionInfo(1111, activeSubInfos, 2);
+
+ assertThat(info).isNotNull();
+ assertThat(info.getDisplayName().toString()).isEqualTo("sim1");
+
+ info = mController.fineSubscriptionInfo(2222, activeSubInfos, 1);
+
+ assertThat(info).isNotNull();
+ assertThat(info.getDisplayName().toString()).isEqualTo("sim2");
+
+ info = mController.fineSubscriptionInfo(2222, activeSubInfos, 2);
+
+ assertThat(info).isNotNull();
+ assertThat(info.getDisplayName().toString()).isEqualTo("sim2");
+ }
+
+ @Test
+ public void fineSubscriptionInfo_sameCarrierId_returnDefaultDataOne() {
+ setUpSpyController();
+ SubscriptionInfo sub1 = mockSubscriptionInfo(1, "sim1", 1111);
+ SubscriptionInfo sub2 = mockSubscriptionInfo(2, "sim2", 1111);
+ List activeSubInfos = Arrays.asList(sub1, sub2);
+
+ SubscriptionInfo info = mController.fineSubscriptionInfo(1111, activeSubInfos, 1);
+
+ assertThat(info).isNotNull();
+ assertThat(info.getDisplayName().toString()).isEqualTo("sim1");
+
+ info = mController.fineSubscriptionInfo(1111, activeSubInfos, 2);
+
+ assertThat(info).isNotNull();
+ assertThat(info.getDisplayName().toString()).isEqualTo("sim2");
+ }
+
+ private SubscriptionInfo mockSubscriptionInfo(int subId, String displayName, int carrierId) {
+ SubscriptionInfo info = mock(SubscriptionInfo.class);
+ when(info.getSubscriptionId()).thenReturn(subId);
+ when(info.getDisplayName()).thenReturn(displayName);
+ when(info.getCarrierId()).thenReturn(carrierId);
+ return info;
+ }
}