• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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.Intent;
20 import android.content.IntentFilter;
21 import android.os.UserHandle;
22 import android.util.Log;
23 import android.util.TypedXmlPullParser;
24 import android.util.TypedXmlSerializer;
25 
26 import com.android.internal.util.XmlUtils;
27 import com.android.server.utils.SnapshotCache;
28 
29 import org.xmlpull.v1.XmlPullParser;
30 import org.xmlpull.v1.XmlPullParserException;
31 
32 import java.io.IOException;
33 
34 /**
35  * The {@link PackageManagerService} maintains some {@link CrossProfileIntentFilter}s for each user.
36  * If an {@link Intent} matches the {@link CrossProfileIntentFilter}, then activities in the user
37  * {@link #mTargetUserId} can access it.
38  */
39 class CrossProfileIntentFilter extends WatchedIntentFilter {
40     private static final String ATTR_TARGET_USER_ID = "targetUserId";
41     private static final String ATTR_FLAGS = "flags";
42     private static final String ATTR_OWNER_PACKAGE = "ownerPackage";
43     private static final String ATTR_FILTER = "filter";
44 
45     private static final String TAG = "CrossProfileIntentFilter";
46 
47     // If the intent matches the IntentFilter, then it can be forwarded to this userId.
48     final int mTargetUserId;
49     final String mOwnerPackage; // packageName of the app.
50     final int mFlags;
51 
52     // The cache for snapshots, so they are not rebuilt if the base object has not
53     // changed.
54     final SnapshotCache<CrossProfileIntentFilter> mSnapshot;
55 
makeCache()56     private SnapshotCache makeCache() {
57         return new SnapshotCache<CrossProfileIntentFilter>(this, this) {
58             @Override
59             public CrossProfileIntentFilter createSnapshot() {
60                 CrossProfileIntentFilter s = new CrossProfileIntentFilter(mSource);
61                 s.seal();
62                 return s;
63             }};
64     }
65 
66     CrossProfileIntentFilter(IntentFilter filter, String ownerPackage, int targetUserId,
67             int flags) {
68         super(filter);
69         mTargetUserId = targetUserId;
70         mOwnerPackage = ownerPackage;
71         mFlags = flags;
72         mSnapshot = makeCache();
73     }
74 
75     CrossProfileIntentFilter(WatchedIntentFilter filter, String ownerPackage, int targetUserId,
76             int flags) {
77         this(filter.mFilter, ownerPackage, targetUserId, flags);
78     }
79 
80     // Copy constructor used only to create a snapshot.
81     private CrossProfileIntentFilter(CrossProfileIntentFilter f) {
82         super(f);
83         mTargetUserId = f.mTargetUserId;
84         mOwnerPackage = f.mOwnerPackage;
85         mFlags = f.mFlags;
86         mSnapshot = new SnapshotCache.Sealed();
87     }
88 
89     public int getTargetUserId() {
90         return mTargetUserId;
91     }
92 
93     public int getFlags() {
94         return mFlags;
95     }
96 
97     public String getOwnerPackage() {
98         return mOwnerPackage;
99     }
100 
101     CrossProfileIntentFilter(TypedXmlPullParser parser) throws XmlPullParserException, IOException {
102         mTargetUserId = parser.getAttributeInt(null, ATTR_TARGET_USER_ID, UserHandle.USER_NULL);
103         mOwnerPackage = getStringFromXml(parser, ATTR_OWNER_PACKAGE, "");
104         mFlags = parser.getAttributeInt(null, ATTR_FLAGS, 0);
105         mSnapshot = makeCache();
106 
107         int outerDepth = parser.getDepth();
108         String tagName = parser.getName();
109         int type;
110         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
111                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
112             tagName = parser.getName();
113             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
114                 continue;
115             } else if (type == XmlPullParser.START_TAG) {
116                 if (tagName.equals(ATTR_FILTER)) {
117                     break;
118                 } else {
119                     String msg = "Unknown element under "
120                             + Settings.TAG_CROSS_PROFILE_INTENT_FILTERS + ": " + tagName + " at "
121                             + parser.getPositionDescription();
122                     PackageManagerService.reportSettingsProblem(Log.WARN, msg);
123                     XmlUtils.skipCurrentTag(parser);
124                 }
125             }
126         }
127         if (tagName.equals(ATTR_FILTER)) {
128             mFilter.readFromXml(parser);
129         } else {
130             String msg = "Missing element under " + TAG + ": " + ATTR_FILTER +
131                     " at " + parser.getPositionDescription();
132             PackageManagerService.reportSettingsProblem(Log.WARN, msg);
133             XmlUtils.skipCurrentTag(parser);
134         }
135     }
136 
137     private String getStringFromXml(TypedXmlPullParser parser, String attribute,
138             String defaultValue) {
139         String value = parser.getAttributeValue(null, attribute);
140         if (value == null) {
141             String msg = "Missing element under " + TAG +": " + attribute + " at " +
142                     parser.getPositionDescription();
143             PackageManagerService.reportSettingsProblem(Log.WARN, msg);
144             return defaultValue;
145         } else {
146             return value;
147         }
148     }
149 
150     public void writeToXml(TypedXmlSerializer serializer) throws IOException {
151         serializer.attributeInt(null, ATTR_TARGET_USER_ID, mTargetUserId);
152         serializer.attributeInt(null, ATTR_FLAGS, mFlags);
153         serializer.attribute(null, ATTR_OWNER_PACKAGE, mOwnerPackage);
154         serializer.startTag(null, ATTR_FILTER);
155         mFilter.writeToXml(serializer);
156         serializer.endTag(null, ATTR_FILTER);
157     }
158 
159     @Override
160     public String toString() {
161         return "CrossProfileIntentFilter{0x" + Integer.toHexString(System.identityHashCode(this))
162                 + " " + Integer.toString(mTargetUserId) + "}";
163     }
164 
165     boolean equalsIgnoreFilter(CrossProfileIntentFilter other) {
166         return mTargetUserId == other.mTargetUserId
167                 && mOwnerPackage.equals(other.mOwnerPackage)
168                 && mFlags == other.mFlags;
169     }
170 
171     public CrossProfileIntentFilter snapshot() {
172         return mSnapshot.snapshot();
173     }
174 }
175