1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.pm; 18 19 import android.content.ComponentName; 20 import android.content.IntentFilter; 21 import android.util.Log; 22 23 import com.android.internal.util.XmlUtils; 24 import com.android.modules.utils.TypedXmlPullParser; 25 import com.android.modules.utils.TypedXmlSerializer; 26 import com.android.server.utils.SnapshotCache; 27 28 import org.xmlpull.v1.XmlPullParser; 29 import org.xmlpull.v1.XmlPullParserException; 30 31 import java.io.IOException; 32 33 class PersistentPreferredActivity extends WatchedIntentFilter { 34 private static final String ATTR_NAME = "name"; // component name 35 private static final String ATTR_FILTER = "filter"; // filter 36 private static final String ATTR_SET_BY_DPM = "set-by-dpm"; // set by DPM 37 38 private static final String TAG = "PersistentPreferredActivity"; 39 40 private static final boolean DEBUG_FILTERS = false; 41 42 final ComponentName mComponent; 43 final boolean mIsSetByDpm; 44 45 // The cache for snapshots, so they are not rebuilt if the base object has not 46 // changed. 47 final SnapshotCache<PersistentPreferredActivity> mSnapshot; 48 makeCache()49 private SnapshotCache makeCache() { 50 return new SnapshotCache<PersistentPreferredActivity>(this, this) { 51 @Override 52 public PersistentPreferredActivity createSnapshot() { 53 PersistentPreferredActivity s = new PersistentPreferredActivity(mSource); 54 s.seal(); 55 return s; 56 }}; 57 } 58 59 PersistentPreferredActivity(IntentFilter filter, ComponentName activity, boolean isSetByDpm) { 60 super(filter); 61 mComponent = activity; 62 mIsSetByDpm = isSetByDpm; 63 mSnapshot = makeCache(); 64 } 65 66 PersistentPreferredActivity(WatchedIntentFilter filter, ComponentName activity, 67 boolean isSetByDpm) { 68 this(filter.mFilter, activity, isSetByDpm); 69 } 70 71 // Copy constructor used only to create a snapshot 72 private PersistentPreferredActivity(PersistentPreferredActivity f) { 73 super(f); 74 mComponent = f.mComponent; 75 mIsSetByDpm = f.mIsSetByDpm; 76 mSnapshot = new SnapshotCache.Sealed(); 77 } 78 79 PersistentPreferredActivity(TypedXmlPullParser parser) 80 throws XmlPullParserException, IOException { 81 String shortComponent = parser.getAttributeValue(null, ATTR_NAME); 82 mComponent = ComponentName.unflattenFromString(shortComponent); 83 if (mComponent == null) { 84 PackageManagerService.reportSettingsProblem(Log.WARN, 85 "Error in package manager settings: " + 86 "Bad activity name " + shortComponent + 87 " at " + parser.getPositionDescription()); 88 } 89 mIsSetByDpm = parser.getAttributeBoolean(null, ATTR_SET_BY_DPM, false); 90 91 int outerDepth = parser.getDepth(); 92 String tagName = parser.getName(); 93 int type; 94 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 95 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 96 tagName = parser.getName(); 97 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 98 continue; 99 } else if (type == XmlPullParser.START_TAG) { 100 if (tagName.equals(ATTR_FILTER)) { 101 break; 102 } else { 103 PackageManagerService.reportSettingsProblem(Log.WARN, 104 "Unknown element: " + tagName + 105 " at " + parser.getPositionDescription()); 106 XmlUtils.skipCurrentTag(parser); 107 } 108 } 109 } 110 if (tagName.equals(ATTR_FILTER)) { 111 mFilter.readFromXml(parser); 112 } else { 113 PackageManagerService.reportSettingsProblem(Log.WARN, 114 "Missing element filter at " + 115 parser.getPositionDescription()); 116 XmlUtils.skipCurrentTag(parser); 117 } 118 mSnapshot = makeCache(); 119 } 120 121 public void writeToXml(TypedXmlSerializer serializer) throws IOException { 122 serializer.attribute(null, ATTR_NAME, mComponent.flattenToShortString()); 123 serializer.attributeBoolean(null, ATTR_SET_BY_DPM, mIsSetByDpm); 124 serializer.startTag(null, ATTR_FILTER); 125 mFilter.writeToXml(serializer); 126 serializer.endTag(null, ATTR_FILTER); 127 } 128 129 public IntentFilter getIntentFilter() { 130 return mFilter; 131 } 132 133 @Override 134 public String toString() { 135 return "PersistentPreferredActivity{0x" + Integer.toHexString(System.identityHashCode(this)) 136 + " " + mComponent.flattenToShortString() 137 + ", mIsSetByDpm=" + mIsSetByDpm + "}"; 138 } 139 140 public PersistentPreferredActivity snapshot() { 141 return mSnapshot.snapshot(); 142 } 143 } 144