1 /* 2 * Copyright (C) 2015 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 android.content.pm; 18 19 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; 20 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; 21 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; 22 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; 23 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; 24 25 import android.annotation.SystemApi; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.text.TextUtils; 29 import android.util.ArraySet; 30 import android.util.Log; 31 32 import com.android.internal.util.XmlUtils; 33 34 import org.xmlpull.v1.XmlPullParser; 35 import org.xmlpull.v1.XmlPullParserException; 36 import org.xmlpull.v1.XmlSerializer; 37 38 import java.io.IOException; 39 import java.util.ArrayList; 40 import java.util.Set; 41 42 /** 43 * The {@link com.android.server.pm.PackageManagerService} maintains some 44 * {@link IntentFilterVerificationInfo}s for each domain / package name. 45 * 46 * @hide 47 */ 48 @SystemApi 49 public final class IntentFilterVerificationInfo implements Parcelable { 50 private static final String TAG = IntentFilterVerificationInfo.class.getName(); 51 52 private static final String TAG_DOMAIN = "domain"; 53 private static final String ATTR_DOMAIN_NAME = "name"; 54 private static final String ATTR_PACKAGE_NAME = "packageName"; 55 private static final String ATTR_STATUS = "status"; 56 57 private ArraySet<String> mDomains = new ArraySet<>(); 58 private String mPackageName; 59 private int mMainStatus; 60 61 /** @hide */ IntentFilterVerificationInfo()62 public IntentFilterVerificationInfo() { 63 mPackageName = null; 64 mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; 65 } 66 67 /** @hide */ IntentFilterVerificationInfo(String packageName, ArraySet<String> domains)68 public IntentFilterVerificationInfo(String packageName, ArraySet<String> domains) { 69 mPackageName = packageName; 70 mDomains = domains; 71 mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; 72 } 73 74 /** @hide */ IntentFilterVerificationInfo(XmlPullParser parser)75 public IntentFilterVerificationInfo(XmlPullParser parser) 76 throws IOException, XmlPullParserException { 77 readFromXml(parser); 78 } 79 80 /** @hide */ IntentFilterVerificationInfo(Parcel source)81 public IntentFilterVerificationInfo(Parcel source) { 82 readFromParcel(source); 83 } 84 getPackageName()85 public String getPackageName() { 86 return mPackageName; 87 } 88 getStatus()89 public int getStatus() { 90 return mMainStatus; 91 } 92 93 /** @hide */ setStatus(int s)94 public void setStatus(int s) { 95 if (s >= INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED && 96 s <= INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) { 97 mMainStatus = s; 98 } else { 99 Log.w(TAG, "Trying to set a non supported status: " + s); 100 } 101 } 102 getDomains()103 public Set<String> getDomains() { 104 return mDomains; 105 } 106 107 /** @hide */ setDomains(ArraySet<String> list)108 public void setDomains(ArraySet<String> list) { 109 mDomains = list; 110 } 111 112 /** @hide */ getDomainsString()113 public String getDomainsString() { 114 StringBuilder sb = new StringBuilder(); 115 for (String str : mDomains) { 116 if (sb.length() > 0) { 117 sb.append(" "); 118 } 119 sb.append(str); 120 } 121 return sb.toString(); 122 } 123 getStringFromXml(XmlPullParser parser, String attribute, String defaultValue)124 String getStringFromXml(XmlPullParser parser, String attribute, String defaultValue) { 125 String value = parser.getAttributeValue(null, attribute); 126 if (value == null) { 127 String msg = "Missing element under " + TAG +": " + attribute + " at " + 128 parser.getPositionDescription(); 129 Log.w(TAG, msg); 130 return defaultValue; 131 } else { 132 return value; 133 } 134 } 135 getIntFromXml(XmlPullParser parser, String attribute, int defaultValue)136 int getIntFromXml(XmlPullParser parser, String attribute, int defaultValue) { 137 String value = parser.getAttributeValue(null, attribute); 138 if (TextUtils.isEmpty(value)) { 139 String msg = "Missing element under " + TAG +": " + attribute + " at " + 140 parser.getPositionDescription(); 141 Log.w(TAG, msg); 142 return defaultValue; 143 } else { 144 return Integer.parseInt(value); 145 } 146 } 147 148 /** @hide */ readFromXml(XmlPullParser parser)149 public void readFromXml(XmlPullParser parser) throws XmlPullParserException, 150 IOException { 151 mPackageName = getStringFromXml(parser, ATTR_PACKAGE_NAME, null); 152 if (mPackageName == null) { 153 Log.e(TAG, "Package name cannot be null!"); 154 } 155 int status = getIntFromXml(parser, ATTR_STATUS, -1); 156 if (status == -1) { 157 Log.e(TAG, "Unknown status value: " + status); 158 } 159 mMainStatus = status; 160 161 int outerDepth = parser.getDepth(); 162 int type; 163 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 164 && (type != XmlPullParser.END_TAG 165 || parser.getDepth() > outerDepth)) { 166 if (type == XmlPullParser.END_TAG 167 || type == XmlPullParser.TEXT) { 168 continue; 169 } 170 171 String tagName = parser.getName(); 172 if (tagName.equals(TAG_DOMAIN)) { 173 String name = getStringFromXml(parser, ATTR_DOMAIN_NAME, null); 174 if (!TextUtils.isEmpty(name)) { 175 mDomains.add(name); 176 } 177 } else { 178 Log.w(TAG, "Unknown tag parsing IntentFilter: " + tagName); 179 } 180 XmlUtils.skipCurrentTag(parser); 181 } 182 } 183 184 /** @hide */ writeToXml(XmlSerializer serializer)185 public void writeToXml(XmlSerializer serializer) throws IOException { 186 serializer.attribute(null, ATTR_PACKAGE_NAME, mPackageName); 187 serializer.attribute(null, ATTR_STATUS, String.valueOf(mMainStatus)); 188 for (String str : mDomains) { 189 serializer.startTag(null, TAG_DOMAIN); 190 serializer.attribute(null, ATTR_DOMAIN_NAME, str); 191 serializer.endTag(null, TAG_DOMAIN); 192 } 193 } 194 195 /** @hide */ getStatusString()196 public String getStatusString() { 197 return getStatusStringFromValue(((long)mMainStatus) << 32); 198 } 199 200 /** @hide */ getStatusStringFromValue(long val)201 public static String getStatusStringFromValue(long val) { 202 StringBuilder sb = new StringBuilder(); 203 switch ((int)(val >> 32)) { 204 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: 205 sb.append("always : "); 206 sb.append(Long.toHexString(val & 0x00000000FFFFFFFF)); 207 break; 208 209 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: 210 sb.append("ask"); 211 break; 212 213 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: 214 sb.append("never"); 215 break; 216 217 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK: 218 sb.append("always-ask"); 219 break; 220 221 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: 222 default: 223 sb.append("undefined"); 224 break; 225 } 226 return sb.toString(); 227 } 228 229 @Override describeContents()230 public int describeContents() { 231 return 0; 232 } 233 readFromParcel(Parcel source)234 private void readFromParcel(Parcel source) { 235 mPackageName = source.readString(); 236 mMainStatus = source.readInt(); 237 ArrayList<String> list = new ArrayList<>(); 238 source.readStringList(list); 239 mDomains.addAll(list); 240 } 241 242 @Override writeToParcel(Parcel dest, int flags)243 public void writeToParcel(Parcel dest, int flags) { 244 dest.writeString(mPackageName); 245 dest.writeInt(mMainStatus); 246 dest.writeStringList(new ArrayList<>(mDomains)); 247 } 248 249 public static final @android.annotation.NonNull Creator<IntentFilterVerificationInfo> CREATOR = 250 new Creator<IntentFilterVerificationInfo>() { 251 public IntentFilterVerificationInfo createFromParcel(Parcel source) { 252 return new IntentFilterVerificationInfo(source); 253 } 254 public IntentFilterVerificationInfo[] newArray(int size) { 255 return new IntentFilterVerificationInfo[size]; 256 } 257 }; 258 } 259