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