1 /* 2 * Copyright (C) 2023 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.app.admin; 18 19 import static android.app.admin.PolicyUpdateReceiver.EXTRA_INTENT_FILTER; 20 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_BUNDLE_KEY; 21 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_KEY; 22 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.SystemApi; 26 import android.annotation.TestApi; 27 import android.content.IntentFilter; 28 import android.os.Bundle; 29 import android.os.Parcel; 30 import android.os.Parcelable; 31 import android.util.Log; 32 33 import com.android.internal.util.XmlUtils; 34 import com.android.modules.utils.TypedXmlPullParser; 35 import com.android.modules.utils.TypedXmlSerializer; 36 37 import org.xmlpull.v1.XmlPullParserException; 38 39 import java.io.IOException; 40 import java.util.Objects; 41 42 /** 43 * Class used to identify a policy that relates to a certain {@link IntentFilter} 44 * (e.g. {@link DevicePolicyManager#addPersistentPreferredActivity}). 45 * 46 * @hide 47 */ 48 @SystemApi 49 public final class IntentFilterPolicyKey extends PolicyKey { 50 51 private static final String TAG = "IntentFilterPolicyKey"; 52 53 private static final String TAG_INTENT_FILTER_ENTRY = "filter"; 54 private final IntentFilter mFilter; 55 56 /** 57 * @hide 58 */ 59 @TestApi IntentFilterPolicyKey(@onNull String identifier, @NonNull IntentFilter filter)60 public IntentFilterPolicyKey(@NonNull String identifier, @NonNull IntentFilter filter) { 61 super(identifier); 62 mFilter = Objects.requireNonNull(filter); 63 } 64 65 /** 66 * @hide 67 */ IntentFilterPolicyKey(@onNull String identifier)68 public IntentFilterPolicyKey(@NonNull String identifier) { 69 super(identifier); 70 mFilter = null; 71 } 72 IntentFilterPolicyKey(Parcel source)73 private IntentFilterPolicyKey(Parcel source) { 74 super(source.readString()); 75 mFilter = source.readTypedObject(IntentFilter.CREATOR); 76 } 77 78 /** 79 * Returns the {@link IntentFilter} this policy relates to. 80 */ 81 @NonNull getIntentFilter()82 public IntentFilter getIntentFilter() { 83 return mFilter; 84 } 85 86 /** 87 * @hide 88 */ 89 @Override saveToXml(TypedXmlSerializer serializer)90 public void saveToXml(TypedXmlSerializer serializer) throws IOException { 91 serializer.attribute(/* namespace= */ null, ATTR_POLICY_IDENTIFIER, getIdentifier()); 92 serializer.startTag(/* namespace= */ null, TAG_INTENT_FILTER_ENTRY); 93 mFilter.writeToXml(serializer); 94 serializer.endTag(/* namespace= */ null, TAG_INTENT_FILTER_ENTRY); 95 } 96 97 /** 98 * @hide 99 */ 100 @Override readFromXml(TypedXmlPullParser parser)101 public IntentFilterPolicyKey readFromXml(TypedXmlPullParser parser) 102 throws XmlPullParserException, IOException { 103 String identifier = parser.getAttributeValue(/* namespace= */ null, ATTR_POLICY_IDENTIFIER); 104 IntentFilter filter = readIntentFilterFromXml(parser); 105 return new IntentFilterPolicyKey(identifier, filter); 106 } 107 108 @Nullable readIntentFilterFromXml(TypedXmlPullParser parser)109 private IntentFilter readIntentFilterFromXml(TypedXmlPullParser parser) 110 throws XmlPullParserException, IOException { 111 int outerDepth = parser.getDepth(); 112 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 113 String tag = parser.getName(); 114 if (tag.equals(TAG_INTENT_FILTER_ENTRY)) { 115 IntentFilter filter = new IntentFilter(); 116 filter.readFromXml(parser); 117 return filter; 118 } 119 Log.e(TAG, "Unknown tag: " + tag); 120 } 121 Log.e(TAG, "Error parsing IntentFilterPolicyKey, IntentFilter not found"); 122 return null; 123 } 124 125 /** 126 * @hide 127 */ 128 @Override writeToBundle(Bundle bundle)129 public void writeToBundle(Bundle bundle) { 130 bundle.putString(EXTRA_POLICY_KEY, getIdentifier()); 131 Bundle extraPolicyParams = new Bundle(); 132 extraPolicyParams.putParcelable(EXTRA_INTENT_FILTER, mFilter); 133 bundle.putBundle(EXTRA_POLICY_BUNDLE_KEY, extraPolicyParams); 134 } 135 136 @Override equals(@ullable Object o)137 public boolean equals(@Nullable Object o) { 138 if (this == o) return true; 139 if (o == null || getClass() != o.getClass()) return false; 140 IntentFilterPolicyKey other = (IntentFilterPolicyKey) o; 141 return Objects.equals(getIdentifier(), other.getIdentifier()) 142 && IntentFilter.filterEquals(mFilter, other.mFilter); 143 } 144 145 @Override hashCode()146 public int hashCode() { 147 return Objects.hash(getIdentifier()); 148 } 149 150 @Override toString()151 public String toString() { 152 return "IntentFilterPolicyKey{mKey= " + getIdentifier() + "; mFilter= " + mFilter + "}"; 153 } 154 155 @Override describeContents()156 public int describeContents() { 157 return 0; 158 } 159 160 @Override writeToParcel(@onNull Parcel dest, int flags)161 public void writeToParcel(@NonNull Parcel dest, int flags) { 162 dest.writeString(getIdentifier()); 163 dest.writeTypedObject(mFilter, flags); 164 } 165 166 @NonNull 167 public static final Parcelable.Creator<IntentFilterPolicyKey> CREATOR = 168 new Parcelable.Creator<IntentFilterPolicyKey>() { 169 @Override 170 public IntentFilterPolicyKey createFromParcel(Parcel source) { 171 return new IntentFilterPolicyKey(source); 172 } 173 174 @Override 175 public IntentFilterPolicyKey[] newArray(int size) { 176 return new IntentFilterPolicyKey[size]; 177 } 178 }; 179 } 180