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

Commit aeb0ed74 authored by Alexandra Gherghina's avatar Alexandra Gherghina Committed by Android (Google) Code Review
Browse files

Merge "Adds cross-profile intent filters for the Settings app"

parents 7f0a1c54 6e2ae259
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -1466,6 +1466,18 @@ final class ApplicationPackageManager extends PackageManager {
        }
    }

    /**
     * @hide
     */
    public void addCrossProfileIntentsForPackage(String packageName,
            int sourceUserId, int targetUserId) {
        try {
            mPM.addCrossProfileIntentsForPackage(packageName, sourceUserId, targetUserId);
        } catch (RemoteException e) {
            // Should never happen!
        }
    }

    /**
     * @hide
     */
+4 −1
Original line number Diff line number Diff line
@@ -251,6 +251,9 @@ interface IPackageManager {
    void addCrossProfileIntentFilter(in IntentFilter intentFilter, int sourceUserId, int targetUserId,
            int flags);

    void addCrossProfileIntentsForPackage(in String packageName, int sourceUserId,
            int targetUserId);

    void clearCrossProfileIntentFilters(int sourceUserId);

    /**
+8 −0
Original line number Diff line number Diff line
@@ -3610,4 +3610,12 @@ public abstract class PackageManager {
     * @hide
     */
    public abstract void clearCrossProfileIntentFilters(int sourceUserId);

    /**
     * Forwards all intents for {@link packageName} for user {@link sourceUserId} to user
     * {@link targetUserId}.
     * @hide
     */
    public abstract void addCrossProfileIntentsForPackage(String packageName,
            int sourceUserId, int targetUserId);
}
+106 −7
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@ import com.android.server.ServiceThread;
import com.android.server.Watchdog;
import com.android.server.pm.Settings.DatabaseVersion;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.storage.DeviceStorageMonitorInternal;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -91,7 +90,6 @@ import android.content.pm.ManifestDigest;
import android.content.pm.PackageCleanItem;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageInstallerParams;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser.ActivityIntentInfo;
import android.content.pm.PackageParser.PackageParserException;
@@ -3363,6 +3361,26 @@ public class PackageManagerService extends IPackageManager.Stub {
                if (matches.get(i).getTargetUserId() == targetUserId) return true;
            }
        }
        ArrayList<String> packageNames = null;
        SparseArray<ArrayList<String>> fromSource =
                mSettings.mCrossProfilePackageInfo.get(sourceUserId);
        if (fromSource != null) {
            packageNames = fromSource.get(targetUserId);
        }
        if (packageNames.contains(intent.getPackage())) {
            return true;
        }
        // We need the package name, so we try to resolve with the loosest flags possible
        List<ResolveInfo> resolveInfos = mActivities.queryIntent(
                intent, resolvedType, PackageManager.GET_UNINSTALLED_PACKAGES, targetUserId);
        int count = resolveInfos.size();
        for (int i = 0; i < count; i++) {
            ResolveInfo resolveInfo = resolveInfos.get(i);
            if (packageNames.contains(resolveInfo.activityInfo.packageName)) {
                return true;
            }
        }
        return false;
    }
