diff options
5 files changed, 387 insertions, 79 deletions
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 0c07bc3..2dbcde9 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -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 diff --git a/core/java/com/android/server/backup/PreferredActivityBackupHelper.java b/core/java/com/android/server/backup/PreferredActivityBackupHelper.java index 26f5bf4..458a2ca 100644 --- a/core/java/com/android/server/backup/PreferredActivityBackupHelper.java +++ b/core/java/com/android/server/backup/PreferredActivityBackupHelper.java @@ -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)) { - if (DEBUG) { - Slog.v(TAG, "Checking whether to back up"); - } - IPackageManager pm = AppGlobals.getPackageManager(); - try { - return pm.getPreferredActivityBackup(UserHandle.USER_OWNER); - } catch (Exception e) { - Slog.e(TAG, "Unable to store backup payload", e); - // fall through to report null state + IPackageManager pm = AppGlobals.getPackageManager(); + if (DEBUG) { + Slog.d(TAG, "Handling backup of " + key); + } + try { + switch (key) { + case KEY_PREFERRED: + return pm.getPreferredActivityBackup(UserHandle.USER_OWNER); + 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); } - } else { - 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)) { - if (DEBUG) { - Slog.v(TAG, "Restoring"); - } - IPackageManager pm = AppGlobals.getPackageManager(); - try { - pm.restorePreferredActivities(payload, UserHandle.USER_OWNER); - } catch (Exception e) { - Slog.e(TAG, "Unable to restore", e); + IPackageManager pm = AppGlobals.getPackageManager(); + if (DEBUG) { + Slog.d(TAG, "Handling restore of " + key); + } + try { + switch (key) { + case KEY_PREFERRED: + pm.restorePreferredActivities(payload, UserHandle.USER_OWNER); + 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); } - } else { - Slog.w(TAG, "Unexpected restore key " + key); + } catch (Exception e) { + Slog.w(TAG, "Unable to restore key " + key); } } } diff --git a/services/core/java/com/android/server/pm/IntentFilterVerificationState.java b/services/core/java/com/android/server/pm/IntentFilterVerificationState.java index c09d6ae..c6e7911 100644 --- a/services/core/java/com/android/server/pm/IntentFilterVerificationState.java +++ b/services/core/java/com/android/server/pm/IntentFilterVerificationState.java @@ -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; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index d7abad0..41d3ffd 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -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(); @@ -13378,9 +13408,45 @@ 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()"); + } + + 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); } - 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; + + serializer.endTag(null, TAG_DEFAULT_APPS); + serializer.endDocument(); + serializer.flush(); + } catch (Exception e) { + if (DEBUG_BACKUP) { + Slog.e(TAG, "Unable to write default apps for backup", e); } + return null; + } - // this is supposed to be TAG_PREFERRED_BACKUP - if (!TAG_PREFERRED_BACKUP.equals(parser.getName())) { - if (DEBUG_BACKUP) { - Slog.e(TAG, "Found unexpected tag " + parser.getName()); - } - return; + 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, "Exception restoring default apps: " + e.getMessage()); } + } + } + + @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); - // skip interfering stuff, then we're aligned with the backing implementation - while ((type = parser.next()) == XmlPullParser.TEXT) { } 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()); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 6415343..169f6de 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -174,6 +174,8 @@ final class Settings { "crossProfile-intent-filters"; public static final String TAG_DOMAIN_VERIFICATION = "domain-verification"; public static final String TAG_DEFAULT_APPS= "default-apps"; + public static final String TAG_ALL_INTENT_FILTER_VERIFICATION = + "all-intent-filter-verifications"; public static final String TAG_DEFAULT_BROWSER= "default-browser"; private static final String ATTR_NAME = "name"; @@ -206,10 +208,15 @@ final class Settings { final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<String, PackageSetting>(); + // List of replaced system applications private final ArrayMap<String, PackageSetting> mDisabledSysPackages = new ArrayMap<String, PackageSetting>(); + // Set of restored intent-filter verification states + private final ArrayMap<String, IntentFilterVerificationInfo> mRestoredIntentFilterVerifications = + new ArrayMap<String, IntentFilterVerificationInfo>(); + private static int mFirstAvailableUid = 0; // TODO: store SDK versions and fingerprint for each volume UUID @@ -753,7 +760,8 @@ final class Settings { } // Utility method that adds a PackageSetting to mPackages and - // completes updating the shared user attributes + // completes updating the shared user attributes and any restored + // app link verification state private void addPackageSettingLPw(PackageSetting p, String name, SharedUserSetting sharedUser) { mPackages.put(name, p); @@ -776,6 +784,14 @@ final class Settings { p.sharedUser = sharedUser; p.appId = sharedUser.userId; } + IntentFilterVerificationInfo ivi = mRestoredIntentFilterVerifications.get(name); + if (ivi != null) { + if (DEBUG_DOMAIN_VERIFICATION) { + Slog.i(TAG, "Applying restored IVI for " + name + " : " + ivi.getStatusString()); + } + mRestoredIntentFilterVerifications.remove(name); + p.setIntentFilterVerificationInfo(ivi); + } } /* @@ -1259,13 +1275,13 @@ final class Settings { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } - String tagName = parser.getName(); + final String tagName = parser.getName(); if (tagName.equals(TAG_ITEM)) { CrossProfileIntentFilter cpif = new CrossProfileIntentFilter(parser); editCrossProfileIntentResolverLPw(userId).addFilter(cpif); } else { String msg = "Unknown element under " + TAG_CROSS_PROFILE_INTENT_FILTERS + ": " + - parser.getName(); + tagName; PackageManagerService.reportSettingsProblem(Log.WARN, msg); XmlUtils.skipCurrentTag(parser); } @@ -1279,7 +1295,31 @@ final class Settings { Log.d(TAG, "Read domain verification for package:" + ivi.getPackageName()); } - private void readDefaultAppsLPw(XmlPullParser parser, int userId) + private void readRestoredIntentFilterVerifications(XmlPullParser parser) + 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; + } + final String tagName = parser.getName(); + if (tagName.equals(TAG_DOMAIN_VERIFICATION)) { + IntentFilterVerificationInfo ivi = new IntentFilterVerificationInfo(parser); + if (DEBUG_DOMAIN_VERIFICATION) { + Slog.i(TAG, "Restored IVI for " + ivi.getPackageName() + + " status=" + ivi.getStatusString()); + } + mRestoredIntentFilterVerifications.put(ivi.getPackageName(), ivi); + } else { + Slog.w(TAG, "Unknown element: " + tagName); + XmlUtils.skipCurrentTag(parser); + } + } + } + + void readDefaultAppsLPw(XmlPullParser parser, int userId) throws XmlPullParserException, IOException { int outerDepth = parser.getDepth(); int type; @@ -1563,6 +1603,62 @@ final class Settings { } } + // Specifically for backup/restore + void writeAllDomainVerificationsLPr(XmlSerializer serializer, int userId) + throws IllegalArgumentException, IllegalStateException, IOException { + serializer.startTag(null, TAG_ALL_INTENT_FILTER_VERIFICATION); + final int N = mPackages.size(); + for (int i = 0; i < N; i++) { + PackageSetting ps = mPackages.valueAt(i); + IntentFilterVerificationInfo ivi = ps.getIntentFilterVerificationInfo(); + if (ivi != null) { + writeDomainVerificationsLPr(serializer, ivi); + } + } + serializer.endTag(null, TAG_ALL_INTENT_FILTER_VERIFICATION); + } + + // Specifically for backup/restore + void readAllDomainVerificationsLPr(XmlPullParser parser, int userId) + throws XmlPullParserException, IOException { + mRestoredIntentFilterVerifications.clear(); + + 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_DOMAIN_VERIFICATION)) { + IntentFilterVerificationInfo ivi = new IntentFilterVerificationInfo(parser); + final String pkgName = ivi.getPackageName(); + final PackageSetting ps = mPackages.get(pkgName); + if (ps != null) { + // known/existing package; update in place + ps.setIntentFilterVerificationInfo(ivi); + if (DEBUG_DOMAIN_VERIFICATION) { + Slog.d(TAG, "Restored IVI for existing app " + pkgName + + " status=" + ivi.getStatusString()); + } + } else { + mRestoredIntentFilterVerifications.put(pkgName, ivi); + if (DEBUG_DOMAIN_VERIFICATION) { + Slog.d(TAG, "Restored IVI for pending app " + pkgName + + " status=" + ivi.getStatusString()); + } + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element under <all-intent-filter-verification>: " + + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + } + void writeDefaultAppsLPr(XmlSerializer serializer, int userId) throws IllegalArgumentException, IllegalStateException, IOException { serializer.startTag(null, TAG_DEFAULT_APPS); @@ -2012,6 +2108,23 @@ final class Settings { } } + final int numIVIs = mRestoredIntentFilterVerifications.size(); + if (numIVIs > 0) { + if (DEBUG_DOMAIN_VERIFICATION) { + Slog.i(TAG, "Writing restored-ivi entries to packages.xml"); + } + serializer.startTag(null, "restored-ivi"); + for (int i = 0; i < numIVIs; i++) { + IntentFilterVerificationInfo ivi = mRestoredIntentFilterVerifications.valueAt(i); + writeDomainVerificationsLPr(serializer, ivi); + } + serializer.endTag(null, "restored-ivi"); + } else { + if (DEBUG_DOMAIN_VERIFICATION) { + Slog.i(TAG, " no restored IVI entries to write"); + } + } + mKeySetManagerService.writeKeySetManagerServiceLPr(serializer); serializer.endTag(null, "packages"); @@ -2441,6 +2554,8 @@ final class Settings { if (nname != null && oname != null) { mRenamedPackages.put(nname, oname); } + } else if (tagName.equals("restored-ivi")) { + readRestoredIntentFilterVerifications(parser); } else if (tagName.equals("last-platform-version")) { mInternalSdkPlatform = mExternalSdkPlatform = 0; try { |