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 com.android.internal.util.XmlUtils;
20 import org.xmlpull.v1.XmlPullParser;
21 import org.xmlpull.v1.XmlPullParserException;
22 import org.xmlpull.v1.XmlSerializer;
23 import android.content.IntentFilter;
24 import android.util.Log;
25 import java.io.IOException;
26 import android.os.UserHandle;
27 
28 /**
29  * The {@link PackageManagerService} maintains some {@link CrossProfileIntentFilter}s for each user.
30  * If an {@link Intent} matches the {@link CrossProfileIntentFilter}, then activities in the user
31  * {@link #mTargetUserId} can access it.
32  */
33 class CrossProfileIntentFilter extends IntentFilter {
34     private static final String ATTR_TARGET_USER_ID = "targetUserId";
35     private static final String ATTR_FLAGS = "flags";
36     private static final String ATTR_OWNER_PACKAGE = "ownerPackage";
37     private static final String ATTR_FILTER = "filter";
38 
39     private static final String TAG = "CrossProfileIntentFilter";
40 
41     // If the intent matches the IntentFilter, then it can be forwarded to this userId.
42     final int mTargetUserId;
43     final String mOwnerPackage; // packageName of the app.
44     final int mFlags;
45 
CrossProfileIntentFilter(IntentFilter filter, String ownerPackage, int targetUserId, int flags)46     CrossProfileIntentFilter(IntentFilter filter, String ownerPackage, int targetUserId,
47             int flags) {
48         super(filter);
49         mTargetUserId = targetUserId;
50         mOwnerPackage = ownerPackage;
51         mFlags = flags;
52     }
53 
getTargetUserId()54     public int getTargetUserId() {
55         return mTargetUserId;
56     }
57 
getFlags()58     public int getFlags() {
59         return mFlags;
60     }
61 
getOwnerPackage()62     public String getOwnerPackage() {
63         return mOwnerPackage;
64     }
65 
CrossProfileIntentFilter(XmlPullParser parser)66     CrossProfileIntentFilter(XmlPullParser parser) throws XmlPullParserException, IOException {
67         mTargetUserId = getIntFromXml(parser, ATTR_TARGET_USER_ID, UserHandle.USER_NULL);
68         mOwnerPackage = getStringFromXml(parser, ATTR_OWNER_PACKAGE, "");
69         mFlags = getIntFromXml(parser, ATTR_FLAGS, 0);
70 
71         int outerDepth = parser.getDepth();
72         String tagName = parser.getName();
73         int type;
74         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
75                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
76             tagName = parser.getName();
77             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
78                 continue;
79             } else if (type == XmlPullParser.START_TAG) {
80                 if (tagName.equals(ATTR_FILTER)) {
81                     break;
82                 } else {
83                     String msg = "Unknown element under "
84                             + Settings.TAG_CROSS_PROFILE_INTENT_FILTERS + ": " + tagName + " at "
85                             + parser.getPositionDescription();
86                     PackageManagerService.reportSettingsProblem(Log.WARN, msg);
87                     XmlUtils.skipCurrentTag(parser);
88                 }
89             }
90         }
91         if (tagName.equals(ATTR_FILTER)) {
92             readFromXml(parser);
93         } else {
94             String msg = "Missing element under " + TAG + ": " + ATTR_FILTER +
95                     " at " + parser.getPositionDescription();
96             PackageManagerService.reportSettingsProblem(Log.WARN, msg);
97             XmlUtils.skipCurrentTag(parser);
98         }
99     }
100 
getStringFromXml(XmlPullParser parser, String attribute, String defaultValue)101     String getStringFromXml(XmlPullParser parser, String attribute, String defaultValue) {
102         String value = parser.getAttributeValue(null, attribute);
103         if (value == null) {
104             String msg = "Missing element under " + TAG +": " + attribute + " at " +
105                     parser.getPositionDescription();
106             PackageManagerService.reportSettingsProblem(Log.WARN, msg);
107             return defaultValue;
108         } else {
109             return value;
110         }
111     }
112 
getIntFromXml(XmlPullParser parser, String attribute, int defaultValue)113     int getIntFromXml(XmlPullParser parser, String attribute, int defaultValue) {
114         String stringValue = getStringFromXml(parser, attribute, null);
115         if (stringValue != null) {
116             return Integer.parseInt(stringValue);
117         }
118         return defaultValue;
119     }
120 
writeToXml(XmlSerializer serializer)121     public void writeToXml(XmlSerializer serializer) throws IOException {
122         serializer.attribute(null, ATTR_TARGET_USER_ID, Integer.toString(mTargetUserId));
123         serializer.attribute(null, ATTR_FLAGS, Integer.toString(mFlags));
124         serializer.attribute(null, ATTR_OWNER_PACKAGE, mOwnerPackage);
125         serializer.startTag(null, ATTR_FILTER);
126             super.writeToXml(serializer);
127         serializer.endTag(null, ATTR_FILTER);
128     }
129 
130     @Override
toString()131     public String toString() {
132         return "CrossProfileIntentFilter{0x" + Integer.toHexString(System.identityHashCode(this))
133                 + " " + Integer.toString(mTargetUserId) + "}";
134     }
135 
equalsIgnoreFilter(CrossProfileIntentFilter other)136     boolean equalsIgnoreFilter(CrossProfileIntentFilter other) {
137         return mTargetUserId == other.mTargetUserId
138                 && mOwnerPackage.equals(other.mOwnerPackage)
139                 && mFlags == other.mFlags;
140     }
141 }
142