• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
20 import static org.xmlpull.v1.XmlPullParser.END_TAG;
21 import static org.xmlpull.v1.XmlPullParser.TEXT;
22 
23 import android.annotation.IntDef;
24 import android.annotation.NonNull;
25 import android.annotation.SuppressLint;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 import android.util.IndentingPrintWriter;
29 import android.util.Log;
30 import android.util.TypedXmlPullParser;
31 import android.util.TypedXmlSerializer;
32 
33 import org.xmlpull.v1.XmlPullParserException;
34 
35 import java.io.IOException;
36 import java.lang.annotation.Retention;
37 import java.lang.annotation.RetentionPolicy;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Collection;
41 import java.util.List;
42 import java.util.Objects;
43 import java.util.stream.Collectors;
44 
45 /**
46  * Network configuration to be set for the user profile
47  * {@see DevicePolicyManager#setPreferentialNetworkServiceConfigs}.
48  */
49 public final class PreferentialNetworkServiceConfig implements Parcelable {
50     final boolean mIsEnabled;
51     final int mNetworkId;
52     final boolean mAllowFallbackToDefaultConnection;
53     final int[] mIncludedUids;
54     final int[] mExcludedUids;
55 
56     private static final String LOG_TAG = "PreferentialNetworkServiceConfig";
57     private static final String TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIG =
58             "preferential_network_service_config";
59     private static final String TAG_CONFIG_ENABLED =
60             "preferential_network_service_config_enabled";
61     private static final String TAG_UID = "uid";
62     private static final String TAG_NETWORK_ID =
63             "preferential_network_service_network_id";
64     private static final String TAG_ALLOW_FALLBACK_TO_DEFAULT_CONNECTION =
65             "allow_fallback_to_default_connection";
66     private static final String TAG_INCLUDED_UIDS = "included_uids";
67     private static final String TAG_EXCLUDED_UIDS = "excluded_uids";
68     private static final String ATTR_VALUE = "value";
69 
70     /** @hide */
71     public static final PreferentialNetworkServiceConfig DEFAULT =
72             (new PreferentialNetworkServiceConfig.Builder()).build();
73 
74     /**
75      * Preferential network identifier 1.
76      */
77     public static final int PREFERENTIAL_NETWORK_ID_1 = 1;
78 
79     /**
80      * Preferential network identifier 2.
81      */
82     public static final int PREFERENTIAL_NETWORK_ID_2 = 2;
83 
84     /**
85      * Preferential network identifier 3.
86      */
87     public static final int PREFERENTIAL_NETWORK_ID_3 = 3;
88 
89     /**
90      * Preferential network identifier 4.
91      */
92     public static final int PREFERENTIAL_NETWORK_ID_4 = 4;
93 
94     /**
95      * Preferential network identifier 5.
96      */
97     public static final int PREFERENTIAL_NETWORK_ID_5 = 5;
98 
99     /** @hide */
100     @Retention(RetentionPolicy.SOURCE)
101     @IntDef(prefix = { "PREFERENTIAL_NETWORK_ID_" }, value = {
102             PREFERENTIAL_NETWORK_ID_1,
103             PREFERENTIAL_NETWORK_ID_2,
104             PREFERENTIAL_NETWORK_ID_3,
105             PREFERENTIAL_NETWORK_ID_4,
106             PREFERENTIAL_NETWORK_ID_5,
107     })
108 
109     public @interface PreferentialNetworkPreferenceId {
110     }
111 
PreferentialNetworkServiceConfig(boolean isEnabled, boolean allowFallbackToDefaultConnection, int[] includedUids, int[] excludedUids, @PreferentialNetworkPreferenceId int networkId)112     private PreferentialNetworkServiceConfig(boolean isEnabled,
113             boolean allowFallbackToDefaultConnection, int[] includedUids,
114             int[] excludedUids, @PreferentialNetworkPreferenceId int networkId) {
115         mIsEnabled = isEnabled;
116         mAllowFallbackToDefaultConnection = allowFallbackToDefaultConnection;
117         mIncludedUids = includedUids;
118         mExcludedUids = excludedUids;
119         mNetworkId = networkId;
120     }
121 
PreferentialNetworkServiceConfig(Parcel in)122     private PreferentialNetworkServiceConfig(Parcel in) {
123         mIsEnabled = in.readBoolean();
124         mAllowFallbackToDefaultConnection = in.readBoolean();
125         mNetworkId = in.readInt();
126         mIncludedUids = in.createIntArray();
127         mExcludedUids = in.createIntArray();
128     }
129 
130     /**
131      * Is the preferential network enabled.
132      * @return true if enabled else false
133      */
isEnabled()134     public boolean isEnabled() {
135         return mIsEnabled;
136     }
137 
138     /**
139      * is fallback to default network allowed. This boolean configures whether default connection
140      * (default internet or wifi) should be used or not if a preferential network service
141      * connection is not available.
142      * @return true if fallback is allowed, else false.
143      */
isFallbackToDefaultConnectionAllowed()144     public boolean isFallbackToDefaultConnectionAllowed() {
145         return mAllowFallbackToDefaultConnection;
146     }
147 
148     /**
149      * Get the array of uids that are applicable for the profile preference.
150      *
151      * {@see #getExcludedUids()}
152      * Included UIDs and Excluded UIDs can't both be non-empty.
153      * if both are empty, it means this request applies to all uids in the user profile.
154      * if included is not empty, then only included UIDs are applied.
155      * if excluded is not empty, then it is all uids in the user profile except these UIDs.
156      * @return Array of uids applicable for the profile preference.
157      *      Empty array would mean that this request applies to all uids in the profile.
158      */
getIncludedUids()159     public @NonNull int[] getIncludedUids() {
160         return mIncludedUids;
161     }
162 
163     /**
164      * Get the array of uids that are excluded for the profile preference.
165      *
166      * {@see #getIncludedUids()}
167      * Included UIDs and Excluded UIDs can't both be non-empty.
168      * if both are empty, it means this request applies to all uids in the user profile.
169      * if included is not empty, then only included UIDs are applied.
170      * if excluded is not empty, then it is all uids in the user profile except these UIDs.
171      * @return Array of uids that are excluded for the profile preference.
172      *      Empty array would mean that this request applies to all uids in the profile.
173      */
getExcludedUids()174     public @NonNull int[] getExcludedUids() {
175         return mExcludedUids;
176     }
177 
178     /**
179      * @return preference enterprise identifier.
180      * preference identifier is applicable only if preference network service is enabled
181      *
182      */
getNetworkId()183     public @PreferentialNetworkPreferenceId int getNetworkId() {
184         return mNetworkId;
185     }
186 
187     @Override
toString()188     public String toString() {
189         return "PreferentialNetworkServiceConfig{"
190                 + "mIsEnabled=" + isEnabled()
191                 + "mAllowFallbackToDefaultConnection=" + isFallbackToDefaultConnectionAllowed()
192                 + "mIncludedUids=" + Arrays.toString(mIncludedUids)
193                 + "mExcludedUids=" + Arrays.toString(mExcludedUids)
194                 + "mNetworkId=" + mNetworkId
195                 + '}';
196     }
197 
198     @Override
equals(Object o)199     public boolean equals(Object o) {
200         if (this == o) return true;
201         if (o == null || getClass() != o.getClass()) return false;
202         final PreferentialNetworkServiceConfig that = (PreferentialNetworkServiceConfig) o;
203         return mIsEnabled == that.mIsEnabled
204                 && mAllowFallbackToDefaultConnection == that.mAllowFallbackToDefaultConnection
205                 && mNetworkId == that.mNetworkId
206                 && Objects.equals(mIncludedUids, that.mIncludedUids)
207                 && Objects.equals(mExcludedUids, that.mExcludedUids);
208     }
209 
210     @Override
hashCode()211     public int hashCode() {
212         return ((Objects.hashCode(mIsEnabled) * 17)
213                 + (Objects.hashCode(mAllowFallbackToDefaultConnection) * 19)
214                 + (Objects.hashCode(mIncludedUids) * 23)
215                 + (Objects.hashCode(mExcludedUids) * 29)
216                 + mNetworkId * 31);
217     }
218 
219     /**
220      * Builder used to create {@link PreferentialNetworkServiceConfig} objects.
221      * Specify the preferred Network preference
222      */
223     public static final class Builder {
224         boolean mIsEnabled = false;
225         int mNetworkId = 0;
226         boolean mAllowFallbackToDefaultConnection = true;
227         int[] mIncludedUids = new int[0];
228         int[] mExcludedUids = new int[0];
229 
230         /**
231          * Constructs an empty Builder with preferential network disabled by default.
232          */
Builder()233         public Builder() {}
234 
235         /**
236          * Set the preferential network service enabled state.
237          * Default value is false.
238          * @param isEnabled  the desired network preference to use, true to enable else false
239          * @return The builder to facilitate chaining.
240          */
241         @NonNull
setEnabled(boolean isEnabled)242         public PreferentialNetworkServiceConfig.Builder setEnabled(boolean isEnabled) {
243             mIsEnabled = isEnabled;
244             return this;
245         }
246 
247         /**
248          * Set whether the default connection should be used as fallback.
249          * This boolean configures whether the default connection (default internet or wifi)
250          * should be used if a preferential network service connection is not available.
251          * Default value is true
252          * @param allowFallbackToDefaultConnection  true if fallback is allowed else false
253          * @return The builder to facilitate chaining.
254          */
255         @NonNull
256         @SuppressLint("MissingGetterMatchingBuilder")
setFallbackToDefaultConnectionAllowed( boolean allowFallbackToDefaultConnection)257         public PreferentialNetworkServiceConfig.Builder setFallbackToDefaultConnectionAllowed(
258                 boolean allowFallbackToDefaultConnection) {
259             mAllowFallbackToDefaultConnection = allowFallbackToDefaultConnection;
260             return this;
261         }
262 
263         /**
264          * Set the array of uids whose network access will go through this preferential
265          * network service.
266          * {@see #setExcludedUids(int[])}
267          * Included UIDs and Excluded UIDs can't both be non-empty.
268          * if both are empty, it means this request applies to all uids in the user profile.
269          * if included is not empty, then only included UIDs are applied.
270          * if excluded is not empty, then it is all uids in the user profile except these UIDs.
271          * @param uids  array of included uids
272          * @return The builder to facilitate chaining.
273          */
274         @NonNull
setIncludedUids( @onNull int[] uids)275         public PreferentialNetworkServiceConfig.Builder setIncludedUids(
276                 @NonNull int[] uids) {
277             Objects.requireNonNull(uids);
278             mIncludedUids = uids;
279             return this;
280         }
281 
282         /**
283          * Set the array of uids who are not allowed through this preferential
284          * network service.
285          * {@see #setIncludedUids(int[])}
286          * Included UIDs and Excluded UIDs can't both be non-empty.
287          * if both are empty, it means this request applies to all uids in the user profile.
288          * if included is not empty, then only included UIDs are applied.
289          * if excluded is not empty, then it is all uids in the user profile except these UIDs.
290          * @param uids  array of excluded uids
291          * @return The builder to facilitate chaining.
292          */
293         @NonNull
setExcludedUids( @onNull int[] uids)294         public PreferentialNetworkServiceConfig.Builder setExcludedUids(
295                 @NonNull int[] uids) {
296             Objects.requireNonNull(uids);
297             mExcludedUids = uids;
298             return this;
299         }
300 
301         /**
302          * Returns an instance of {@link PreferentialNetworkServiceConfig} created from the
303          * fields set on this builder.
304          */
305         @NonNull
build()306         public PreferentialNetworkServiceConfig build() {
307             if (mIncludedUids.length > 0 && mExcludedUids.length > 0) {
308                 throw new IllegalStateException("Both includedUids and excludedUids "
309                         + "cannot be nonempty");
310             }
311             return new PreferentialNetworkServiceConfig(mIsEnabled,
312                     mAllowFallbackToDefaultConnection, mIncludedUids, mExcludedUids, mNetworkId);
313         }
314 
315         /**
316          * Set the preferential network identifier.
317          * preference identifier is applicable only if preferential network service is enabled.
318          * @param preferenceId  preference Id
319          * @return The builder to facilitate chaining.
320          */
321         @NonNull
setNetworkId( @referentialNetworkPreferenceId int preferenceId)322         public PreferentialNetworkServiceConfig.Builder setNetworkId(
323                 @PreferentialNetworkPreferenceId int preferenceId) {
324             if ((preferenceId < PREFERENTIAL_NETWORK_ID_1)
325                     || (preferenceId > PREFERENTIAL_NETWORK_ID_5)) {
326                 throw new IllegalArgumentException("Invalid preference identifier");
327             }
328             mNetworkId = preferenceId;
329             return this;
330         }
331     }
332 
333     @Override
writeToParcel(@onNull android.os.Parcel dest, int flags)334     public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
335         dest.writeBoolean(mIsEnabled);
336         dest.writeBoolean(mAllowFallbackToDefaultConnection);
337         dest.writeInt(mNetworkId);
338         dest.writeIntArray(mIncludedUids);
339         dest.writeIntArray(mExcludedUids);
340     }
341 
writeAttributeValueToXml(TypedXmlSerializer out, String tag, int value)342     private void writeAttributeValueToXml(TypedXmlSerializer out, String tag, int value)
343             throws IOException {
344         out.startTag(null, tag);
345         out.attributeInt(null, ATTR_VALUE, value);
346         out.endTag(null, tag);
347     }
348 
writeAttributeValueToXml(TypedXmlSerializer out, String tag, boolean value)349     private void writeAttributeValueToXml(TypedXmlSerializer out, String tag, boolean value)
350             throws IOException {
351         out.startTag(null, tag);
352         out.attributeBoolean(null, ATTR_VALUE, value);
353         out.endTag(null, tag);
354     }
355 
writeAttributeValuesToXml(TypedXmlSerializer out, String outerTag, String innerTag, @NonNull Collection<String> values)356     private void writeAttributeValuesToXml(TypedXmlSerializer out, String outerTag, String innerTag,
357             @NonNull Collection<String> values) throws IOException {
358         out.startTag(null, outerTag);
359         for (String value : values) {
360             out.startTag(null, innerTag);
361             out.attribute(null, ATTR_VALUE, value);
362             out.endTag(null, innerTag);
363         }
364         out.endTag(null, outerTag);
365     }
366 
readAttributeValues( TypedXmlPullParser parser, String tag, Collection<String> result)367     private static  void readAttributeValues(
368             TypedXmlPullParser parser, String tag, Collection<String> result)
369             throws XmlPullParserException, IOException {
370         result.clear();
371         int outerDepthDAM = parser.getDepth();
372         int typeDAM;
373         while ((typeDAM = parser.next()) != END_DOCUMENT
374                 && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
375             if (typeDAM == END_TAG || typeDAM == TEXT) {
376                 continue;
377             }
378             String tagDAM = parser.getName();
379             if (tag.equals(tagDAM)) {
380                 result.add(parser.getAttributeValue(null, ATTR_VALUE));
381             } else {
382                 Log.e(LOG_TAG, "Expected tag " + tag + " but found " + tagDAM);
383             }
384         }
385     }
386 
intArrayToStringList(int[] array)387     private List<String> intArrayToStringList(int[] array) {
388         return Arrays.stream(array).mapToObj(String::valueOf).collect(Collectors.toList());
389     }
390 
readStringListToIntArray(TypedXmlPullParser parser, String tag)391     private static int[] readStringListToIntArray(TypedXmlPullParser parser, String tag)
392             throws XmlPullParserException, IOException {
393         List<String> stringList = new ArrayList<>();
394         readAttributeValues(parser, tag, stringList);
395         int[] intArray = stringList.stream()
396                 .map(s -> Integer.parseInt(s))
397                 .mapToInt(Integer::intValue)
398                 .toArray();
399         return intArray;
400     }
401 
402     /**
403      * @hide
404      */
getPreferentialNetworkServiceConfig( TypedXmlPullParser parser, String tag)405     public static PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig(
406             TypedXmlPullParser parser, String tag) throws XmlPullParserException, IOException  {
407         int outerDepthDAM = parser.getDepth();
408         int typeDAM;
409         PreferentialNetworkServiceConfig.Builder resultBuilder =
410                 new PreferentialNetworkServiceConfig.Builder();
411         while ((typeDAM = parser.next()) != END_DOCUMENT
412                 && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
413             if (typeDAM == END_TAG || typeDAM == TEXT) {
414                 continue;
415             }
416             String tagDAM = parser.getName();
417             if (TAG_CONFIG_ENABLED.equals(tagDAM)) {
418                 resultBuilder.setEnabled(parser.getAttributeBoolean(null, ATTR_VALUE,
419                         DevicePolicyManager.PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT));
420             } else if (TAG_NETWORK_ID.equals(tagDAM)) {
421                 int val = parser.getAttributeInt(null, ATTR_VALUE, 0);
422                 if (val != 0) {
423                     resultBuilder.setNetworkId(val);
424                 }
425             } else if (TAG_ALLOW_FALLBACK_TO_DEFAULT_CONNECTION.equals(tagDAM)) {
426                 resultBuilder.setFallbackToDefaultConnectionAllowed(parser.getAttributeBoolean(
427                         null, ATTR_VALUE, true));
428             } else if (TAG_INCLUDED_UIDS.equals(tagDAM)) {
429                 resultBuilder.setIncludedUids(readStringListToIntArray(parser, TAG_UID));
430             } else if (TAG_EXCLUDED_UIDS.equals(tagDAM)) {
431                 resultBuilder.setExcludedUids(readStringListToIntArray(parser, TAG_UID));
432             } else {
433                 Log.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
434             }
435         }
436         return resultBuilder.build();
437     }
438 
439     /**
440      * @hide
441      */
writeToXml(@onNull TypedXmlSerializer out)442     public void writeToXml(@NonNull TypedXmlSerializer out) throws IOException {
443         out.startTag(null, TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIG);
444         writeAttributeValueToXml(out, TAG_CONFIG_ENABLED, isEnabled());
445         writeAttributeValueToXml(out, TAG_NETWORK_ID, getNetworkId());
446         writeAttributeValueToXml(out, TAG_ALLOW_FALLBACK_TO_DEFAULT_CONNECTION,
447                 isFallbackToDefaultConnectionAllowed());
448         writeAttributeValuesToXml(out, TAG_INCLUDED_UIDS, TAG_UID,
449                 intArrayToStringList(getIncludedUids()));
450         writeAttributeValuesToXml(out, TAG_EXCLUDED_UIDS, TAG_UID,
451                 intArrayToStringList(getExcludedUids()));
452         out.endTag(null, TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIG);
453     }
454 
455     /**
456      * @hide
457      */
dump(IndentingPrintWriter pw)458     public void dump(IndentingPrintWriter pw) {
459         pw.print("networkId=");
460         pw.println(mNetworkId);
461         pw.print("isEnabled=");
462         pw.println(mIsEnabled);
463         pw.print("allowFallbackToDefaultConnection=");
464         pw.println(mAllowFallbackToDefaultConnection);
465         pw.print("includedUids=");
466         pw.println(mIncludedUids);
467         pw.print("excludedUids=");
468         pw.println(mExcludedUids);
469     }
470 
471     @Override
describeContents()472     public int describeContents() {
473         return 0;
474     }
475 
476     @NonNull
477     public static final Creator<PreferentialNetworkServiceConfig> CREATOR =
478             new Creator<PreferentialNetworkServiceConfig>() {
479                 @Override
480                 public PreferentialNetworkServiceConfig[] newArray(int size) {
481                     return new PreferentialNetworkServiceConfig[size];
482                 }
483 
484                 @Override
485                 public PreferentialNetworkServiceConfig createFromParcel(
486                         @NonNull android.os.Parcel in) {
487                     return new PreferentialNetworkServiceConfig(in);
488                 }
489             };
490 }
491