Merge "Log cross-profile metrics"

This commit is contained in:
Alex Kershaw
2020-02-15 10:45:44 +00:00
committed by Android (Google) Code Review
2 changed files with 71 additions and 18 deletions

View File

@@ -68,7 +68,6 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
private Context mContext;
private Injector mInjector;
private AppOpsManager mAppOpsManager;
public CrossProfileAppsServiceImpl(Context context) {
this(context, new InjectorImpl(context));
@@ -217,19 +216,27 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
mInjector.getActivityTaskManagerInternal().startActivityAsUser(caller, callingPackage,
callingFeatureId, launchIntent, /* options= */ null, userId);
logStartActivityByIntent(callingPackage);
}
private void logStartActivityByIntent(String packageName) {
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.START_ACTIVITY_BY_INTENT)
.setStrings(packageName)
.setBoolean(isCallingUserAManagedProfile())
.write();
}
@Override
public boolean canRequestInteractAcrossProfiles(String callingPackage) {
Objects.requireNonNull(callingPackage);
verifyCallingPackage(callingPackage);
return canRequestInteractAcrossProfilesUnchecked(
callingPackage, mInjector.getCallingUserId());
return canRequestInteractAcrossProfilesUnchecked(callingPackage);
}
private boolean canRequestInteractAcrossProfilesUnchecked(
String packageName, @UserIdInt int userId) {
List<UserHandle> targetUserProfiles = getTargetUserProfilesUnchecked(packageName, userId);
private boolean canRequestInteractAcrossProfilesUnchecked(String packageName) {
List<UserHandle> targetUserProfiles =
getTargetUserProfilesUnchecked(packageName, mInjector.getCallingUserId());
if (targetUserProfiles.isEmpty()) {
return false;
}
@@ -256,12 +263,11 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
Objects.requireNonNull(callingPackage);
verifyCallingPackage(callingPackage);
final List<UserHandle> targetUserProfiles = getTargetUserProfilesUnchecked(callingPackage,
mInjector.getCallingUserId());
final List<UserHandle> targetUserProfiles = getTargetUserProfilesUnchecked(
callingPackage, mInjector.getCallingUserId());
if (targetUserProfiles.isEmpty()) {
return false;
}
return hasInteractAcrossProfilesPermission(callingPackage);
}
@@ -363,6 +369,12 @@ 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.
*/
@Override
public void setInteractAcrossProfilesAppOp(String packageName, @Mode int newMode) {
final int callingUid = mInjector.getCallingUid();
@@ -379,6 +391,11 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
"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);
}
private void setInteractAcrossProfilesAppOpUnchecked(
String packageName, @Mode int newMode, boolean logMetrics) {
if (newMode == AppOpsManager.MODE_ALLOWED
&& !canConfigureInteractAcrossProfiles(packageName)) {
// The user should not be prompted for apps that cannot request to interact across
@@ -394,7 +411,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
if (!isPackageInstalled(packageName, profileId)) {
continue;
}
setInteractAcrossProfilesAppOpForUser(packageName, newMode, profileId);
setInteractAcrossProfilesAppOpForUser(packageName, newMode, profileId, logMetrics);
}
}
@@ -413,16 +430,16 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
}
private void setInteractAcrossProfilesAppOpForUser(
String packageName, @Mode int newMode, @UserIdInt int userId) {
String packageName, @Mode int newMode, @UserIdInt int userId, boolean logMetrics) {
try {
setInteractAcrossProfilesAppOpForUserOrThrow(packageName, newMode, userId);
setInteractAcrossProfilesAppOpForUserOrThrow(packageName, newMode, userId, logMetrics);
} catch (PackageManager.NameNotFoundException e) {
Slog.e(TAG, "Missing package " + packageName + " on user ID " + userId, e);
}
}
private void setInteractAcrossProfilesAppOpForUserOrThrow(
String packageName, @Mode int newMode, @UserIdInt int userId)
String packageName, @Mode int newMode, @UserIdInt int userId, boolean logMetrics)
throws PackageManager.NameNotFoundException {
final int uid = mInjector.getPackageManager()
.getPackageUidAsUser(packageName, /* flags= */ 0, userId);
@@ -444,6 +461,28 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
.setMode(OP_INTERACT_ACROSS_PROFILES, uid, packageName, newMode);
}
sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(userId));
maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, userId, logMetrics, uid);
}
private void maybeLogSetInteractAcrossProfilesAppOp(
String packageName,
@Mode int newMode,
@UserIdInt int userId,
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)
.setInt(newMode)
.setBoolean(appDeclaresCrossProfileAttribute(uid))
.write();
}
/**
@@ -541,11 +580,13 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
permission, uid, /* owningUid= */-1, /* exported= */ true);
}
private AppOpsManager getAppOpsManager() {
if (mAppOpsManager == null) {
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
}
return mAppOpsManager;
private boolean isCallingUserAManagedProfile() {
return isManagedProfile(mInjector.getCallingUserId());
}
private boolean isManagedProfile(@UserIdInt int userId) {
return mInjector.withCleanCallingIdentity(()
-> mContext.getSystemService(UserManager.class).isManagedProfile(userId));
}
private static class InjectorImpl implements Injector {

View File

@@ -15230,15 +15230,27 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final ActiveAdmin admin =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
previousCrossProfilePackages = admin.mCrossProfilePackages;
if (packageNames.equals(previousCrossProfilePackages)) {
return;
}
admin.mCrossProfilePackages = packageNames;
saveSettingsLocked(mInjector.userHandleGetCallingUserId());
}
logSetCrossProfilePackages(who, packageNames);
final CrossProfileApps crossProfileApps = mContext.getSystemService(CrossProfileApps.class);
mInjector.binderWithCleanCallingIdentity(
() -> crossProfileApps.resetInteractAcrossProfilesAppOps(
previousCrossProfilePackages, new HashSet<>(packageNames)));
}
private void logSetCrossProfilePackages(ComponentName who, List<String> packageNames) {
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_CROSS_PROFILE_PACKAGES)
.setAdmin(who)
.setStrings(packageNames.toArray(new String[packageNames.size()]))
.write();
}
@Override
public List<String> getCrossProfilePackages(ComponentName who) {
if (!mHasFeature) {