summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/admin/DevicePolicyManagerInternal.java12
-rw-r--r--core/java/android/content/pm/CrossProfileAppsInternal.java11
-rw-r--r--core/java/android/net/ConnectivityManager.java4
-rw-r--r--core/proto/android/stats/mediametrics/mediametrics.proto13
-rw-r--r--media/jni/android_media_MediaExtractor.cpp2
-rw-r--r--packages/CarSystemUI/res/values-uz/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java60
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java4
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java33
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkNotificationManager.java8
-rw-r--r--services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java160
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java23
-rw-r--r--services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java77
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java10
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.