1 /*
2  * Copyright (C) 2021 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.net;
18 
19 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
20 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
21 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
22 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_5;
23 
24 import android.annotation.NonNull;
25 import android.annotation.SystemApi;
26 import android.net.ConnectivityManager.ProfileNetworkPreferencePolicy;
27 import android.os.Parcel;
28 import android.os.Parcelable;
29 
30 import java.util.Arrays;
31 import java.util.Objects;
32 
33 /**
34  * Network preferences to be set for the user profile
35  * {@link ProfileNetworkPreferencePolicy}.
36  * @hide
37  */
38 @SystemApi(client = MODULE_LIBRARIES)
39 public final class ProfileNetworkPreference implements Parcelable {
40     private final @ProfileNetworkPreferencePolicy int mPreference;
41     private final @NetworkCapabilities.EnterpriseId int mPreferenceEnterpriseId;
42     private int[] mIncludedUids = new int[0];
43     private int[] mExcludedUids = new int[0];
44 
ProfileNetworkPreference(int preference, int[] includedUids, int[] excludedUids, @NetworkCapabilities.EnterpriseId int preferenceEnterpriseId)45     private ProfileNetworkPreference(int preference, int[] includedUids,
46             int[] excludedUids,
47             @NetworkCapabilities.EnterpriseId int preferenceEnterpriseId) {
48         mPreference = preference;
49         mPreferenceEnterpriseId = preferenceEnterpriseId;
50         if (includedUids != null) {
51             mIncludedUids = includedUids.clone();
52         } else {
53             mIncludedUids = new int[0];
54         }
55 
56         if (excludedUids != null) {
57             mExcludedUids = excludedUids.clone();
58         } else {
59             mExcludedUids = new int[0];
60         }
61     }
62 
ProfileNetworkPreference(Parcel in)63     private ProfileNetworkPreference(Parcel in) {
64         mPreference = in.readInt();
65         in.readIntArray(mIncludedUids);
66         in.readIntArray(mExcludedUids);
67         mPreferenceEnterpriseId = in.readInt();
68     }
69 
getPreference()70     public int getPreference() {
71         return mPreference;
72     }
73 
74     /**
75      * Get the array of UIDs subject to this preference.
76      *
77      * Included UIDs and Excluded UIDs can't both be non-empty.
78      * if both are empty, it means this request applies to all uids in the user profile.
79      * if included is not empty, then only included UIDs are applied.
80      * if excluded is not empty, then it is all uids in the user profile except these UIDs.
81      * @return Array of uids included for the profile preference.
82      * @see #getExcludedUids()
83      */
getIncludedUids()84     public @NonNull int[] getIncludedUids() {
85         return mIncludedUids.clone();
86     }
87 
88     /**
89      * Get the array of UIDS excluded from this preference.
90      *
91      * <ul>Included UIDs and Excluded UIDs can't both be non-empty.</ul>
92      * <ul>If both are empty, it means this request applies to all uids in the user profile.</ul>
93      * <ul>If included is not empty, then only included UIDs are applied.</ul>
94      * <ul>If excluded is not empty, then it is all uids in the user profile except these UIDs.</ul>
95      * @return Array of uids not included for the profile preference.
96      * @see #getIncludedUids()
97      */
getExcludedUids()98     public @NonNull int[] getExcludedUids() {
99         return mExcludedUids.clone();
100     }
101 
102     /**
103      * Get preference enterprise identifier.
104      *
105      * Preference enterprise identifier will be used to create different network preferences
106      * within enterprise preference category.
107      * Valid values starts from PROFILE_NETWORK_PREFERENCE_ENTERPRISE_ID_1 to
108      * NetworkCapabilities.NET_ENTERPRISE_ID_5.
109      * Preference identifier is not applicable if preference is set as
110      * PROFILE_NETWORK_PREFERENCE_DEFAULT. Default value is
111      * NetworkCapabilities.NET_ENTERPRISE_ID_1.
112      * @return Preference enterprise identifier.
113      *
114      */
getPreferenceEnterpriseId()115     public @NetworkCapabilities.EnterpriseId int getPreferenceEnterpriseId() {
116         return mPreferenceEnterpriseId;
117     }
118 
119     @Override
toString()120     public String toString() {
121         return "ProfileNetworkPreference{"
122                 + "mPreference=" + getPreference()
123                 + "mIncludedUids=" + Arrays.toString(mIncludedUids)
124                 + "mExcludedUids=" + Arrays.toString(mExcludedUids)
125                 + "mPreferenceEnterpriseId=" + mPreferenceEnterpriseId
126                 + '}';
127     }
128 
129     @Override
equals(Object o)130     public boolean equals(Object o) {
131         if (this == o) return true;
132         if (o == null || getClass() != o.getClass()) return false;
133         final ProfileNetworkPreference that = (ProfileNetworkPreference) o;
134         return mPreference == that.mPreference
135                 && (Arrays.equals(mIncludedUids, that.mIncludedUids))
136                 && (Arrays.equals(mExcludedUids, that.mExcludedUids))
137                 && mPreferenceEnterpriseId == that.mPreferenceEnterpriseId;
138     }
139 
140     @Override
hashCode()141     public int hashCode() {
142         return mPreference
143                 + mPreferenceEnterpriseId * 2
144                 + (Arrays.hashCode(mIncludedUids) * 11)
145                 + (Arrays.hashCode(mExcludedUids) * 13);
146     }
147 
148     /**
149      * Builder used to create {@link ProfileNetworkPreference} objects.
150      * Specify the preferred Network preference
151      */
152     public static final class Builder {
153         private @ProfileNetworkPreferencePolicy int mPreference =
154                 PROFILE_NETWORK_PREFERENCE_DEFAULT;
155         private int[] mIncludedUids = new int[0];
156         private int[] mExcludedUids = new int[0];
157         private int mPreferenceEnterpriseId;
158 
159         /**
160          * Constructs an empty Builder with PROFILE_NETWORK_PREFERENCE_DEFAULT profile preference
161          */
Builder()162         public Builder() {}
163 
164         /**
165          * Set the profile network preference
166          * See the documentation for the individual preferences for a description of the supported
167          * behaviors. Default value is PROFILE_NETWORK_PREFERENCE_DEFAULT.
168          * @param preference  the desired network preference to use
169          * @return The builder to facilitate chaining.
170          */
171         @NonNull
setPreference(@rofileNetworkPreferencePolicy int preference)172         public Builder setPreference(@ProfileNetworkPreferencePolicy int preference) {
173             mPreference = preference;
174             return this;
175         }
176 
177         /**
178          * This is a array of uids for which profile perefence is set.
179          * Empty would mean that this preference applies to all uids in the profile.
180          * @see #setExcludedUids(int[])
181          * Included UIDs and Excluded UIDs can't both be non-empty.
182          * if both are empty, it means this request applies to all uids in the user profile.
183          * if included is not empty, then only included UIDs are applied.
184          * if excluded is not empty, then it is all uids in the user profile except these UIDs.
185          * @param uids  Array of uids that are included
186          * @return The builder to facilitate chaining.
187          */
188         @NonNull
setIncludedUids(@onNull int[] uids)189         public Builder setIncludedUids(@NonNull int[] uids) {
190             Objects.requireNonNull(uids);
191             mIncludedUids = uids.clone();
192             return this;
193         }
194 
195 
196         /**
197          * This is a array of uids that are excluded for the profile perefence.
198          * @see #setIncludedUids(int[])
199          * Included UIDs and Excluded UIDs can't both be non-empty.
200          * if both are empty, it means this request applies to all uids in the user profile.
201          * if included is not empty, then only included UIDs are applied.
202          * if excluded is not empty, then it is all uids in the user profile except these UIDs.
203          * @param uids  Array of uids that are not included
204          * @return The builder to facilitate chaining.
205          */
206         @NonNull
setExcludedUids(@onNull int[] uids)207         public Builder setExcludedUids(@NonNull int[] uids) {
208             Objects.requireNonNull(uids);
209             mExcludedUids = uids.clone();
210             return this;
211         }
212 
213         /**
214          * Check if given preference enterprise identifier is valid
215          *
216          * Valid values starts from PROFILE_NETWORK_PREFERENCE_ENTERPRISE_ID_1 to
217          * NetworkCapabilities.NET_ENTERPRISE_ID_5.
218          * @return True if valid else false
219          * @hide
220          */
isEnterpriseIdentifierValid( @etworkCapabilities.EnterpriseId int identifier)221         private boolean isEnterpriseIdentifierValid(
222                 @NetworkCapabilities.EnterpriseId int identifier) {
223             if ((identifier >= NET_ENTERPRISE_ID_1)
224                     && (identifier <= NET_ENTERPRISE_ID_5)) {
225                 return true;
226             }
227             return false;
228         }
229 
230         /**
231          * Returns an instance of {@link ProfileNetworkPreference} created from the
232          * fields set on this builder.
233          */
234         @NonNull
build()235         public ProfileNetworkPreference  build() {
236             if (mIncludedUids.length > 0 && mExcludedUids.length > 0) {
237                 throw new IllegalArgumentException("Both includedUids and excludedUids "
238                         + "cannot be nonempty");
239             }
240 
241             if (((mPreference != PROFILE_NETWORK_PREFERENCE_DEFAULT)
242                     && (!isEnterpriseIdentifierValid(mPreferenceEnterpriseId)))
243                     || ((mPreference == PROFILE_NETWORK_PREFERENCE_DEFAULT)
244                     && (mPreferenceEnterpriseId != 0))) {
245                 throw new IllegalStateException("Invalid preference enterprise identifier");
246             }
247             return new ProfileNetworkPreference(mPreference, mIncludedUids,
248                     mExcludedUids, mPreferenceEnterpriseId);
249         }
250 
251         /**
252          * Set the preference enterprise identifier.
253          *
254          * Preference enterprise identifier will be used to create different network preferences
255          * within enterprise preference category.
256          * Valid values starts from NetworkCapabilities.NET_ENTERPRISE_ID_1 to
257          * NetworkCapabilities.NET_ENTERPRISE_ID_5.
258          * Preference identifier is not applicable if preference is set as
259          * PROFILE_NETWORK_PREFERENCE_DEFAULT. Default value is
260          * NetworkCapabilities.NET_ENTERPRISE_ID_1.
261          * @param preferenceId  preference sub level
262          * @return The builder to facilitate chaining.
263          */
264         @NonNull
setPreferenceEnterpriseId( @etworkCapabilities.EnterpriseId int preferenceId)265         public Builder setPreferenceEnterpriseId(
266                 @NetworkCapabilities.EnterpriseId int preferenceId) {
267             mPreferenceEnterpriseId = preferenceId;
268             return this;
269         }
270     }
271 
272     @Override
writeToParcel(@onNull android.os.Parcel dest, int flags)273     public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
274         dest.writeInt(mPreference);
275         dest.writeIntArray(mIncludedUids);
276         dest.writeIntArray(mExcludedUids);
277         dest.writeInt(mPreferenceEnterpriseId);
278     }
279 
280     @Override
describeContents()281     public int describeContents() {
282         return 0;
283     }
284 
285     @NonNull
286     public static final Creator<ProfileNetworkPreference> CREATOR =
287             new Creator<ProfileNetworkPreference>() {
288                 @Override
289                 public ProfileNetworkPreference[] newArray(int size) {
290                     return new ProfileNetworkPreference[size];
291                 }
292 
293                 @Override
294                 public ProfileNetworkPreference  createFromParcel(
295                         @NonNull android.os.Parcel in) {
296                     return new ProfileNetworkPreference(in);
297                 }
298             };
299 }
300