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

Commit 1ab58c3b authored by Alex Johnston's avatar Alex Johnston
Browse files

Non-system camera PPA set by DPC

Background
ag/10760163 introduced a change which requires
camera intents to match system apps only.
As a result, the DPC will no longer have the
aility to control the camera PPA.

This CL gives the DPC the ability to set a
camera PPA, by adding a new field isSetByDPM
to the PersistentPreferredActivity. If this
field is set, the camera intent does not have to
match a system app.

Changes
* Added isSetByDPM to PersistentPreferredActivity
* Added helper method in PackageManagerService to
  check if an intent is an image capture intent
  and not set by the DPC
* updated the is isImplicitImageCaptureIntentAndNotSetByDpc
  parameter to updateFlagsForResolve() in
  PackageManagerService

Bug: 153921883
Test: atest com.android.server.pm.PackageManagerServiceTest
      atest com.android.cts.devicepolicy.MixedDeviceOwnerTest#testPersistentIntentResolving
      atest com.android.cts.devicepolicy.MixedProfileOwnerTest#testPersistentIntentResolving
      atest com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testPersistentIntentResolving
Change-Id: I667a7e613b76514ecc1d814393d173c2987ca0b6
parent 09aa3bc4
Loading
Loading
Loading
Loading
+57 −15
Original line number Diff line number Diff line
@@ -5264,15 +5264,17 @@ public class PackageManagerService extends IPackageManager.Stub
     * </ul>
     */
    int updateFlagsForResolve(int flags, int userId, int callingUid, boolean wantInstantApps,
            boolean matchSystemOnly) {
            boolean isImplicitImageCaptureIntentAndNotSetByDpc) {
        return updateFlagsForResolve(flags, userId, callingUid,
                wantInstantApps, matchSystemOnly, false /*onlyExposedExplicitly*/);
                wantInstantApps, false /*onlyExposedExplicitly*/,
                isImplicitImageCaptureIntentAndNotSetByDpc);
    }
    int updateFlagsForResolve(int flags, int userId, int callingUid,
            boolean wantInstantApps, boolean onlyExposedExplicitly, boolean matchSystemOnly) {
            boolean wantInstantApps, boolean onlyExposedExplicitly,
            boolean isImplicitImageCaptureIntentAndNotSetByDpc) {
        // Safe mode means we shouldn't match any third-party components
        if (mSafeMode || matchSystemOnly) {
        if (mSafeMode || isImplicitImageCaptureIntentAndNotSetByDpc) {
            flags |= PackageManager.MATCH_SYSTEM_ONLY;
        }
        if (getInstantAppPackageName(callingUid) != null) {
@@ -6400,7 +6402,8 @@ public class PackageManagerService extends IPackageManager.Stub
            if (!mUserManager.exists(userId)) return null;
            final int callingUid = Binder.getCallingUid();
            flags = updateFlagsForResolve(flags, userId, filterCallingUid, resolveForStart,
                    intent.isImplicitImageCaptureIntent() /*matchSystemOnly*/);
                    isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
                            flags));
            mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                    false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
@@ -6438,7 +6441,7 @@ public class PackageManagerService extends IPackageManager.Stub
        final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
        final int flags = updateFlagsForResolve(
                0, userId, callingUid, false /*includeInstantApps*/,
                intent.isImplicitImageCaptureIntent() /*matchSystemOnly*/);
                isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType, 0));
        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
                userId);
        synchronized (mLock) {
@@ -6684,6 +6687,40 @@ public class PackageManagerService extends IPackageManager.Stub
        return true;
    }
    /**
     * From Android R, camera intents have to match system apps. The only exception to this is if
     * the DPC has set the camera persistent preferred activity. This case was introduced
     * because it is important that the DPC has the ability to set both system and non-system
     * camera persistent preferred activities.
     *
     * @return {@code true} if the intent is a camera intent and the persistent preferred
     * activity was not set by the DPC.
     */
    @GuardedBy("mLock")
    private boolean isImplicitImageCaptureIntentAndNotSetByDpcLocked(Intent intent, int userId,
            String resolvedType, int flags) {
        return intent.isImplicitImageCaptureIntent() && !isPersistentPreferredActivitySetByDpm(
                intent, userId, resolvedType, flags);
    }
    private boolean isPersistentPreferredActivitySetByDpm(Intent intent, int userId,
            String resolvedType, int flags) {
        PersistentPreferredIntentResolver ppir = mSettings.mPersistentPreferredActivities
                .get(userId);
        //TODO(b/158003772): Remove double query
        List<PersistentPreferredActivity> pprefs = ppir != null
                ? ppir.queryIntent(intent, resolvedType,
                (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
                userId)
                : new ArrayList<>();
        for (PersistentPreferredActivity ppa : pprefs) {
            if (ppa.mIsSetByDpm) {
                return true;
            }
        }
        return false;
    }
    @GuardedBy("mLock")
    private ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType,
            int flags, List<ResolveInfo> query, boolean debug, int userId) {
@@ -6767,7 +6804,8 @@ public class PackageManagerService extends IPackageManager.Stub
                        android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 1;
        flags = updateFlagsForResolve(
                flags, userId, callingUid, false /*includeInstantApps*/,
                intent.isImplicitImageCaptureIntent() /*matchSystemOnly*/);
                isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
                        flags));
        intent = updateIntentForResolve(intent);
        // writer
        synchronized (mLock) {
@@ -6980,7 +7018,8 @@ public class PackageManagerService extends IPackageManager.Stub
            synchronized (mLock) {
                int flags = updateFlagsForResolve(0, parent.id, callingUid,
                        false /*includeInstantApps*/,
                        intent.isImplicitImageCaptureIntent() /*matchSystemOnly*/);
                        isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, parent.id,
                                resolvedType, 0));
                CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr(
                        intent, resolvedType, flags, sourceUserId, parent.id);
                return xpDomainInfo != null;
