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

Commit 6d2268a5 authored by Christopher Tate's avatar Christopher Tate Committed by Android (Google) Code Review
Browse files

Merge "Back up / restore default app and intent filter verification state" into mnc-dev

parents 0c5c8570 6038d15c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -282,6 +282,10 @@ interface IPackageManager {
     */
    byte[] getPreferredActivityBackup(int userId);
    void restorePreferredActivities(in byte[] backup, int userId);
    byte[] getDefaultAppsBackup(int userId);
    void restoreDefaultApps(in byte[] backup, int userId);
    byte[] getIntentFilterVerificationBackup(int userId);
    void restoreIntentFilterVerification(in byte[] backup, int userId);

    /**
     * Report the set of 'Home' activity candidates, plus (if any) which of them
+46 −25
Original line number Diff line number Diff line
@@ -27,48 +27,69 @@ public class PreferredActivityBackupHelper extends BlobBackupHelper {
    private static final boolean DEBUG = false;

    // current schema of the backup state blob
    private static final int STATE_VERSION = 2;
    private static final int STATE_VERSION = 3;

    // key under which the preferred-activity state blob is committed to backup
    private static final String KEY_PREFERRED = "preferred-activity";

    // key for default-browser [etc] state
    private static final String KEY_DEFAULT_APPS = "default-apps";

    // intent-filter verification state
    private static final String KEY_INTENT_VERIFICATION = "intent-verification";

    public PreferredActivityBackupHelper() {
        super(STATE_VERSION, KEY_PREFERRED);
        super(STATE_VERSION,
                KEY_PREFERRED,
                KEY_DEFAULT_APPS,
                KEY_INTENT_VERIFICATION);
    }

    @Override
    protected byte[] getBackupPayload(String key) {
        if (KEY_PREFERRED.equals(key)) {
        IPackageManager pm = AppGlobals.getPackageManager();
        if (DEBUG) {
                Slog.v(TAG, "Checking whether to back up");
            Slog.d(TAG, "Handling backup of " + key);
        }
            IPackageManager pm = AppGlobals.getPackageManager();
        try {
            switch (key) {
                case KEY_PREFERRED:
                    return pm.getPreferredActivityBackup(UserHandle.USER_OWNER);
            } catch (Exception e) {
                Slog.e(TAG, "Unable to store backup payload", e);
                // fall through to report null state
            }
        } else {
                case KEY_DEFAULT_APPS:
                    return pm.getDefaultAppsBackup(UserHandle.USER_OWNER);
                case KEY_INTENT_VERIFICATION:
                    return pm.getIntentFilterVerificationBackup(UserHandle.USER_OWNER);
                default:
                    Slog.w(TAG, "Unexpected backup key " + key);
            }
        } catch (Exception e) {
            Slog.e(TAG, "Unable to store payload " + key);
        }
        return null;
    }

    @Override
    protected void applyRestoredPayload(String key, byte[] payload) {
        if (KEY_PREFERRED.equals(key)) {
        IPackageManager pm = AppGlobals.getPackageManager();
        if (DEBUG) {
                Slog.v(TAG, "Restoring");
            Slog.d(TAG, "Handling restore of " + key);
        }
            IPackageManager pm = AppGlobals.getPackageManager();
        try {
            switch (key) {
                case KEY_PREFERRED:
                    pm.restorePreferredActivities(payload, UserHandle.USER_OWNER);
            } catch (Exception e) {
                Slog.e(TAG, "Unable to restore", e);
            }
        } else {
                    break;
                case KEY_DEFAULT_APPS:
                    pm.restoreDefaultApps(payload, UserHandle.USER_OWNER);
                    break;
                case KEY_INTENT_VERIFICATION:
                    pm.restoreIntentFilterVerification(payload, UserHandle.USER_OWNER);
                    break;
                default:
                    Slog.w(TAG, "Unexpected restore key " + key);
            }
        } catch (Exception e) {
            Slog.w(TAG, "Unable to restore key " + key);
        }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package com.android.server.pm;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;

import java.util.ArrayList;

@@ -113,7 +113,7 @@ public class IntentFilterVerificationState {
            setState(state);
            return true;
        }
        Log.d(TAG, "Cannot set verifier response with callerUid:" + callerUid + " and code:" +
        Slog.d(TAG, "Cannot set verifier response with callerUid:" + callerUid + " and code:" +
                code + " as required verifierUid is:" + mRequiredVerifierUid);
        return false;
    }
+216 −48
Original line number Diff line number Diff line
@@ -212,6 +212,7 @@ import com.android.server.pm.PermissionsState.PermissionState;
import com.android.server.storage.DeviceStorageMonitorInternal;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.BufferedInputStream;
@@ -556,6 +557,22 @@ public class PackageManagerService extends IPackageManager.Stub {
    final DefaultPermissionGrantPolicy mDefaultPermissionPolicy =
            new DefaultPermissionGrantPolicy(this);
    private static class IFVerificationParams {
        PackageParser.Package pkg;
        boolean replacing;
        int userId;
        int verifierUid;
        public IFVerificationParams(PackageParser.Package _pkg, boolean _replacing,
                int _userId, int _verifierUid) {
            pkg = _pkg;
            replacing = _replacing;
            userId = _userId;
            replacing = _replacing;
            verifierUid = _verifierUid;
        }
    }
    private interface IntentFilterVerifier<T extends IntentFilter> {
        boolean addOneIntentFilterVerification(int verifierId, int userId, int verificationId,
                                               T filter, String packageName);
@@ -629,7 +646,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            UserHandle user = new UserHandle(userId);
            mContext.sendBroadcastAsUser(verificationIntent, user);
            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                    "Sending IntenFilter verification broadcast");
                    "Sending IntentFilter verification broadcast");
        }
        public void receiveVerificationResponse(int verificationId) {
@@ -639,6 +656,10 @@ public class PackageManagerService extends IPackageManager.Stub {
            ArrayList<PackageParser.ActivityIntentInfo> filters = ivs.getFilters();
            final int count = filters.size();
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.i(TAG, "Received verification response " + verificationId
                        + " for " + count + " filters, verified=" + verified);
            }
            for (int n=0; n<count; n++) {
                PackageParser.ActivityIntentInfo filter = filters.get(n);
                filter.setVerified(verified);
@@ -713,30 +734,27 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
        @Override
        public boolean addOneIntentFilterVerification(int verifierId, int userId, int verificationId,
        public boolean addOneIntentFilterVerification(int verifierUid, int userId, int verificationId,
                    ActivityIntentInfo filter, String packageName) {
            if (!(filter.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
                    filter.hasDataScheme(IntentFilter.SCHEME_HTTPS))) {
                if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                        "IntentFilter does not contain HTTP nor HTTPS data scheme");
            if (!hasValidDomains(filter)) {
                return false;
            }
            IntentFilterVerificationState ivs = mIntentFilterVerificationStates.get(verificationId);
            if (ivs == null) {
                ivs = createDomainVerificationState(verifierId, userId, verificationId,
                ivs = createDomainVerificationState(verifierUid, userId, verificationId,
                        packageName);
            }
            if (!hasValidDomains(filter)) {
                return false;
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.d(TAG, "Adding verification filter for " + packageName + " : " + filter);
            }
            ivs.addFilter(filter);
            return true;
        }
        private IntentFilterVerificationState createDomainVerificationState(int verifierId,
        private IntentFilterVerificationState createDomainVerificationState(int verifierUid,
                int userId, int verificationId, String packageName) {
            IntentFilterVerificationState ivs = new IntentFilterVerificationState(
                    verifierId, userId, packageName);
                    verifierUid, userId, packageName);
            ivs.setPendingState();
            synchronized (mPackages) {
                mIntentFilterVerificationStates.append(verificationId, ivs);
@@ -888,8 +906,10 @@ public class PackageManagerService extends IPackageManager.Stub {
    final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
    int mNextInstallToken = 1;  // nonzero; will be wrapped back to 1 when ++ overflows
    // backup/restore of preferred activity state
    // XML tags for backup/restore of various bits of state
    private static final String TAG_PREFERRED_BACKUP = "pa";
    private static final String TAG_DEFAULT_APPS = "da";
    private static final String TAG_INTENT_FILTER_VERIFICATION = "iv";
    private final String mRequiredVerifierPackage;
@@ -1507,11 +1527,9 @@ public class PackageManagerService extends IPackageManager.Stub {
                    break;
                }
                case START_INTENT_FILTER_VERIFICATIONS: {
                    int userId = msg.arg1;
                    int verifierUid = msg.arg2;
                    PackageParser.Package pkg = (PackageParser.Package)msg.obj;
                    verifyIntentFiltersIfNeeded(userId, verifierUid, pkg);
                    IFVerificationParams params = (IFVerificationParams) msg.obj;
                    verifyIntentFiltersIfNeeded(params.userId, params.verifierUid,
                            params.replacing, params.pkg);
                    break;
                }
                case INTENT_FILTER_VERIFIED: {
@@ -2357,8 +2375,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        final String packageName = getDefaultBrowserPackageName(myUserId);
        PackageInfo info = getPackageInfo(packageName, 0, myUserId);
        if (info == null) {
            Slog.w(TAG, "Clearing default Browser as its package is no more installed: " +
                    packageName);
            Slog.w(TAG, "Default browser no longer installed: " + packageName);
            setDefaultBrowserPackageName(null, myUserId);
        }
    }
@@ -11863,7 +11880,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            return;
        }
        startIntentFilterVerifications(args.user.getIdentifier(), pkg);
        startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);
        if (replace) {
            replacePackageLI(pkg, parseFlags, scanFlags, args.user,
@@ -11880,7 +11897,8 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
    }
    private void startIntentFilterVerifications(int userId, PackageParser.Package pkg) {
    private void startIntentFilterVerifications(int userId, boolean replacing,
            PackageParser.Package pkg) {
        if (mIntentFilterVerifierComponent == null) {
            Slog.w(TAG, "No IntentFilter verification will not be done as "
                    + "there is no IntentFilterVerifier available!");
@@ -11893,14 +11911,11 @@ public class PackageManagerService extends IPackageManager.Stub {
        mHandler.removeMessages(START_INTENT_FILTER_VERIFICATIONS);
        final Message msg = mHandler.obtainMessage(START_INTENT_FILTER_VERIFICATIONS);
        msg.obj = pkg;
        msg.arg1 = userId;
        msg.arg2 = verifierUid;
        msg.obj = new IFVerificationParams(pkg, replacing, userId, verifierUid);
        mHandler.sendMessage(msg);
    }
    private void verifyIntentFiltersIfNeeded(int userId, int verifierUid,
    private void verifyIntentFiltersIfNeeded(int userId, int verifierUid, boolean replacing,
            PackageParser.Package pkg) {
        int size = pkg.activities.size();
        if (size == 0) {
@@ -11920,13 +11935,26 @@ public class PackageManagerService extends IPackageManager.Stub {
                + " if any IntentFilter from the " + size
                + " Activities needs verification ...");
        final int verificationId = mIntentFilterVerificationToken++;
        int count = 0;
        final String packageName = pkg.packageName;
        boolean needToVerify = false;
        synchronized (mPackages) {
            // If this is a new install and we see that we've already run verification for this
            // package, we have nothing to do: it means the state was restored from backup.
            if (!replacing) {
                IntentFilterVerificationInfo ivi =
                        mSettings.getIntentFilterVerificationLPr(packageName);
                if (ivi != null) {
                    if (DEBUG_DOMAIN_VERIFICATION) {
                        Slog.i(TAG, "Package " + packageName+ " already verified: status="
                                + ivi.getStatusString());
                    }
                    return;
                }
            }
            // If any filters need to be verified, then all need to be.
            boolean needToVerify = false;
            for (PackageParser.Activity a : pkg.activities) {
                for (ActivityIntentInfo filter : a.intents) {
                    if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) {
@@ -11938,7 +11966,9 @@ public class PackageManagerService extends IPackageManager.Stub {
                    }
                }
            }
            if (needToVerify) {
                final int verificationId = mIntentFilterVerificationToken++;
                for (PackageParser.Activity a : pkg.activities) {
                    for (ActivityIntentInfo filter : a.intents) {
                        boolean needsFilterVerification = filter.hasWebDataURI();
@@ -13377,10 +13407,46 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
    }
    /**
     * Common machinery for picking apart a restored XML blob and passing
     * it to a caller-supplied functor to be applied to the running system.
     */
    private void restoreFromXml(XmlPullParser parser, int userId,
            String expectedStartTag, BlobXmlRestorer functor)
            throws IOException, XmlPullParserException {
        int type;
        while ((type = parser.next()) != XmlPullParser.START_TAG
                && type != XmlPullParser.END_DOCUMENT) {
        }
        if (type != XmlPullParser.START_TAG) {
            // oops didn't find a start tag?!
            if (DEBUG_BACKUP) {
                Slog.e(TAG, "Didn't find start tag during restore");
            }
            return;
        }
        // this is supposed to be TAG_PREFERRED_BACKUP
        if (!expectedStartTag.equals(parser.getName())) {
            if (DEBUG_BACKUP) {
                Slog.e(TAG, "Found unexpected tag " + parser.getName());
            }
            return;
        }
        // skip interfering stuff, then we're aligned with the backing implementation
        while ((type = parser.next()) == XmlPullParser.TEXT) { }
        functor.apply(parser, userId);
    }
    private interface BlobXmlRestorer {
        public void apply(XmlPullParser parser, int userId) throws IOException, XmlPullParserException;
    }
    /**
     * Non-Binder method, support for the backup/restore mechanism: write the
     * full set of preferred activities in its canonical XML format.  Returns true
     * on success; false otherwise.
     * full set of preferred activities in its canonical XML format.  Returns the
     * XML output as a byte array, or null if there is none.
     */
    @Override
    public byte[] getPreferredActivityBackup(int userId) {
@@ -13421,32 +13487,134 @@ public class PackageManagerService extends IPackageManager.Stub {
        try {
            final XmlPullParser parser = Xml.newPullParser();
            parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name());
            restoreFromXml(parser, userId, TAG_PREFERRED_BACKUP,
                    new BlobXmlRestorer() {
                        @Override
                        public void apply(XmlPullParser parser, int userId)
                                throws XmlPullParserException, IOException {
                            synchronized (mPackages) {
                                mSettings.readPreferredActivitiesLPw(parser, userId);
                            }
                        }
                    } );
        } catch (Exception e) {
            if (DEBUG_BACKUP) {
                Slog.e(TAG, "Exception restoring preferred activities: " + e.getMessage());
            }
        }
    }
            int type;
            while ((type = parser.next()) != XmlPullParser.START_TAG
                    && type != XmlPullParser.END_DOCUMENT) {
    /**
     * Non-Binder method, support for the backup/restore mechanism: write the
     * default browser (etc) settings in its canonical XML format.  Returns the default
     * browser XML representation as a byte array, or null if there is none.
     */
    @Override
    public byte[] getDefaultAppsBackup(int userId) {
        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
            throw new SecurityException("Only the system may call getDefaultAppsBackup()");
        }
            if (type != XmlPullParser.START_TAG) {
                // oops didn't find a start tag?!
        ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
        try {
            final XmlSerializer serializer = new FastXmlSerializer();
            serializer.setOutput(dataStream, StandardCharsets.UTF_8.name());
            serializer.startDocument(null, true);
            serializer.startTag(null, TAG_DEFAULT_APPS);
            synchronized (mPackages) {
                mSettings.writeDefaultAppsLPr(serializer, userId);
            }
            serializer.endTag(null, TAG_DEFAULT_APPS);
            serializer.endDocument();
            serializer.flush();
        } catch (Exception e) {
            if (DEBUG_BACKUP) {
                    Slog.e(TAG, "Didn't find start tag during restore");
                Slog.e(TAG, "Unable to write default apps for backup", e);
            }
                return;
            return null;
        }
            // this is supposed to be TAG_PREFERRED_BACKUP
            if (!TAG_PREFERRED_BACKUP.equals(parser.getName())) {
        return dataStream.toByteArray();
    }
    @Override
    public void restoreDefaultApps(byte[] backup, int userId) {
        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
            throw new SecurityException("Only the system may call restoreDefaultApps()");
        }
        try {
            final XmlPullParser parser = Xml.newPullParser();
            parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name());
            restoreFromXml(parser, userId, TAG_DEFAULT_APPS,
                    new BlobXmlRestorer() {
                        @Override
                        public void apply(XmlPullParser parser, int userId)
                                throws XmlPullParserException, IOException {
                            synchronized (mPackages) {
                                mSettings.readDefaultAppsLPw(parser, userId);
                            }
                        }
                    } );
        } catch (Exception e) {
            if (DEBUG_BACKUP) {
                    Slog.e(TAG, "Found unexpected tag " + parser.getName());
                Slog.e(TAG, "Exception restoring default apps: " + e.getMessage());
            }
        }
                return;
    }
            // skip interfering stuff, then we're aligned with the backing implementation
            while ((type = parser.next()) == XmlPullParser.TEXT) { }
    @Override
    public byte[] getIntentFilterVerificationBackup(int userId) {
        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
            throw new SecurityException("Only the system may call getIntentFilterVerificationBackup()");
        }
        ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
        try {
            final XmlSerializer serializer = new FastXmlSerializer();
            serializer.setOutput(dataStream, StandardCharsets.UTF_8.name());
            serializer.startDocument(null, true);
            serializer.startTag(null, TAG_INTENT_FILTER_VERIFICATION);
            synchronized (mPackages) {
                mSettings.readPreferredActivitiesLPw(parser, userId);
                mSettings.writeAllDomainVerificationsLPr(serializer, userId);
            }
            serializer.endTag(null, TAG_INTENT_FILTER_VERIFICATION);
            serializer.endDocument();
            serializer.flush();
        } catch (Exception e) {
            if (DEBUG_BACKUP) {
                Slog.e(TAG, "Unable to write default apps for backup", e);
            }
            return null;
        }
        return dataStream.toByteArray();
    }
    @Override
    public void restoreIntentFilterVerification(byte[] backup, int userId) {
        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
            throw new SecurityException("Only the system may call restorePreferredActivities()");
        }
        try {
            final XmlPullParser parser = Xml.newPullParser();
            parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name());
            restoreFromXml(parser, userId, TAG_INTENT_FILTER_VERIFICATION,
                    new BlobXmlRestorer() {
                        @Override
                        public void apply(XmlPullParser parser, int userId)
                                throws XmlPullParserException, IOException {
                            synchronized (mPackages) {
                                mSettings.readAllDomainVerificationsLPr(parser, userId);
                                mSettings.writeLPr();
                            }
                        }
                    } );
        } catch (Exception e) {
            if (DEBUG_BACKUP) {
                Slog.e(TAG, "Exception restoring preferred activities: " + e.getMessage());
+119 −4

File changed.

Preview size limit exceeded, changes collapsed.