diff options
Diffstat (limited to 'services/core/java/com/android/server/pm/PreferredComponent.java')
-rw-r--r-- | services/core/java/com/android/server/pm/PreferredComponent.java | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/pm/PreferredComponent.java b/services/core/java/com/android/server/pm/PreferredComponent.java new file mode 100644 index 0000000..f437372 --- /dev/null +++ b/services/core/java/com/android/server/pm/PreferredComponent.java @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import com.android.internal.util.XmlUtils; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import android.content.ComponentName; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.ResolveInfo; +import android.util.Slog; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; + +public class PreferredComponent { + private static final String TAG_SET = "set"; + private static final String ATTR_ALWAYS = "always"; // boolean + private static final String ATTR_MATCH = "match"; // number + private static final String ATTR_NAME = "name"; // component name + private static final String ATTR_SET = "set"; // number + + public final int mMatch; + public final ComponentName mComponent; + // Whether this is to be the one that's always chosen. If false, it's the most recently chosen. + public boolean mAlways; + + private final String[] mSetPackages; + private final String[] mSetClasses; + private final String[] mSetComponents; + private final String mShortComponent; + private String mParseError; + + private final Callbacks mCallbacks; + + public interface Callbacks { + public boolean onReadTag(String tagName, XmlPullParser parser) + throws XmlPullParserException, IOException; + } + + public PreferredComponent(Callbacks callbacks, int match, ComponentName[] set, + ComponentName component, boolean always) { + mCallbacks = callbacks; + mMatch = match&IntentFilter.MATCH_CATEGORY_MASK; + mComponent = component; + mAlways = always; + mShortComponent = component.flattenToShortString(); + mParseError = null; + if (set != null) { + final int N = set.length; + String[] myPackages = new String[N]; + String[] myClasses = new String[N]; + String[] myComponents = new String[N]; + for (int i=0; i<N; i++) { + ComponentName cn = set[i]; + if (cn == null) { + mSetPackages = null; + mSetClasses = null; + mSetComponents = null; + return; + } + myPackages[i] = cn.getPackageName().intern(); + myClasses[i] = cn.getClassName().intern(); + myComponents[i] = cn.flattenToShortString(); + } + mSetPackages = myPackages; + mSetClasses = myClasses; + mSetComponents = myComponents; + } else { + mSetPackages = null; + mSetClasses = null; + mSetComponents = null; + } + } + + public PreferredComponent(Callbacks callbacks, XmlPullParser parser) + throws XmlPullParserException, IOException { + mCallbacks = callbacks; + mShortComponent = parser.getAttributeValue(null, ATTR_NAME); + mComponent = ComponentName.unflattenFromString(mShortComponent); + if (mComponent == null) { + mParseError = "Bad activity name " + mShortComponent; + } + String matchStr = parser.getAttributeValue(null, ATTR_MATCH); + mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0; + String setCountStr = parser.getAttributeValue(null, ATTR_SET); + int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0; + String alwaysStr = parser.getAttributeValue(null, ATTR_ALWAYS); + mAlways = alwaysStr != null ? Boolean.parseBoolean(alwaysStr) : true; + + String[] myPackages = setCount > 0 ? new String[setCount] : null; + String[] myClasses = setCount > 0 ? new String[setCount] : null; + String[] myComponents = setCount > 0 ? new String[setCount] : null; + + int setPos = 0; + + 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(); + //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth=" + // + parser.getDepth() + " tag=" + tagName); + if (tagName.equals(TAG_SET)) { + String name = parser.getAttributeValue(null, ATTR_NAME); + if (name == null) { + if (mParseError == null) { + mParseError = "No name in set tag in preferred activity " + + mShortComponent; + } + } else if (setPos >= setCount) { + if (mParseError == null) { + mParseError = "Too many set tags in preferred activity " + + mShortComponent; + } + } else { + ComponentName cn = ComponentName.unflattenFromString(name); + if (cn == null) { + if (mParseError == null) { + mParseError = "Bad set name " + name + " in preferred activity " + + mShortComponent; + } + } else { + myPackages[setPos] = cn.getPackageName(); + myClasses[setPos] = cn.getClassName(); + myComponents[setPos] = name; + setPos++; + } + } + XmlUtils.skipCurrentTag(parser); + } else if (!mCallbacks.onReadTag(tagName, parser)) { + Slog.w("PreferredComponent", "Unknown element: " + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + + if (setPos != setCount) { + if (mParseError == null) { + mParseError = "Not enough set tags (expected " + setCount + + " but found " + setPos + ") in " + mShortComponent; + } + } + + mSetPackages = myPackages; + mSetClasses = myClasses; + mSetComponents = myComponents; + } + + public String getParseError() { + return mParseError; + } + + public void writeToXml(XmlSerializer serializer, boolean full) throws IOException { + final int NS = mSetClasses != null ? mSetClasses.length : 0; + serializer.attribute(null, ATTR_NAME, mShortComponent); + if (full) { + if (mMatch != 0) { + serializer.attribute(null, ATTR_MATCH, Integer.toHexString(mMatch)); + } + serializer.attribute(null, ATTR_ALWAYS, Boolean.toString(mAlways)); + serializer.attribute(null, ATTR_SET, Integer.toString(NS)); + for (int s=0; s<NS; s++) { + serializer.startTag(null, TAG_SET); + serializer.attribute(null, ATTR_NAME, mSetComponents[s]); + serializer.endTag(null, TAG_SET); + } + } + } + + public boolean sameSet(List<ResolveInfo> query, int priority) { + if (mSetPackages == null) return false; + final int NQ = query.size(); + final int NS = mSetPackages.length; + int numMatch = 0; + for (int i=0; i<NQ; i++) { + ResolveInfo ri = query.get(i); + if (ri.priority != priority) continue; + ActivityInfo ai = ri.activityInfo; + boolean good = false; + for (int j=0; j<NS; j++) { + if (mSetPackages[j].equals(ai.packageName) + && mSetClasses[j].equals(ai.name)) { + numMatch++; + good = true; + break; + } + } + if (!good) return false; + } + return numMatch == NS; + } + + public void dump(PrintWriter out, String prefix, Object ident) { + out.print(prefix); out.print( + Integer.toHexString(System.identityHashCode(ident))); + out.print(' '); + out.println(mShortComponent); + out.print(prefix); out.print(" mMatch=0x"); + out.print(Integer.toHexString(mMatch)); + out.print(" mAlways="); out.println(mAlways); + if (mSetComponents != null) { + out.print(prefix); out.println(" Selected from:"); + for (int i=0; i<mSetComponents.length; i++) { + out.print(prefix); out.print(" "); + out.println(mSetComponents[i]); + } + } + } +} |