summaryrefslogtreecommitdiffstats
path: root/services/core/java/com/android/server/pm/PreferredComponent.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/core/java/com/android/server/pm/PreferredComponent.java')
-rw-r--r--services/core/java/com/android/server/pm/PreferredComponent.java234
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]);
+ }
+ }
+ }
+}