Merge "Back up / restore default app and intent filter verification state" into mnc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
6d2268a576
@@ -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
|
||||
|
||||
@@ -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();
|
||||
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);
|
||||
}
|
||||
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
|
||||
}
|
||||
} 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();
|
||||
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);
|
||||
}
|
||||
IPackageManager pm = AppGlobals.getPackageManager();
|
||||
try {
|
||||
pm.restorePreferredActivities(payload, UserHandle.USER_OWNER);
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "Unable to restore", e);
|
||||
}
|
||||
} else {
|
||||
Slog.w(TAG, "Unexpected restore key " + key);
|
||||
} catch (Exception e) {
|
||||
Slog.w(TAG, "Unable to restore key " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
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;
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
|
||||
// skip interfering stuff, then we're aligned with the backing implementation
|
||||
while ((type = parser.next()) == XmlPullParser.TEXT) { }
|
||||
synchronized (mPackages) {
|
||||
mSettings.readPreferredActivitiesLPw(parser, userId);
|
||||
mSettings.writeDefaultAppsLPr(serializer, userId);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
synchronized (mPackages) {
|
||||
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());
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user