diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 0445b3975d990..a36845104e1fb 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -210,6 +210,8 @@ interface IPackageManager { List getPreferredPackages(int flags); + void resetPreferredActivities(int userId); + void addPreferredActivity(in IntentFilter filter, int match, in ComponentName[] set, in ComponentName activity, int userId); diff --git a/core/java/com/android/internal/util/FastXmlSerializer.java b/core/java/com/android/internal/util/FastXmlSerializer.java index 592a8facc7fd1..99eea151879fd 100644 --- a/core/java/com/android/internal/util/FastXmlSerializer.java +++ b/core/java/com/android/internal/util/FastXmlSerializer.java @@ -50,6 +50,8 @@ public class FastXmlSerializer implements XmlSerializer { private static final int BUFFER_LEN = 8192; + private static String sSpace = " "; + private final char[] mText = new char[BUFFER_LEN]; private int mPos; @@ -59,8 +61,12 @@ public class FastXmlSerializer implements XmlSerializer { private CharsetEncoder mCharset; private ByteBuffer mBytes = ByteBuffer.allocate(BUFFER_LEN); + private boolean mIndent = false; private boolean mInTag; + private int mNesting = 0; + private boolean mLineStart = true; + private void append(char c) throws IOException { int pos = mPos; if (pos >= (BUFFER_LEN-1)) { @@ -113,6 +119,14 @@ public class FastXmlSerializer implements XmlSerializer { append(str, 0, str.length()); } + private void appendIndent(int indent) throws IOException { + indent *= 4; + if (indent > sSpace.length()) { + indent = sSpace.length(); + } + append(sSpace, 0, indent); + } + private void escapeAndAppendString(final String string) throws IOException { final int N = string.length(); final char NE = (char)ESCAPE_TABLE.length; @@ -161,6 +175,7 @@ public class FastXmlSerializer implements XmlSerializer { escapeAndAppendString(value); append('"'); + mLineStart = false; return this; } @@ -185,9 +200,13 @@ public class FastXmlSerializer implements XmlSerializer { public XmlSerializer endTag(String namespace, String name) throws IOException, IllegalArgumentException, IllegalStateException { + mNesting--; if (mInTag) { append(" />\n"); } else { + if (mIndent && mLineStart) { + appendIndent(mNesting); + } append("\n"); } + mLineStart = true; mInTag = false; return this; } @@ -278,6 +298,7 @@ public class FastXmlSerializer implements XmlSerializer { public void setFeature(String name, boolean state) throws IllegalArgumentException, IllegalStateException { if (name.equals("http://xmlpull.org/v1/doc/features.html#indent-output")) { + mIndent = true; return; } throw new UnsupportedOperationException(); @@ -325,6 +346,7 @@ public class FastXmlSerializer implements XmlSerializer { IllegalArgumentException, IllegalStateException { append("\n"); + mLineStart = true; } public XmlSerializer startTag(String namespace, String name) throws IOException, @@ -332,6 +354,10 @@ public class FastXmlSerializer implements XmlSerializer { if (mInTag) { append(">\n"); } + if (mIndent) { + appendIndent(mNesting); + } + mNesting++; append('<'); if (namespace != null) { append(namespace); @@ -339,6 +365,7 @@ public class FastXmlSerializer implements XmlSerializer { } append(name); mInTag = true; + mLineStart = false; return this; } @@ -349,6 +376,9 @@ public class FastXmlSerializer implements XmlSerializer { mInTag = false; } escapeAndAppendString(buf, start, len); + if (mIndent) { + mLineStart = buf[start+len-1] == '\n'; + } return this; } @@ -359,6 +389,9 @@ public class FastXmlSerializer implements XmlSerializer { mInTag = false; } escapeAndAppendString(text); + if (mIndent) { + mLineStart = text.charAt(text.length()-1) == '\n'; + } return this; } diff --git a/services/java/com/android/server/PreferredComponent.java b/services/java/com/android/server/PreferredComponent.java index 718b05d0227e5..bb22545160175 100644 --- a/services/java/com/android/server/PreferredComponent.java +++ b/services/java/com/android/server/PreferredComponent.java @@ -164,17 +164,19 @@ public class PreferredComponent { return mParseError; } - public void writeToXml(XmlSerializer serializer) throws IOException { + public void writeToXml(XmlSerializer serializer, boolean full) throws IOException { final int NS = mSetClasses != null ? mSetClasses.length : 0; serializer.attribute(null, "name", mShortComponent); - if (mMatch != 0) { - serializer.attribute(null, "match", Integer.toHexString(mMatch)); - } - serializer.attribute(null, "set", Integer.toString(NS)); - for (int s=0; s { public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) { @@ -8830,8 +8830,10 @@ public class PackageManagerService extends IPackageManager.Stub { } } - if (clearPackagePreferredActivitiesLPw(packageName, UserHandle.getCallingUserId())) { - scheduleWriteSettingsLocked(); + int user = UserHandle.getCallingUserId(); + if (clearPackagePreferredActivitiesLPw(packageName, user)) { + mSettings.writePackageRestrictionsLPr(user); + scheduleWriteSettingsLocked(); } } } @@ -8849,7 +8851,8 @@ public class PackageManagerService extends IPackageManager.Stub { Iterator it = pir.filterIterator(); while (it.hasNext()) { PreferredActivity pa = it.next(); - if (pa.mPref.mComponent.getPackageName().equals(packageName)) { + if (packageName == null || + pa.mPref.mComponent.getPackageName().equals(packageName)) { if (removed == null) { removed = new ArrayList(); } @@ -8862,12 +8865,24 @@ public class PackageManagerService extends IPackageManager.Stub { pir.removeFilter(pa); } changed = true; - mSettings.writePackageRestrictionsLPr(thisUserId); } } return changed; } + public void resetPreferredActivities(int userId) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); + // writer + synchronized (mPackages) { + int user = UserHandle.getCallingUserId(); + clearPackagePreferredActivitiesLPw(null, user); + mSettings.readDefaultPreferredAppsLPw(this, user); + mSettings.writePackageRestrictionsLPr(user); + scheduleWriteSettingsLocked(); + } + } + public int getPreferredActivities(List outFilters, List outActivities, String packageName) { @@ -9254,6 +9269,7 @@ public class PackageManagerService extends IPackageManager.Stub { } DumpState dumpState = new DumpState(); + boolean fullPreferred = false; String packageName = null; @@ -9277,7 +9293,7 @@ public class PackageManagerService extends IPackageManager.Stub { pw.println(" r[esolvers]: dump intent resolvers"); pw.println(" perm[issions]: dump permissions"); pw.println(" pref[erred]: print preferred package settings"); - pw.println(" preferred-xml: print preferred package settings as xml"); + pw.println(" preferred-xml [--full]: print preferred package settings as xml"); pw.println(" prov[iders]: dump content providers"); pw.println(" p[ackages]: dump installed packages"); pw.println(" s[hared-users]: dump shared user IDs"); @@ -9311,6 +9327,10 @@ public class PackageManagerService extends IPackageManager.Stub { dumpState.setDump(DumpState.DUMP_PREFERRED); } else if ("preferred-xml".equals(cmd)) { dumpState.setDump(DumpState.DUMP_PREFERRED_XML); + opti++; + if (opti < args.length && "--full".equals(args[opti])) { + fullPreferred = true; + } } else if ("p".equals(cmd) || "packages".equals(cmd)) { dumpState.setDump(DumpState.DUMP_PACKAGES); } else if ("s".equals(cmd) || "shared-users".equals(cmd)) { @@ -9405,7 +9425,7 @@ public class PackageManagerService extends IPackageManager.Stub { serializer.startDocument(null, true); serializer.setFeature( "http://xmlpull.org/v1/doc/features.html#indent-output", true); - mSettings.writePreferredActivitiesLPr(serializer, 0); + mSettings.writePreferredActivitiesLPr(serializer, 0, fullPreferred); serializer.endDocument(); serializer.flush(); } catch (IllegalArgumentException e) { @@ -10158,7 +10178,7 @@ public class PackageManagerService extends IPackageManager.Stub { /** Called by UserManagerService */ void createNewUserLILPw(int userHandle, File path) { if (mInstaller != null) { - mSettings.createNewUserLILPw(mInstaller, userHandle, path); + mSettings.createNewUserLILPw(this, mInstaller, userHandle, path); } } diff --git a/services/java/com/android/server/pm/PreferredActivity.java b/services/java/com/android/server/pm/PreferredActivity.java index dbf56efe42d1d..c655bb16bfd7a 100644 --- a/services/java/com/android/server/pm/PreferredActivity.java +++ b/services/java/com/android/server/pm/PreferredActivity.java @@ -46,8 +46,8 @@ class PreferredActivity extends IntentFilter implements PreferredComponent.Callb mPref = new PreferredComponent(this, parser); } - public void writeToXml(XmlSerializer serializer) throws IOException { - mPref.writeToXml(serializer); + public void writeToXml(XmlSerializer serializer, boolean full) throws IOException { + mPref.writeToXml(serializer, full); serializer.startTag(null, "filter"); super.writeToXml(serializer); serializer.endTag(null, "filter"); diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java index e33652442c271..13f514b260732 100644 --- a/services/java/com/android/server/pm/Settings.java +++ b/services/java/com/android/server/pm/Settings.java @@ -23,6 +23,12 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +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; @@ -972,14 +978,14 @@ final class Settings { return components; } - void writePreferredActivitiesLPr(XmlSerializer serializer, int userId) + void writePreferredActivitiesLPr(XmlSerializer serializer, int userId, boolean full) throws IllegalArgumentException, IllegalStateException, IOException { serializer.startTag(null, "preferred-activities"); PreferredIntentResolver pir = mPreferredActivities.get(userId); if (pir != null) { for (final PreferredActivity pa : pir.filterSet()) { serializer.startTag(null, TAG_ITEM); - pa.writeToXml(serializer); + pa.writeToXml(serializer, full); serializer.endTag(null, TAG_ITEM); } } @@ -1072,7 +1078,7 @@ final class Settings { } } - writePreferredActivitiesLPr(serializer, userId); + writePreferredActivitiesLPr(serializer, userId, true); serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS); @@ -1557,7 +1563,8 @@ final class Settings { } } - boolean readLPw(List users, int sdkVersion, boolean onlyCore) { + boolean readLPw(PackageManagerService service, List users, int sdkVersion, + boolean onlyCore) { FileInputStream str = null; if (mBackupSettingsFilename.exists()) { try { @@ -1588,7 +1595,7 @@ final class Settings { PackageManagerService.reportSettingsProblem(Log.INFO, "No settings file; creating initial state"); if (!onlyCore) { - readDefaultPreferredAppsLPw(0); + readDefaultPreferredAppsLPw(service, 0); } mInternalSdkPlatform = mExternalSdkPlatform = sdkVersion; return false; @@ -1771,7 +1778,7 @@ final class Settings { return true; } - private void readDefaultPreferredAppsLPw(int userId) { + void readDefaultPreferredAppsLPw(PackageManagerService service, int userId) { // Read preferred apps from .../etc/preferred-apps directory. File preferredDir = new File(Environment.getRootDirectory(), "etc/preferred-apps"); if (!preferredDir.exists() || !preferredDir.isDirectory()) { @@ -1793,6 +1800,7 @@ final class Settings { continue; } + if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Reading default preferred " + f); FileInputStream str = null; try { str = new FileInputStream(f); @@ -1814,7 +1822,7 @@ final class Settings { + " does not start with 'preferred-activities'"); continue; } - readPreferredActivitiesLPw(parser, userId); + readDefaultPreferredActivitiesLPw(service, parser, userId); } catch (XmlPullParserException e) { Slog.w(TAG, "Error reading apps file " + f, e); } catch (IOException e) { @@ -1830,6 +1838,112 @@ final class Settings { } } + private void readDefaultPreferredActivitiesLPw(PackageManagerService service, + 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)) { + PreferredActivity tmpPa = new PreferredActivity(parser); + if (tmpPa.mPref.getParseError() == null) { + // The initial preferences only specify the target activity + // component and intent-filter, not the set of matches. So we + // now need to query for the matches to build the correct + // preferred activity entry. + if (PackageManagerService.DEBUG_PREFERRED) { + Log.d(TAG, "Processing preferred:"); + tmpPa.dump(new LogPrinter(Log.DEBUG, TAG), " "); + } + final ComponentName cn = tmpPa.mPref.mComponent; + Intent intent = new Intent(); + int flags = 0; + intent.setAction(tmpPa.getAction(0)); + for (int i=0; i 0) { + Uri.Builder builder = new Uri.Builder(); + builder.scheme(tmpPa.getDataScheme(0)); + if (tmpPa.countDataAuthorities() > 0) { + IntentFilter.AuthorityEntry auth = tmpPa.getDataAuthority(0); + if (auth.getHost() != null) { + builder.authority(auth.getHost()); + } + } + if (tmpPa.countDataPaths() > 0) { + PatternMatcher path = tmpPa.getDataPath(0); + builder.path(path.getPath()); + } + intent.setData(builder.build()); + } else if (tmpPa.countDataTypes() > 0) { + intent.setType(tmpPa.getDataType(0)); + } + List ri = service.mActivities.queryIntent(intent, + intent.getType(), flags, 0); + if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent + + " results: " + ri); + int match = 0; + if (ri != null && ri.size() > 1) { + boolean haveAct = false; + boolean haveNonSys = false; + ComponentName[] set = new ComponentName[ri.size()]; + for (int i=0; i " + + tmpPa.mPref.getParseError() + " at " + + parser.getPositionDescription()); + } + } else { + PackageManagerService.reportSettingsProblem(Log.WARN, + "Unknown element under : " + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + } + private int readInt(XmlPullParser parser, String ns, String name, int defValue) { String v = parser.getAttributeValue(ns, name); try { @@ -2329,7 +2443,8 @@ final class Settings { } } - void createNewUserLILPw(Installer installer, int userHandle, File path) { + void createNewUserLILPw(PackageManagerService service, Installer installer, + int userHandle, File path) { path.mkdir(); FileUtils.setPermissions(path.toString(), FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IXOTH, -1, -1); @@ -2340,7 +2455,7 @@ final class Settings { installer.createUserData(ps.name, UserHandle.getUid(userHandle, ps.appId), userHandle); } - readDefaultPreferredAppsLPw(userHandle); + readDefaultPreferredAppsLPw(service, userHandle); writePackageRestrictionsLPr(userHandle); }