@@ -7067,7 +7106,8 @@ public class PackageManagerService extends IPackageManager.Stub
        flags = updateFlagsForResolve(flags, userId, filterCallingUid, resolveForStart,
                comp != null || pkgName != null /*onlyExposedExplicitly*/,
                intent.isImplicitImageCaptureIntent() /*matchSystemOnly*/);
                isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
                        flags));
        if (comp != null) {
            final List<ResolveInfo> list = new ArrayList<>(1);
            final ActivityInfo ai = getActivityInfo(comp, flags, userId);
@@ -7856,7 +7896,8 @@ public class PackageManagerService extends IPackageManager.Stub
        if (!mUserManager.exists(userId)) return Collections.emptyList();
        final int callingUid = Binder.getCallingUid();
        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
                intent.isImplicitImageCaptureIntent() /*matchSystemOnly*/);
                isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
                        flags));
        mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                false /*requireFullPermission*/, false /*checkShell*/,
                "query intent activity options");
@@ -8043,7 +8084,8 @@ public class PackageManagerService extends IPackageManager.Stub
                "query intent receivers");
        final String instantAppPkgName = getInstantAppPackageName(callingUid);
        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
                intent.isImplicitImageCaptureIntent() /*matchSystemOnly*/);
                isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
                        flags));
        ComponentName comp = intent.getComponent();
        if (comp == null) {
            if (intent.getSelector() != null) {
@@ -8134,7 +8176,7 @@ public class PackageManagerService extends IPackageManager.Stub
            int userId, int callingUid) {
        if (!mUserManager.exists(userId)) return null;
        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
                false /* matchSystemOnly */);
                false /* isImplicitImageCaptureIntentAndNotSetByDpc */);
        List<ResolveInfo> query = queryIntentServicesInternal(
                intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/);
        if (query != null) {
@@ -8166,7 +8208,7 @@ public class PackageManagerService extends IPackageManager.Stub
                "query intent receivers");
        final String instantAppPkgName = getInstantAppPackageName(callingUid);
        flags = updateFlagsForResolve(flags, userId, callingUid, includeInstantApps,
                false /* matchSystemOnly */);
                false /* isImplicitImageCaptureIntentAndNotSetByDpc */);
        ComponentName comp = intent.getComponent();
        if (comp == null) {
            if (intent.getSelector() != null) {
@@ -8304,7 +8346,7 @@ public class PackageManagerService extends IPackageManager.Stub
        final int callingUid = Binder.getCallingUid();
        final String instantAppPkgName = getInstantAppPackageName(callingUid);
        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
                false /* matchSystemOnly */);
                false /* isImplicitImageCaptureIntentAndNotSetByDpc */);
        ComponentName comp = intent.getComponent();
        if (comp == null) {
            if (intent.getSelector() != null) {
@@ -19839,7 +19881,7 @@ public class PackageManagerService extends IPackageManager.Stub
        }
        synchronized (mLock) {
            mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter(
                    new PersistentPreferredActivity(filter, activity));
                    new PersistentPreferredActivity(filter, activity, true));
            scheduleWritePackageRestrictionsLocked(userId);
        }
        updateDefaultHomeNotLocked(userId);
+13 −6
Original line number Diff line number Diff line
@@ -16,31 +16,34 @@

package com.android.server.pm;

import android.content.ComponentName;
import android.content.IntentFilter;
import android.util.Log;

import com.android.internal.util.XmlUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import android.content.ComponentName;
import android.content.IntentFilter;
import android.util.Log;

import java.io.IOException;

class PersistentPreferredActivity extends IntentFilter {
    private static final String ATTR_NAME = "name"; // component name
    private static final String ATTR_FILTER = "filter"; // filter
    private static final String ATTR_SET_BY_DPM = "set-by-dpm"; // set by DPM

    private static final String TAG = "PersistentPreferredActivity";

    private static final boolean DEBUG_FILTERS = false;

    final ComponentName mComponent;
    final boolean mIsSetByDpm;

    PersistentPreferredActivity(IntentFilter filter, ComponentName activity) {
    PersistentPreferredActivity(IntentFilter filter, ComponentName activity, boolean isSetByDpm) {
        super(filter);
        mComponent = activity;
        mIsSetByDpm = isSetByDpm;
    }

    PersistentPreferredActivity(XmlPullParser parser) throws XmlPullParserException, IOException {
@@ -52,6 +55,8 @@ class PersistentPreferredActivity extends IntentFilter {
                            "Bad activity name " + shortComponent +
                            " at " + parser.getPositionDescription());
        }
        mIsSetByDpm = Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_SET_BY_DPM));

        int outerDepth = parser.getDepth();
        String tagName = parser.getName();
        int type;
@@ -83,6 +88,7 @@ class PersistentPreferredActivity extends IntentFilter {

    public void writeToXml(XmlSerializer serializer) throws IOException {
        serializer.attribute(null, ATTR_NAME, mComponent.flattenToShortString());
        serializer.attribute(null, ATTR_SET_BY_DPM, Boolean.toString(mIsSetByDpm));
        serializer.startTag(null, ATTR_FILTER);
            super.writeToXml(serializer);
        serializer.endTag(null, ATTR_FILTER);
@@ -91,6 +97,7 @@ class PersistentPreferredActivity extends IntentFilter {
    @Override
    public String toString() {
        return "PersistentPreferredActivity{0x" + Integer.toHexString(System.identityHashCode(this))
                + " " + mComponent.flattenToShortString() + "}";
                + " " + mComponent.flattenToShortString()
                + ", mIsSetByDpm=" + mIsSetByDpm + "}";
    }
}