diff options
16 files changed, 299 insertions, 124 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java index 8f5dbc45bf1b..62ac84b2b1e6 100644 --- a/core/java/android/app/admin/DevicePolicyManagerInternal.java +++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java @@ -222,4 +222,16 @@ public abstract class DevicePolicyManagerInternal { * Returns the profile owner component for the given user, or {@code null} if there is not one. */ public abstract ComponentName getProfileOwnerAsUser(int userHandle); + + /** + * Returns whether this class supports being deferred the responsibility for resetting the given + * op. + */ + public abstract boolean supportsResetOp(int op); + + /** + * Resets the given op across the profile group of the given user for the given package. Assumes + * {@link #supportsResetOp(int)} is true. + */ + public abstract void resetOp(int op, String packageName, @UserIdInt int userId); } diff --git a/core/java/android/content/pm/CrossProfileAppsInternal.java b/core/java/android/content/pm/CrossProfileAppsInternal.java index 16a749fa360a..255aeac06cae 100644 --- a/core/java/android/content/pm/CrossProfileAppsInternal.java +++ b/core/java/android/content/pm/CrossProfileAppsInternal.java @@ -17,6 +17,7 @@ package android.content.pm; import android.annotation.UserIdInt; +import android.app.AppOpsManager.Mode; import android.os.UserHandle; import java.util.List; @@ -62,4 +63,14 @@ public abstract class CrossProfileAppsInternal { */ public abstract List<UserHandle> getTargetUserProfiles( String packageName, @UserIdInt int userId); + + /** + * Sets the app-op for {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} that is + * configurable by users in Settings. This configures it for the profile group of the given + * user. + * + * @see CrossProfileApps#setInteractAcrossProfilesAppOp(String, int) + */ + public abstract void setInteractAcrossProfilesAppOp( + String packageName, @Mode int newMode, @UserIdInt int userId); } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index a29f8782601e..ed03f5198d6f 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3115,9 +3115,9 @@ public class ConnectivityManager { } /** - * Set sign in error notification to visible or in visible + * Set sign in error notification to visible or invisible * - * {@hide} + * @hide * @deprecated Doesn't properly deal with multiple connected networks of the same type. */ @Deprecated diff --git a/core/proto/android/stats/mediametrics/mediametrics.proto b/core/proto/android/stats/mediametrics/mediametrics.proto index 9f0ff591a506..2a27fa21817c 100644 --- a/core/proto/android/stats/mediametrics/mediametrics.proto +++ b/core/proto/android/stats/mediametrics/mediametrics.proto @@ -166,12 +166,23 @@ message CodecData { * Logged from: * frameworks/av/media/libstagefright/RemoteMediaExtractor.cpp * frameworks/av/services/mediaanalytics/statsd_extractor.cpp - * Next Tag: 4 + * Next Tag: 5 */ message ExtractorData { optional string format = 1; optional string mime = 2; optional int32 tracks = 3; + + enum EntryPoint { + UNSET = 0; // For backwards compatibility with clients that don't + // collect the entry point. + SDK = 1; + NDK_WITH_JVM = 2; + NDK_NO_JVM = 3; + OTHER = 4; // For extractor users that don't make use of the APIs. + } + + optional EntryPoint entry_point = 4 [default = UNSET]; } /** diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp index 528dc62c3016..c60203eae759 100644 --- a/media/jni/android_media_MediaExtractor.cpp +++ b/media/jni/android_media_MediaExtractor.cpp @@ -68,7 +68,7 @@ JMediaExtractor::JMediaExtractor(JNIEnv *env, jobject thiz) mClass = (jclass)env->NewGlobalRef(clazz); mObject = env->NewWeakGlobalRef(thiz); - mImpl = new NuMediaExtractor; + mImpl = new NuMediaExtractor(NuMediaExtractor::EntryPoint::SDK); } JMediaExtractor::~JMediaExtractor() { diff --git a/packages/CarSystemUI/res/values-uz/strings.xml b/packages/CarSystemUI/res/values-uz/strings.xml index adef2add435f..15b2b7aa8ac8 100644 --- a/packages/CarSystemUI/res/values-uz/strings.xml +++ b/packages/CarSystemUI/res/values-uz/strings.xml @@ -17,7 +17,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="hvac_min_text" msgid="8167124789068494624">"Daq."</string> + <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string> <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string> <string name="voice_recognition_toast" msgid="1149934534584052842">"Endi ovozni tanish Bluetooth qurilma ulanganda amalga oshadi"</string> <string name="car_guest" msgid="318393171202663722">"Mehmon"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 4397b35699fa..a3f26efb53b6 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -489,7 +489,6 @@ <string name="wifi_status_mac_randomized" msgid="466382542497832189">"Les adresses MAC sont randomisées"</string> <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139"> <item quantity="one">%1$d appareil connecté</item> - <item quantity="many">%1$d devices connected</item> <item quantity="other">%1$d appareils connectés</item> </plurals> <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Plus longtemps."</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 6d7428d48e56..a467540156e0 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -251,7 +251,7 @@ <string name="wifi_display_certification" msgid="1805579519992520381">"Certification affichage sans fil"</string> <string name="wifi_verbose_logging" msgid="1785910450009679371">"Autoriser l\'enregistrement d\'infos Wi-Fi détaillées"</string> <string name="wifi_scan_throttling" msgid="2985624788509913617">"Limiter la recherche Wi‑Fi"</string> - <string name="wifi_enhanced_mac_randomization" msgid="5437378364995776979">"Chgt aléatoire d\'adresse MAC en Wi-Fi"</string> + <string name="wifi_enhanced_mac_randomization" msgid="5437378364995776979">"Changement aléatoire d\'adresse MAC en Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8275958101875563572">"Données mobiles toujours actives"</string> <string name="tethering_hardware_offload" msgid="4116053719006939161">"Accélération matérielle pour le partage de connexion"</string> <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Afficher les appareils Bluetooth sans nom"</string> @@ -489,7 +489,6 @@ <string name="wifi_status_mac_randomized" msgid="466382542497832189">"La sélection des adresses MAC est aléatoire"</string> <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139"> <item quantity="one">%1$d appareil connecté</item> - <item quantity="many">%1$d devices connected</item> <item quantity="other">%1$d appareils connectés</item> </plurals> <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Plus longtemps."</string> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java index dc42997be0d3..603679afc109 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java @@ -75,6 +75,7 @@ import com.android.systemui.tracing.nano.EdgeBackGestureHandlerProto; import com.android.systemui.tracing.nano.SystemUiTraceProto; import java.io.PrintWriter; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -204,10 +205,15 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa private BackGestureTfClassifierProvider mBackGestureTfClassifierProvider; private Map<String, Integer> mVocab; private boolean mUseMLModel; + // minimum width below which we do not run the model + private int mMLEnableWidth; private float mMLModelThreshold; private String mPackageName; private float mMLResults; + private static final int MAX_LOGGED_PREDICTIONS = 10; + private ArrayDeque<String> mPredictionLog = new ArrayDeque<>(); + private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver; private final NavigationEdgeBackPlugin.BackCallback mBackCallback = @@ -292,6 +298,11 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa mBottomGestureHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, gestureHeight, dm); + // Set the minimum bounds to activate ML to 12dp or the minimum of configured values + mMLEnableWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12.0f, dm); + if (mMLEnableWidth > mEdgeWidthRight) mMLEnableWidth = mEdgeWidthRight; + if (mMLEnableWidth > mEdgeWidthLeft) mMLEnableWidth = mEdgeWidthLeft; + // Reduce the default touch slop to ensure that we can intercept the gesture // before the app starts to react to it. // TODO(b/130352502) Tune this value and extract into a constant @@ -500,8 +511,8 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa } } - private float getBackGesturePredictionsCategory(int x, int y) { - if (!mVocab.containsKey(mPackageName)) { + private int getBackGesturePredictionsCategory(int x, int y, int app) { + if (app == -1) { return -1; } @@ -519,20 +530,19 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa new long[]{(long) mDisplaySize.x}, new long[]{(long) distanceFromEdge}, new long[]{(long) location}, - new long[]{(long) mVocab.get(mPackageName)}, + new long[]{(long) app}, new long[]{(long) y}, }; mMLResults = mBackGestureTfClassifierProvider.predict(featuresVector); - if (mMLResults == -1) return -1; + if (mMLResults == -1) { + return -1; + } return mMLResults >= mMLModelThreshold ? 1 : 0; } private boolean isWithinTouchRegion(int x, int y) { - boolean withinRange = false; - float results = -1; - // Disallow if we are in the bottom gesture area if (y >= (mDisplaySize.y - mBottomGestureHeight)) { return false; @@ -546,15 +556,33 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa return false; } - if (mUseMLModel && (results = getBackGesturePredictionsCategory(x, y)) != -1) { - withinRange = results == 1 ? true : false; - } else { - // Denotes whether we should proceed with the gesture. - // Even if it is false, we may want to log it assuming - // it is not invalid due to exclusion. - withinRange = x <= mEdgeWidthLeft + mLeftInset - || x >= (mDisplaySize.x - mEdgeWidthRight - mRightInset); + int app = -1; + if (mVocab != null) { + app = mVocab.getOrDefault(mPackageName, -1); + } + // Check if we are within the tightest bounds beyond which + // we would not need to run the ML model. + boolean withinRange = x <= mMLEnableWidth + mLeftInset + || x >= (mDisplaySize.x - mMLEnableWidth - mRightInset); + if (!withinRange) { + int results = -1; + if (mUseMLModel && (results = getBackGesturePredictionsCategory(x, y, app)) != -1) { + withinRange = results == 1; + } else { + // Denotes whether we should proceed with the gesture. + // Even if it is false, we may want to log it assuming + // it is not invalid due to exclusion. + withinRange = x <= mEdgeWidthLeft + mLeftInset + || x >= (mDisplaySize.x - mEdgeWidthRight - mRightInset); + } + } + + // For debugging purposes + if (mPredictionLog.size() >= MAX_LOGGED_PREDICTIONS) { + mPredictionLog.removeFirst(); } + mPredictionLog.addLast(String.format("[%d,%d,%d,%f,%d]", + x, y, app, mMLResults, withinRange ? 1 : 0)); // Always allow if the user is in a transient sticky immersive state if (mIsNavBarShownTransiently) { @@ -753,6 +781,8 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa pw.println(" mIsAttached=" + mIsAttached); pw.println(" mEdgeWidthLeft=" + mEdgeWidthLeft); pw.println(" mEdgeWidthRight=" + mEdgeWidthRight); + pw.println(" mIsNavBarShownTransiently=" + mIsNavBarShownTransiently); + pw.println(" mPredictionLog=" + String.join(";", mPredictionLog)); } private boolean isGestureBlockingActivityRunning() { diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 8c38b66dd44e..9ce7cf27f9ff 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -1236,7 +1236,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public boolean bindBluetoothProfileService(int bluetoothProfile, IBluetoothProfileServiceConnection proxy) { - if (!mEnable) { + if (mState != BluetoothAdapter.STATE_ON) { if (DBG) { Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + ", while Bluetooth was disabled"); @@ -1400,7 +1400,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } - if (!mEnable || state != BluetoothAdapter.STATE_ON) { + if (state != BluetoothAdapter.STATE_ON) { if (DBG) { Slog.d(TAG, "Unable to bindService while Bluetooth is disabled"); } diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 1b12dc79d98f..4e194e2e495a 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -75,6 +75,7 @@ import android.Manifest; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AppGlobals; @@ -89,6 +90,7 @@ import android.app.AppOpsManagerInternal.CheckOpsDelegate; import android.app.AsyncNotedAppOp; import android.app.RuntimeAppOpAccessMessage; import android.app.SyncNotedAppOp; +import android.app.admin.DevicePolicyManagerInternal; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -270,6 +272,8 @@ public class AppOpsService extends IAppOpsService.Stub { private final AppOpsManagerInternalImpl mAppOpsManagerInternal = new AppOpsManagerInternalImpl(); + @Nullable private final DevicePolicyManagerInternal dpmi = + LocalServices.getService(DevicePolicyManagerInternal.class); /** * Registered callbacks, called from {@link #collectAsyncNotedOp}. @@ -2675,6 +2679,10 @@ public class AppOpsService extends IAppOpsService.Stub { Ops pkgOps = ent.getValue(); for (int j=pkgOps.size()-1; j>=0; j--) { Op curOp = pkgOps.valueAt(j); + if (shouldDeferResetOpToDpm(curOp.op)) { + deferResetOpToDpm(curOp.op, reqPackageName, reqUserId); + continue; + } if (AppOpsManager.opAllowsReset(curOp.op) && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) { int previousMode = curOp.mode; @@ -2724,16 +2732,27 @@ public class AppOpsService extends IAppOpsService.Stub { } } - if (allChanges != null) { - int numChanges = allChanges.size(); - for (int i = 0; i < numChanges; i++) { - ChangeRec change = allChanges.get(i); - notifyOpChangedSync(change.op, change.uid, change.pkg, - AppOpsManager.opToDefaultMode(change.op), change.previous_mode); - } + int numChanges = allChanges.size(); + for (int i = 0; i < numChanges; i++) { + ChangeRec change = allChanges.get(i); + notifyOpChangedSync(change.op, change.uid, change.pkg, + AppOpsManager.opToDefaultMode(change.op), change.previous_mode); } } + private boolean shouldDeferResetOpToDpm(int op) { + // TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission + // pre-grants to a role-based mechanism or another general-purpose mechanism. + return dpmi != null && dpmi.supportsResetOp(op); + } + + /** Assumes {@link #shouldDeferResetOpToDpm(int)} is true. */ + private void deferResetOpToDpm(int op, String packageName, @UserIdInt int userId) { + // TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission + // pre-grants to a role-based mechanism or another general-purpose mechanism. + dpmi.resetOp(op, packageName, userId); + } + private void evalAllForegroundOpsLocked() { for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) { final UidState uidState = mUidStates.valueAt(uidi); diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 34b0aa246433..71ef0e280912 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -324,7 +324,13 @@ public class NetworkNotificationManager { */ public void setProvNotificationVisible(boolean visible, int id, String action) { if (visible) { - Intent intent = new Intent(action); + // For legacy purposes, action is sent as the action + the phone ID from DcTracker. + // Split the string here and send the phone ID as an extra instead. + String[] splitAction = action.split(":"); + Intent intent = new Intent(splitAction[0]); + try { + intent.putExtra("provision.phone.id", Integer.parseInt(splitAction[1])); + } catch (NumberFormatException ignored) { } PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); showNotification(id, NotificationType.SIGN_IN, null, null, pendingIntent, false); } else { diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java index 617f6879e65e..3e9e45e59b95 100644 --- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java +++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java @@ -14,14 +14,17 @@ * limitations under the License. */ package com.android.server.pm; - +import static android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES; +import static android.Manifest.permission.INTERACT_ACROSS_PROFILES; +import static android.Manifest.permission.INTERACT_ACROSS_USERS; +import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; +import static android.Manifest.permission.MANAGE_APP_OPS_MODES; import static android.app.AppOpsManager.OP_INTERACT_ACROSS_PROFILES; import static android.content.Intent.FLAG_RECEIVER_REGISTERED_ONLY; import static android.content.pm.CrossProfileApps.ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; -import android.Manifest; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -31,7 +34,6 @@ import android.app.AppOpsManager; import android.app.AppOpsManager.Mode; import android.app.IApplicationThread; import android.app.admin.DevicePolicyEventLogger; -import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.ComponentName; import android.content.Context; @@ -154,15 +156,15 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { if (callerUserId != userId) { final int permissionFlag = PermissionChecker.checkPermissionForPreflight( mContext, - android.Manifest.permission.INTERACT_ACROSS_PROFILES, + INTERACT_ACROSS_PROFILES, callingPid, callingUid, callingPackage); if (permissionFlag != PermissionChecker.PERMISSION_GRANTED || !isSameProfileGroup(callerUserId, userId)) { throw new SecurityException("Attempt to launch activity without required " - + android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission" - + " or target user is not in the same profile group."); + + INTERACT_ACROSS_PROFILES + + " permission or target user is not in the same profile group."); } } launchIntent.setComponent(component); @@ -217,8 +219,8 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { if (callerUserId != userId) { if (!hasCallerGotInteractAcrossProfilesPermission(callingPackage)) { throw new SecurityException("Attempt to launch activity without required " - + android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission" - + " or target user is not in the same profile group."); + + INTERACT_ACROSS_PROFILES + + " permission or target user is not in the same profile group."); } } @@ -294,13 +296,13 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { callingPackage, mInjector.getCallingUid(), mInjector.getCallingPid()); } - private boolean isCrossProfilePackageWhitelisted(String packageName) { + private boolean isCrossProfilePackageAllowlisted(String packageName) { return mInjector.withCleanCallingIdentity(() -> mInjector.getDevicePolicyManagerInternal() .getAllCrossProfilePackages().contains(packageName)); } - private boolean isCrossProfilePackageWhitelistedByDefault(String packageName) { + private boolean isCrossProfilePackageAllowlistedByDefault(String packageName) { return mInjector.withCleanCallingIdentity(() -> mInjector.getDevicePolicyManagerInternal() .getDefaultCrossProfilePackages().contains(packageName)); @@ -388,32 +390,36 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { /** * See {@link android.content.pm.CrossProfileApps#setInteractAcrossProfilesAppOp(String, int)}. * - * <p>Logs metrics. Use {@link #setInteractAcrossProfilesAppOpUnchecked(String, int, boolean)} - * to avoid permission checks or to specify not to log metrics. + * <p>Use {@link #setInteractAcrossProfilesAppOpUnchecked(String, int, int)} to avoid permission + * checks. */ @Override public void setInteractAcrossProfilesAppOp(String packageName, @Mode int newMode) { + setInteractAcrossProfilesAppOp(packageName, newMode, mInjector.getCallingUserId()); + } + + private void setInteractAcrossProfilesAppOp( + String packageName, @Mode int newMode, @UserIdInt int userId) { final int callingUid = mInjector.getCallingUid(); - if (!isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid) - && !isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, callingUid)) { + if (!isPermissionGranted(INTERACT_ACROSS_USERS_FULL, callingUid) + && !isPermissionGranted(INTERACT_ACROSS_USERS, callingUid)) { throw new SecurityException( "INTERACT_ACROSS_USERS or INTERACT_ACROSS_USERS_FULL is required to set the" + " app-op for interacting across profiles."); } - if (!isPermissionGranted(Manifest.permission.MANAGE_APP_OPS_MODES, callingUid) - && !isPermissionGranted( - Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) { + if (!isPermissionGranted(MANAGE_APP_OPS_MODES, callingUid) + && !isPermissionGranted(CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) { throw new SecurityException( "MANAGE_APP_OPS_MODES or CONFIGURE_INTERACT_ACROSS_PROFILES is required to set" + " the app-op for interacting across profiles."); } - setInteractAcrossProfilesAppOpUnchecked(packageName, newMode, /* logMetrics= */ true); + setInteractAcrossProfilesAppOpUnchecked(packageName, newMode, userId); } private void setInteractAcrossProfilesAppOpUnchecked( - String packageName, @Mode int newMode, boolean logMetrics) { + String packageName, @Mode int newMode, @UserIdInt int userId) { if (newMode == AppOpsManager.MODE_ALLOWED - && !canConfigureInteractAcrossProfiles(packageName)) { + && !canConfigureInteractAcrossProfiles(packageName, userId)) { // The user should not be prompted for apps that cannot request to interact across // profiles. However, we return early here if required to avoid race conditions. Slog.e(TAG, "Tried to turn on the appop for interacting across profiles for invalid" @@ -421,56 +427,57 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { return; } final int[] profileIds = - mInjector.getUserManager() - .getProfileIds(mInjector.getCallingUserId(), /* enabledOnly= */ false); + mInjector.getUserManager().getProfileIds(userId, /* enabledOnly= */ false); for (int profileId : profileIds) { if (!isPackageInstalled(packageName, profileId)) { continue; } - setInteractAcrossProfilesAppOpForUser(packageName, newMode, profileId, logMetrics); + // Only log once per profile group by checking against the user ID. + setInteractAcrossProfilesAppOpForProfile( + packageName, newMode, profileId, /* logMetrics= */ profileId == userId); } } + /** + * Returns whether the given package name is installed in the given user ID. The calling UID is + * used as the filter calling UID, as described at {@link PackageManagerInternal#getPackageInfo( + * String, int, int, int)}. + */ private boolean isPackageInstalled(String packageName, @UserIdInt int userId) { - final int callingUid = mInjector.getCallingUid(); return mInjector.withCleanCallingIdentity(() -> { + final int flags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE; final PackageInfo info = mInjector.getPackageManagerInternal() - .getPackageInfo( - packageName, - MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, - callingUid, - userId); + .getPackageInfo(packageName, flags, mInjector.getCallingUid(), userId); return info != null; }); } - private void setInteractAcrossProfilesAppOpForUser( - String packageName, @Mode int newMode, @UserIdInt int userId, boolean logMetrics) { + private void setInteractAcrossProfilesAppOpForProfile( + String packageName, @Mode int newMode, @UserIdInt int profileId, boolean logMetrics) { try { - setInteractAcrossProfilesAppOpForUserOrThrow(packageName, newMode, userId, logMetrics); + setInteractAcrossProfilesAppOpForProfileOrThrow( + packageName, newMode, profileId, logMetrics); } catch (PackageManager.NameNotFoundException e) { - Slog.e(TAG, "Missing package " + packageName + " on user ID " + userId, e); + Slog.e(TAG, "Missing package " + packageName + " on profile user ID " + profileId, e); } } - private void setInteractAcrossProfilesAppOpForUserOrThrow( - String packageName, @Mode int newMode, @UserIdInt int userId, boolean logMetrics) + private void setInteractAcrossProfilesAppOpForProfileOrThrow( + String packageName, @Mode int newMode, @UserIdInt int profileId, boolean logMetrics) throws PackageManager.NameNotFoundException { final int uid = mInjector.getPackageManager() - .getPackageUidAsUser(packageName, /* flags= */ 0, userId); + .getPackageUidAsUser(packageName, /* flags= */ 0, profileId); if (currentModeEquals(newMode, packageName, uid)) { Slog.i(TAG, "Attempt to set mode to existing value of " + newMode + " for " - + packageName + " on user ID " + userId); + + packageName + " on profile user ID " + profileId); return; } final boolean hadPermission = hasInteractAcrossProfilesPermission( packageName, uid, PermissionChecker.PID_UNKNOWN); - final int callingUid = mInjector.getCallingUid(); - if (isPermissionGranted( - Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) { + if (isPermissionGranted(CONFIGURE_INTERACT_ACROSS_PROFILES, mInjector.getCallingUid())) { // Clear calling identity since the CONFIGURE_INTERACT_ACROSS_PROFILES permission allows // this particular app-op to be modified without the broader app-op permissions. mInjector.withCleanCallingIdentity(() -> @@ -483,16 +490,15 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { // Kill the UID before sending the broadcast to ensure that apps can be informed when // their app-op has been revoked. maybeKillUid(packageName, uid, hadPermission); - sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(userId)); - maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, userId, logMetrics, uid); + sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(profileId)); + maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, logMetrics, uid); } /** * Kills the process represented by the given UID if it has lost the permission to * interact across profiles. */ - private void maybeKillUid( - String packageName, int uid, boolean hadPermission) { + private void maybeKillUid(String packageName, int uid, boolean hadPermission) { if (!hadPermission) { return; } @@ -503,18 +509,10 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { } private void maybeLogSetInteractAcrossProfilesAppOp( - String packageName, - @Mode int newMode, - @UserIdInt int userId, - boolean logMetrics, - int uid) { + String packageName, @Mode int newMode, boolean logMetrics, int uid) { if (!logMetrics) { return; } - if (userId != mInjector.getCallingUserId()) { - // Only log once per profile group by checking for the calling user ID. - return; - } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_INTERACT_ACROSS_PROFILES_APP_OP) .setStrings(packageName) @@ -529,8 +527,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { * any necessary permission checks. */ private boolean currentModeEquals(@Mode int otherMode, String packageName, int uid) { - final String op = - AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES); + final String op = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES); return mInjector.withCleanCallingIdentity(() -> otherMode == mInjector.getAppOpsManager().unsafeCheckOpNoThrow(op, uid, packageName)); } @@ -562,37 +559,49 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { @Override public boolean canConfigureInteractAcrossProfiles(String packageName) { - if (!canUserAttemptToConfigureInteractAcrossProfiles(packageName)) { + return canConfigureInteractAcrossProfiles(packageName, mInjector.getCallingUserId()); + } + + private boolean canConfigureInteractAcrossProfiles(String packageName, @UserIdInt int userId) { + if (!canUserAttemptToConfigureInteractAcrossProfiles(packageName, userId)) { return false; } - if (!hasOtherProfileWithPackageInstalled(packageName, mInjector.getCallingUserId())) { + if (!hasOtherProfileWithPackageInstalled(packageName, userId)) { return false; } if (!hasRequestedAppOpPermission( AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)) { return false; } - return isCrossProfilePackageWhitelisted(packageName); + return isCrossProfilePackageAllowlisted(packageName); } @Override public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) { - final int[] profileIds = mInjector.getUserManager().getProfileIds( - mInjector.getCallingUserId(), /* enabledOnly= */ false); + return canUserAttemptToConfigureInteractAcrossProfiles( + packageName, mInjector.getCallingUserId()); + } + + private boolean canUserAttemptToConfigureInteractAcrossProfiles( + String packageName, @UserIdInt int userId) { + final int[] profileIds = + mInjector.getUserManager().getProfileIds(userId, /* enabledOnly= */ false); if (profileIds.length < 2) { return false; } if (isProfileOwner(packageName, profileIds)) { return false; } - return hasRequestedAppOpPermission( - AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName) - && !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds); + if (!hasRequestedAppOpPermission( + AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)) { + return false; + } + return !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds); } private boolean isPlatformSignedAppWithNonUserConfigurablePermission( String packageName, int[] profileIds) { - return !isCrossProfilePackageWhitelistedByDefault(packageName) + return !isCrossProfilePackageAllowlistedByDefault(packageName) && isPlatformSignedAppWithAutomaticProfilesPermission(packageName, profileIds); } @@ -610,7 +619,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { if (uid == -1) { continue; } - if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_PROFILES, uid)) { + if (isPermissionGranted(INTERACT_ACROSS_PROFILES, uid)) { return true; } } @@ -642,7 +651,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { return; } final String op = - AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES); + AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES); setInteractAcrossProfilesAppOp(packageName, AppOpsManager.opToDefaultMode(op)); } @@ -650,7 +659,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { public void clearInteractAcrossProfilesAppOps() { final int defaultMode = AppOpsManager.opToDefaultMode( - AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES)); + AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES)); findAllPackageNames() .forEach(packageName -> setInteractAcrossProfilesAppOp(packageName, defaultMode)); } @@ -695,17 +704,13 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { } private boolean hasInteractAcrossProfilesPermission(String packageName, int uid, int pid) { - if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid) - || isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, uid)) { + if (isPermissionGranted(INTERACT_ACROSS_USERS_FULL, uid) + || isPermissionGranted(INTERACT_ACROSS_USERS, uid)) { return true; } return PermissionChecker.PERMISSION_GRANTED == PermissionChecker.checkPermissionForPreflight( - mContext, - Manifest.permission.INTERACT_ACROSS_PROFILES, - pid, - uid, - packageName); + mContext, INTERACT_ACROSS_PROFILES, pid, uid, packageName); } private boolean isProfileOwner(String packageName, int[] userIds) { @@ -898,5 +903,12 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { public List<UserHandle> getTargetUserProfiles(String packageName, int userId) { return getTargetUserProfilesUnchecked(packageName, userId); } + + @Override + public void setInteractAcrossProfilesAppOp( + String packageName, int newMode, @UserIdInt int userId) { + CrossProfileAppsServiceImpl.this.setInteractAcrossProfilesAppOpUnchecked( + packageName, newMode, userId); + } } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index ce3cdeab232a..b8a20ed4fe5b 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -125,6 +125,7 @@ import android.app.ActivityThread; import android.app.AlarmManager; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.app.AppOpsManager.Mode; import android.app.BroadcastOptions; import android.app.IActivityManager; import android.app.IActivityTaskManager; @@ -12816,6 +12817,28 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { public ComponentName getProfileOwnerAsUser(int userHandle) { return DevicePolicyManagerService.this.getProfileOwnerAsUser(userHandle); } + + @Override + public boolean supportsResetOp(int op) { + return op == AppOpsManager.OP_INTERACT_ACROSS_PROFILES + && LocalServices.getService(CrossProfileAppsInternal.class) != null; + } + + @Override + public void resetOp(int op, String packageName, @UserIdInt int userId) { + if (op != AppOpsManager.OP_INTERACT_ACROSS_PROFILES) { + throw new IllegalArgumentException("Unsupported op for DPM reset: " + op); + } + LocalServices.getService(CrossProfileAppsInternal.class) + .setInteractAcrossProfilesAppOp( + packageName, findInteractAcrossProfilesResetMode(packageName), userId); + } + + private @Mode int findInteractAcrossProfilesResetMode(String packageName) { + return getDefaultCrossProfilePackages().contains(packageName) + ? AppOpsManager.MODE_ALLOWED + : AppOpsManager.opToDefaultMode(AppOpsManager.OP_INTERACT_ACROSS_PROFILES); + } } private Intent createShowAdminSupportIntent(ComponentName admin, int userId) { diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java index 4b25890e5fdb..adf892aa12ab 100644 --- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java +++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java @@ -37,7 +37,6 @@ import android.annotation.UserIdInt; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; import android.app.AppOpsManager.Mode; -import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.ComponentName; import android.content.ContextWrapper; @@ -94,12 +93,15 @@ public class CrossProfileAppsServiceImplRoboTest { private static final int CALLING_PID = 1000; private static final String CROSS_PROFILE_APP_PACKAGE_NAME = "com.android.server.pm.crossprofileappsserviceimplrobotest.crossprofileapp"; - private static final int PERSONAL_PROFILE_USER_ID = 0; + @UserIdInt private static final int PERSONAL_PROFILE_USER_ID = 0; private static final int PERSONAL_PROFILE_UID = 2222; - private static final int WORK_PROFILE_USER_ID = 10; + @UserIdInt private static final int WORK_PROFILE_USER_ID = 10; private static final int WORK_PROFILE_UID = 3333; private static final int OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID = 20; - private static final int OUTSIDE_PROFILE_GROUP_USER_ID = 30; + @UserIdInt private static final int OTHER_PROFILE_GROUP_USER_ID = 30; + private static final int OTHER_PROFILE_GROUP_UID = 4444; + @UserIdInt private static final int OTHER_PROFILE_GROUP_2_USER_ID = 31; + private static final int OTHER_PROFILE_GROUP_2_UID = 5555; private final ContextWrapper mContext = ApplicationProvider.getApplicationContext(); private final UserManager mUserManager = mContext.getSystemService(UserManager.class); @@ -138,6 +140,10 @@ public class CrossProfileAppsServiceImplRoboTest { mockCrossProfileAppInstalledOnProfile( packageInfo, PERSONAL_PROFILE_USER_ID, PERSONAL_PROFILE_UID); mockCrossProfileAppInstalledOnProfile(packageInfo, WORK_PROFILE_USER_ID, WORK_PROFILE_UID); + mockCrossProfileAppInstalledOnProfile( + packageInfo, OTHER_PROFILE_GROUP_USER_ID, OTHER_PROFILE_GROUP_UID); + mockCrossProfileAppInstalledOnProfile( + packageInfo, OTHER_PROFILE_GROUP_2_USER_ID, OTHER_PROFILE_GROUP_2_UID); } private void mockCrossProfileAppInstalledOnProfile( @@ -200,16 +206,22 @@ public class CrossProfileAppsServiceImplRoboTest { @Before public void setUpCrossProfileAppUidsAndPackageNames() { + setUpCrossProfileAppUidAndPackageName( + PERSONAL_PROFILE_UID, PERSONAL_PROFILE_USER_ID); + setUpCrossProfileAppUidAndPackageName( + WORK_PROFILE_UID, WORK_PROFILE_USER_ID); + setUpCrossProfileAppUidAndPackageName( + OTHER_PROFILE_GROUP_UID, OTHER_PROFILE_GROUP_USER_ID); + setUpCrossProfileAppUidAndPackageName( + OTHER_PROFILE_GROUP_2_UID, OTHER_PROFILE_GROUP_2_USER_ID); + } + + private void setUpCrossProfileAppUidAndPackageName(int uid, @UserIdInt int userId) { ShadowApplicationPackageManager.setPackageUidAsUser( - CROSS_PROFILE_APP_PACKAGE_NAME, PERSONAL_PROFILE_UID, PERSONAL_PROFILE_USER_ID); - ShadowApplicationPackageManager.setPackageUidAsUser( - CROSS_PROFILE_APP_PACKAGE_NAME, WORK_PROFILE_UID, WORK_PROFILE_USER_ID); - when(mPackageManagerInternal.getPackageUidInternal( - CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, PERSONAL_PROFILE_USER_ID)) - .thenReturn(PERSONAL_PROFILE_UID); - when(mPackageManagerInternal.getPackageUidInternal( - CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, WORK_PROFILE_USER_ID)) - .thenReturn(WORK_PROFILE_UID); + CROSS_PROFILE_APP_PACKAGE_NAME, uid, userId); + when(mPackageManagerInternal + .getPackageUid(CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, userId)) + .thenReturn(uid); } @Before @@ -229,7 +241,9 @@ public class CrossProfileAppsServiceImplRoboTest { PERSONAL_PROFILE_USER_ID, WORK_PROFILE_USER_ID, OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID); - shadowUserManager.addProfileIds(OUTSIDE_PROFILE_GROUP_USER_ID); + shadowUserManager.addProfileIds( + OTHER_PROFILE_GROUP_USER_ID, + OTHER_PROFILE_GROUP_2_USER_ID); } @Before @@ -239,6 +253,8 @@ public class CrossProfileAppsServiceImplRoboTest { final int defaultMode = AppOpsManager.opToDefaultMode(OP_INTERACT_ACROSS_PROFILES); explicitlySetInteractAcrossProfilesAppOp(PERSONAL_PROFILE_UID, defaultMode); explicitlySetInteractAcrossProfilesAppOp(WORK_PROFILE_UID, defaultMode); + explicitlySetInteractAcrossProfilesAppOp(OTHER_PROFILE_GROUP_UID, defaultMode); + explicitlySetInteractAcrossProfilesAppOp(OTHER_PROFILE_GROUP_2_UID, defaultMode); } @Test @@ -422,6 +438,27 @@ public class CrossProfileAppsServiceImplRoboTest { } @Test + public void setInteractAcrossProfilesAppOp_userToSetInDifferentProfileGroupToCaller_setsAppOp() { + mCrossProfileAppsServiceImpl.getLocalService().setInteractAcrossProfilesAppOp( + CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED, OTHER_PROFILE_GROUP_USER_ID); + assertThat(getCrossProfileAppOp(OTHER_PROFILE_GROUP_UID)).isEqualTo(MODE_ALLOWED); + } + + @Test + public void setInteractAcrossProfilesAppOp_userToSetInDifferentProfileGroupToCaller_setsAppOpOnOtherProfile() { + mCrossProfileAppsServiceImpl.getLocalService().setInteractAcrossProfilesAppOp( + CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED, OTHER_PROFILE_GROUP_USER_ID); + assertThat(getCrossProfileAppOp(OTHER_PROFILE_GROUP_2_UID)).isEqualTo(MODE_ALLOWED); + } + + @Test + public void setInteractAcrossProfilesAppOp_userToSetInDifferentProfileGroupToCaller_doesNotSetCallerAppOp() { + mCrossProfileAppsServiceImpl.getLocalService().setInteractAcrossProfilesAppOp( + CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED, OTHER_PROFILE_GROUP_USER_ID); + assertThat(getCrossProfileAppOp()).isEqualTo(MODE_DEFAULT); + } + + @Test public void canConfigureInteractAcrossProfiles_packageNotInstalledInProfile_returnsFalse() { mockUninstallCrossProfileAppFromWorkProfile(); assertThat(mCrossProfileAppsServiceImpl @@ -530,7 +567,7 @@ public class CrossProfileAppsServiceImplRoboTest { @Test public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOutsideProfileGroup_returnsTrue() { - when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(OUTSIDE_PROFILE_GROUP_USER_ID)) + when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(OTHER_PROFILE_GROUP_USER_ID)) .thenReturn(buildCrossProfileComponentName()); assertThat(mCrossProfileAppsServiceImpl .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME)) @@ -601,8 +638,14 @@ public class CrossProfileAppsServiceImplRoboTest { private void mockCrossProfileAndroidPackage(AndroidPackage androidPackage) { when(mPackageManagerInternal.getPackage(CROSS_PROFILE_APP_PACKAGE_NAME)) .thenReturn(androidPackage); - when(mPackageManagerInternal.getPackage(PERSONAL_PROFILE_UID)).thenReturn(androidPackage); - when(mPackageManagerInternal.getPackage(WORK_PROFILE_UID)).thenReturn(androidPackage); + when(mPackageManagerInternal.getPackage(PERSONAL_PROFILE_UID)) + .thenReturn(androidPackage); + when(mPackageManagerInternal.getPackage(WORK_PROFILE_UID)) + .thenReturn(androidPackage); + when(mPackageManagerInternal.getPackage(OTHER_PROFILE_GROUP_UID)) + .thenReturn(androidPackage); + when(mPackageManagerInternal.getPackage(OTHER_PROFILE_GROUP_2_UID)) + .thenReturn(androidPackage); } private void mockCrossProfileAppNotWhitelisted() { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 3d51d7cf7af7..35e263036694 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1494,6 +1494,16 @@ public class TelephonyManager { public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4; /** + * Used as an int value for {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE} + * to indicate that default subscription for data/sms/voice is now determined, that + * it should dismiss any dialog or pop-ups that is asking user to select default sub. + * This is used when, for example, opportunistic subscription is configured. At that + * time the primary becomes default sub there's no need to ask user to select anymore. + * @hide + */ + public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS = 5; + + /** * Integer intent extra to be used with {@link #ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED} * to indicate if the SIM combination in DSDS has limitation or compatible issue. * e.g. two CDMA SIMs may disrupt each other's voice call in certain scenarios. |