/* * Copyright (C) 2015 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 android.content.pm; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.util.ArrayList; /** * The {@link com.android.server.pm.PackageManagerService} maintains some * {@link IntentFilterVerificationInfo}s for each domain / package name. * * @hide */ public final class IntentFilterVerificationInfo implements Parcelable { private static final String TAG = IntentFilterVerificationInfo.class.getName(); private static final String TAG_DOMAIN = "domain"; private static final String ATTR_DOMAIN_NAME = "name"; private static final String ATTR_PACKAGE_NAME = "packageName"; private static final String ATTR_STATUS = "status"; private ArraySet mDomains = new ArraySet<>(); private String mPackageName; private int mMainStatus; public IntentFilterVerificationInfo() { mPackageName = null; mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; } public IntentFilterVerificationInfo(String packageName, ArrayList domains) { mPackageName = packageName; mDomains.addAll(domains); mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; } public IntentFilterVerificationInfo(XmlPullParser parser) throws IOException, XmlPullParserException { readFromXml(parser); } public IntentFilterVerificationInfo(Parcel source) { readFromParcel(source); } public String getPackageName() { return mPackageName; } public int getStatus() { return mMainStatus; } public void setStatus(int s) { if (s >= INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED && s <= INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) { mMainStatus = s; } else { Log.w(TAG, "Trying to set a non supported status: " + s); } } public ArraySet getDomains() { return mDomains; } public void setDomains(ArrayList list) { mDomains = new ArraySet<>(list); } public String getDomainsString() { StringBuilder sb = new StringBuilder(); for (String str : mDomains) { if (sb.length() > 0) { sb.append(" "); } sb.append(str); } return sb.toString(); } String getStringFromXml(XmlPullParser parser, String attribute, String defaultValue) { String value = parser.getAttributeValue(null, attribute); if (value == null) { String msg = "Missing element under " + TAG +": " + attribute + " at " + parser.getPositionDescription(); Log.w(TAG, msg); return defaultValue; } else { return value; } } int getIntFromXml(XmlPullParser parser, String attribute, int defaultValue) { String value = parser.getAttributeValue(null, attribute); if (TextUtils.isEmpty(value)) { String msg = "Missing element under " + TAG +": " + attribute + " at " + parser.getPositionDescription(); Log.w(TAG, msg); return defaultValue; } else { return Integer.parseInt(value); } } public void readFromXml(XmlPullParser parser) throws XmlPullParserException, IOException { mPackageName = getStringFromXml(parser, ATTR_PACKAGE_NAME, null); if (mPackageName == null) { Log.e(TAG, "Package name cannot be null!"); } int status = getIntFromXml(parser, ATTR_STATUS, -1); if (status == -1) { Log.e(TAG, "Unknown status value: " + status); } mMainStatus = status; 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(); if (tagName.equals(TAG_DOMAIN)) { String name = getStringFromXml(parser, ATTR_DOMAIN_NAME, null); if (!TextUtils.isEmpty(name)) { mDomains.add(name); } } else { Log.w(TAG, "Unknown tag parsing IntentFilter: " + tagName); } XmlUtils.skipCurrentTag(parser); } } public void writeToXml(XmlSerializer serializer) throws IOException { serializer.attribute(null, ATTR_PACKAGE_NAME, mPackageName); serializer.attribute(null, ATTR_STATUS, String.valueOf(mMainStatus)); for (String str : mDomains) { serializer.startTag(null, TAG_DOMAIN); serializer.attribute(null, ATTR_DOMAIN_NAME, str); serializer.endTag(null, TAG_DOMAIN); } } public String getStatusString() { return getStatusStringFromValue(mMainStatus); } public static String getStatusStringFromValue(long val) { StringBuilder sb = new StringBuilder(); switch ((int)(val >> 32)) { case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: sb.append("always : "); sb.append(Long.toHexString(val & 0x00000000FFFFFFFF)); break; case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: sb.append("ask"); break; case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: sb.append("never"); break; case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK: sb.append("always-ask"); break; case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: default: sb.append("undefined"); break; } return sb.toString(); } @Override public int describeContents() { return 0; } private void readFromParcel(Parcel source) { mPackageName = source.readString(); mMainStatus = source.readInt(); ArrayList list = new ArrayList<>(); source.readStringList(list); mDomains.addAll(list); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mPackageName); dest.writeInt(mMainStatus); dest.writeStringList(new ArrayList<>(mDomains)); } public static final Creator CREATOR = new Creator() { public IntentFilterVerificationInfo createFromParcel(Parcel source) { return new IntentFilterVerificationInfo(source); } public IntentFilterVerificationInfo[] newArray(int size) { return new IntentFilterVerificationInfo[size]; } }; }