@@ -3403,6 +3421,14 @@ public class PackageManagerService extends IPackageManager.Stub {
        synchronized (mPackages) {
            final String pkgName = intent.getPackage();
            if (pkgName == null) {
                //Check if the intent needs to be forwarded to another user for this package
                ArrayList<ResolveInfo> crossProfileResult =
                        queryIntentActivitiesCrossProfilePackage(
                                intent, resolvedType, flags, userId);
                if (!crossProfileResult.isEmpty()) {
                    // Skip the current profile
                    return crossProfileResult;
                }
                List<ResolveInfo> result;
                List<CrossProfileIntentFilter> matchingFilters =
                        getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
@@ -3426,6 +3452,13 @@ public class PackageManagerService extends IPackageManager.Stub {
            }
            final PackageParser.Package pkg = mPackages.get(pkgName);
            if (pkg != null) {
                ArrayList<ResolveInfo> crossProfileResult =
                        queryIntentActivitiesCrossProfilePackage(
                                intent, resolvedType, flags, userId, pkg, pkgName);
                if (!crossProfileResult.isEmpty()) {
                    // Skip the current profile
                    return crossProfileResult;
                }
                return mActivities.queryIntentForPackage(intent, resolvedType, flags,
                        pkg.activities, userId);
            }
@@ -3446,7 +3479,8 @@ public class PackageManagerService extends IPackageManager.Stub {
                    ResolveInfo resolveInfo = checkTargetCanHandle(filter, intent, resolvedType,
                            flags, sourceUserId);
                    if (resolveInfo != null) {
                        return createForwardingResolveInfo(filter, sourceUserId);
                        return createForwardingResolveInfo(
                                filter, sourceUserId, filter.getTargetUserId());
                    }
                }
            }
@@ -3454,6 +3488,56 @@ public class PackageManagerService extends IPackageManager.Stub {
        return null;
    }
    private ArrayList<ResolveInfo> queryIntentActivitiesCrossProfilePackage(
            Intent intent, String resolvedType, int flags, int userId) {
        ArrayList<ResolveInfo> matchingResolveInfos = new ArrayList<ResolveInfo>();
        SparseArray<ArrayList<String>> sourceForwardingInfo =
                mSettings.mCrossProfilePackageInfo.get(userId);
        if (sourceForwardingInfo != null) {
            int NI = sourceForwardingInfo.size();
            for (int i = 0; i < NI; i++) {
                int targetUserId = sourceForwardingInfo.keyAt(i);
                ArrayList<String> packageNames = sourceForwardingInfo.valueAt(i);
                List<ResolveInfo> resolveInfos = mActivities.queryIntent(
                        intent, resolvedType, flags, targetUserId);
                int NJ = resolveInfos.size();
                for (int j = 0; j < NJ; j++) {
                    ResolveInfo resolveInfo = resolveInfos.get(j);
                    if (packageNames.contains(resolveInfo.activityInfo.packageName)) {
                        matchingResolveInfos.add(createForwardingResolveInfo(
                                resolveInfo.filter, userId, targetUserId));
                    }
                }
            }
        }
        return matchingResolveInfos;
    }
    private ArrayList<ResolveInfo> queryIntentActivitiesCrossProfilePackage(
            Intent intent, String resolvedType, int flags, int userId, PackageParser.Package pkg,
            String packageName) {
        ArrayList<ResolveInfo> matchingResolveInfos = new ArrayList<ResolveInfo>();
        SparseArray<ArrayList<String>> sourceForwardingInfo =
                mSettings.mCrossProfilePackageInfo.get(userId);
        if (sourceForwardingInfo != null) {
            int NI = sourceForwardingInfo.size();
            for (int i = 0; i < NI; i++) {
                int targetUserId = sourceForwardingInfo.keyAt(i);
                if (sourceForwardingInfo.valueAt(i).contains(packageName)) {
                    List<ResolveInfo> resolveInfos = mActivities.queryIntentForPackage(
                            intent, resolvedType, flags, pkg.activities, targetUserId);
                    int NJ = resolveInfos.size();
                    for (int j = 0; j < NJ; j++) {
                        ResolveInfo resolveInfo = resolveInfos.get(j);
                        matchingResolveInfos.add(createForwardingResolveInfo(
                                resolveInfo.filter, userId, targetUserId));
                    }
                }
            }
        }
        return matchingResolveInfos;
    }
    // Return matching ResolveInfo if any for skip current profile intent filters.
    private ResolveInfo queryCrossProfileIntents(
            List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
@@ -3486,15 +3570,14 @@ public class PackageManagerService extends IPackageManager.Stub {
        List<ResolveInfo> resultTargetUser = mActivities.queryIntent(intent,
                resolvedType, flags, filter.getTargetUserId());
        if (resultTargetUser != null) {
            return createForwardingResolveInfo(filter, sourceUserId);
            return createForwardingResolveInfo(filter, sourceUserId, filter.getTargetUserId());
        }
        return null;
    }
    private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter,
            int sourceUserId) {
    private ResolveInfo createForwardingResolveInfo(IntentFilter filter,
            int sourceUserId, int targetUserId) {
        String className;
        int targetUserId = filter.getTargetUserId();
        if (targetUserId == UserHandle.USER_OWNER) {
            className = FORWARD_INTENT_TO_USER_OWNER;
        } else {
@@ -11604,6 +11687,22 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
    }
    public void addCrossProfileIntentsForPackage(String packageName,
            int sourceUserId, int targetUserId) {
        mContext.enforceCallingOrSelfPermission(
                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
        mSettings.addCrossProfilePackage(packageName, sourceUserId, targetUserId);
        mSettings.writePackageRestrictionsLPr(sourceUserId);
    }
    public void removeCrossProfileIntentsForPackage(String packageName,
            int sourceUserId, int targetUserId) {
        mContext.enforceCallingOrSelfPermission(
                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
        mSettings.removeCrossProfilePackage(packageName, sourceUserId, targetUserId);
        mSettings.writePackageRestrictionsLPr(sourceUserId);
    }
    @Override
    public void clearCrossProfileIntentFilters(int sourceUserId) {
        mContext.enforceCallingOrSelfPermission(
+144 −0
Original line number Diff line number Diff line
@@ -31,12 +31,14 @@ import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.PatternMatcher;
import android.util.LogPrinter;

import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.XmlUtils;
import com.android.server.pm.PackageManagerService.DumpState;

import java.util.Collection;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -134,6 +136,10 @@ final class Settings {
            "persistent-preferred-activities";
    static final String TAG_CROSS_PROFILE_INTENT_FILTERS =
            "crossProfile-intent-filters";
    private static final String TAG_CROSS_PROFILE_PACKAGE_INFO = "cross-profile-package-info";
    private static final String CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID = "target-user-id";
    private static final String CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME = "package-name";
    private static final String CROSS_PROFILE_PACKAGE_INFO_ATTR_PACKAGE_NAME = "value";
    //Old name. Kept for compatibility
    static final String TAG_FORWARDING_INTENT_FILTERS =
            "forwarding-intent-filters";
@@ -240,6 +246,11 @@ final class Settings {

    public final KeySetManager mKeySetManager = new KeySetManager(mPackages);

    // A mapping of (sourceUserId, targetUserId, packageNames) for forwarding the intents of a
    // package.
    final SparseArray<SparseArray<ArrayList<String>>>
            mCrossProfilePackageInfo = new SparseArray<SparseArray<ArrayList<String>>>();

    Settings(Context context) {
        this(context, Environment.getDataDirectory());
    }
@@ -262,6 +273,47 @@ final class Settings {
        mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
    }

    public void addCrossProfilePackage(
            String packageName, int sourceUserId, int targetUserId) {
        synchronized(mCrossProfilePackageInfo) {
            SparseArray<ArrayList<String>> sourceForwardingInfo =
                    mCrossProfilePackageInfo.get(sourceUserId);
            if (sourceForwardingInfo == null) {
                sourceForwardingInfo = new SparseArray<ArrayList<String>>();
                mCrossProfilePackageInfo.put(sourceUserId, sourceForwardingInfo);
            }
            ArrayList<String> packageNames = sourceForwardingInfo.get(targetUserId);
            if (packageNames == null) {
                packageNames = new ArrayList<String>();
                sourceForwardingInfo.put(targetUserId, packageNames);
            }
            if (!packageNames.contains(packageName)) {
                packageNames.add(packageName);
            }
        }
    }

    public void removeCrossProfilePackage(
            String packageName, int sourceUserId, int targetUserId) {
        synchronized(mCrossProfilePackageInfo) {
            SparseArray<ArrayList<String>> sourceForwardingInfo =
                    mCrossProfilePackageInfo.get(sourceUserId);
            if (sourceForwardingInfo == null) {
                return;
            }
            ArrayList<String> packageNames = sourceForwardingInfo.get(targetUserId);
            if (packageNames != null && packageNames.contains(packageName)) {
                packageNames.remove(packageName);
                if (packageNames.isEmpty()) {
                    sourceForwardingInfo.remove(targetUserId);
                    if (sourceForwardingInfo.size() == 0) {
                        mCrossProfilePackageInfo.remove(sourceUserId);
                    }
                }
            }
        }
    }

    PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
            String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
            String nativeLibraryPathString, String cpuAbiString, int pkgFlags, UserHandle user, boolean add) {
@@ -1005,6 +1057,68 @@ final class Settings {
        }
    }

    private void readCrossProfilePackageInfoLPw(XmlPullParser parser, int userId)
            throws XmlPullParserException, IOException {
        int outerDepth = parser.getDepth();
        int type;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                continue;
            }
            String tagName = parser.getName();
            if (tagName.equals(TAG_ITEM)) {
                String targetUserIdString = parser.getAttributeValue(null,
                        CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID);
                if (targetUserIdString == null) {
                    String msg = "Missing element under " + TAG +": "
                            + CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID + " at " +
                            parser.getPositionDescription();
                    PackageManagerService.reportSettingsProblem(Log.WARN, msg);
                    continue;
                }
                int targetUserId = Integer.parseInt(targetUserIdString);
                readCrossProfilePackageInfoForTargetLPw(parser, userId, targetUserId);
            } else {
                String msg = "Unknown element under " +  TAG_CROSS_PROFILE_PACKAGE_INFO + ": " +
                        parser.getName();
                PackageManagerService.reportSettingsProblem(Log.WARN, msg);
                XmlUtils.skipCurrentTag(parser);
            }
        }
    }

    private void readCrossProfilePackageInfoForTargetLPw(
            XmlPullParser parser, int sourceUserId, int targetUserId)
            throws XmlPullParserException, IOException {
        int outerDepth = parser.getDepth();
        int type;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                continue;
            }
            String tagName = parser.getName();
            if (tagName.equals(CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME)) {
                String packageName = parser.getAttributeValue(
                        null, CROSS_PROFILE_PACKAGE_INFO_ATTR_PACKAGE_NAME);
                if (packageName == null) {
                    String msg = "Missing element under " + TAG +": "
                            + CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME + " at " +
                            parser.getPositionDescription();
                    PackageManagerService.reportSettingsProblem(Log.WARN, msg);
                    continue;
                }
                addCrossProfilePackage(packageName, sourceUserId, targetUserId);
            } else {
                String msg = "Unknown element under " +  TAG_ITEM + ": " +
                        parser.getName();
                PackageManagerService.reportSettingsProblem(Log.WARN, msg);
                XmlUtils.skipCurrentTag(parser);
            }
        }
    }

    void readPackageRestrictionsLPr(int userId) {
        if (DEBUG_MU) {
            Log.i(TAG, "Reading package restrictions for user=" + userId);
@@ -1136,6 +1250,8 @@ final class Settings {
                } else if (tagName.equals(TAG_FORWARDING_INTENT_FILTERS)
                        || tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
                    readCrossProfileIntentFiltersLPw(parser, userId);
                } else if (tagName.equals(TAG_CROSS_PROFILE_PACKAGE_INFO)){
                    readCrossProfilePackageInfoLPw(parser, userId);
                } else {
                    Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
                          + parser.getName());
@@ -1227,6 +1343,32 @@ final class Settings {
        serializer.endTag(null, TAG_CROSS_PROFILE_INTENT_FILTERS);
    }

    void writeCrossProfilePackageInfoLPr(XmlSerializer serializer, int userId)
            throws IllegalArgumentException, IllegalStateException, IOException {
        SparseArray<ArrayList<String>> sourceForwardingInfo = mCrossProfilePackageInfo.get(userId);
        if (sourceForwardingInfo == null) {
            return;
        }
        serializer.startTag(null, TAG_CROSS_PROFILE_PACKAGE_INFO);
        int NI = sourceForwardingInfo.size();
        for (int i = 0; i < NI; i++) {
            int targetUserId = sourceForwardingInfo.keyAt(i);
            ArrayList<String> packageNames = sourceForwardingInfo.valueAt(i);
            serializer.startTag(null, TAG_ITEM);
            serializer.attribute(null, CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID,
                    Integer.toString(targetUserId));
            int NJ = packageNames.size();
            for (int j = 0; j < NJ; j++) {
                serializer.startTag(null, CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME);
                serializer.attribute(null, CROSS_PROFILE_PACKAGE_INFO_ATTR_PACKAGE_NAME,
                        packageNames.get(j));
                serializer.endTag(null, CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME);
            }
            serializer.endTag(null, TAG_ITEM);
        }
        serializer.endTag(null, TAG_CROSS_PROFILE_PACKAGE_INFO);
    }

    void writePackageRestrictionsLPr(int userId) {
        if (DEBUG_MU) {
            Log.i(TAG, "Writing package restrictions for user=" + userId);
@@ -1327,6 +1469,8 @@ final class Settings {

            writeCrossProfileIntentFiltersLPr(serializer, userId);

            writeCrossProfilePackageInfoLPr(serializer, userId);

            serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);

            serializer.endDocument();
Loading