Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 747d05fb authored by Alex Kershaw's avatar Alex Kershaw Committed by Android (Google) Code Review
Browse files

Merge "Log cross-profile metrics"

parents 68c55ddb 7f7195bf
Loading
Loading
Loading
Loading
+59 −18
Original line number Diff line number Diff line
@@ -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);
    private boolean isCallingUserAManagedProfile() {
        return isManagedProfile(mInjector.getCallingUserId());
    }
        return mAppOpsManager;

    private boolean isManagedProfile(@UserIdInt int userId) {
        return mInjector.withCleanCallingIdentity(()
                -> mContext.getSystemService(UserManager.class).isManagedProfile(userId));
    }

    private static class InjectorImpl implements Injector {
+12 −0
Original line number Diff line number Diff line
@@ -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) {