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 android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.SystemApi; 22 import android.os.Bundle; 23 import android.os.Parcelable; 24 25 import java.lang.annotation.Retention; 26 import java.lang.annotation.RetentionPolicy; 27 import java.util.Collections; 28 import java.util.HashMap; 29 import java.util.Map; 30 import java.util.Objects; 31 32 /** 33 * Network preferences to set the default active network on a per-application basis as per a given 34 * {@link OemNetworkPreference}. An example of this would be to set an application's network 35 * preference to {@link #OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK} which would have the default 36 * network for that application set to an unmetered network first if available and if not, it then 37 * set that application's default network to an OEM managed network if available. 38 * 39 * @hide 40 */ 41 @SystemApi 42 public final class OemNetworkPreferences implements Parcelable { 43 // Valid production preferences must be > 0, negative values reserved for testing 44 /** 45 * This preference is only to be used for testing and nothing else. 46 * Use only TRANSPORT_TEST transport networks. 47 * @hide 48 */ 49 public static final int OEM_NETWORK_PREFERENCE_TEST_ONLY = -2; 50 51 /** 52 * This preference is only to be used for testing and nothing else. 53 * If an unmetered network is available, use it. 54 * Otherwise, if a network with the TRANSPORT_TEST transport is available, use it. 55 * Otherwise, use the general default network. 56 * @hide 57 */ 58 public static final int OEM_NETWORK_PREFERENCE_TEST = -1; 59 60 /** 61 * Default in case this value is not set. Using it will result in an error. 62 */ 63 public static final int OEM_NETWORK_PREFERENCE_UNINITIALIZED = 0; 64 65 /** 66 * If an unmetered network is available, use it. 67 * Otherwise, if a network with the OEM_PAID capability is available, use it. 68 * Otherwise, use the general default network. 69 */ 70 public static final int OEM_NETWORK_PREFERENCE_OEM_PAID = 1; 71 72 /** 73 * If an unmetered network is available, use it. 74 * Otherwise, if a network with the OEM_PAID capability is available, use it. 75 * Otherwise, the app doesn't get a default network. 76 */ 77 public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK = 2; 78 79 /** 80 * Use only NET_CAPABILITY_OEM_PAID networks. 81 */ 82 public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY = 3; 83 84 /** 85 * Use only NET_CAPABILITY_OEM_PRIVATE networks. 86 */ 87 public static final int OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY = 4; 88 89 /** 90 * The max allowed value for an OEM network preference. 91 * @hide 92 */ 93 public static final int OEM_NETWORK_PREFERENCE_MAX = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; 94 95 @NonNull 96 private final Bundle mNetworkMappings; 97 98 /** 99 * Return whether this object is empty. 100 * @hide 101 */ isEmpty()102 public boolean isEmpty() { 103 return mNetworkMappings.keySet().size() == 0; 104 } 105 106 /** 107 * Return the currently built application package name to {@link OemNetworkPreference} mappings. 108 * @return the current network preferences map. 109 */ 110 @NonNull getNetworkPreferences()111 public Map<String, Integer> getNetworkPreferences() { 112 return convertToUnmodifiableMap(mNetworkMappings); 113 } 114 OemNetworkPreferences(@onNull final Bundle networkMappings)115 private OemNetworkPreferences(@NonNull final Bundle networkMappings) { 116 Objects.requireNonNull(networkMappings); 117 mNetworkMappings = (Bundle) networkMappings.clone(); 118 } 119 120 @Override toString()121 public String toString() { 122 return "OemNetworkPreferences{" + "mNetworkMappings=" + getNetworkPreferences() + '}'; 123 } 124 125 @Override equals(Object o)126 public boolean equals(Object o) { 127 if (this == o) return true; 128 if (o == null || getClass() != o.getClass()) return false; 129 OemNetworkPreferences that = (OemNetworkPreferences) o; 130 131 return mNetworkMappings.size() == that.mNetworkMappings.size() 132 && mNetworkMappings.toString().equals(that.mNetworkMappings.toString()); 133 } 134 135 @Override hashCode()136 public int hashCode() { 137 return Objects.hash(mNetworkMappings); 138 } 139 140 /** 141 * Builder used to create {@link OemNetworkPreferences} objects. Specify the preferred Network 142 * to package name mappings. 143 */ 144 public static final class Builder { 145 private final Bundle mNetworkMappings; 146 Builder()147 public Builder() { 148 mNetworkMappings = new Bundle(); 149 } 150 151 /** 152 * Constructor to populate the builder's values with an already built 153 * {@link OemNetworkPreferences}. 154 * @param preferences the {@link OemNetworkPreferences} to populate with. 155 */ Builder(@onNull final OemNetworkPreferences preferences)156 public Builder(@NonNull final OemNetworkPreferences preferences) { 157 Objects.requireNonNull(preferences); 158 mNetworkMappings = (Bundle) preferences.mNetworkMappings.clone(); 159 } 160 161 /** 162 * Add a network preference for a given package. Previously stored values for the given 163 * package will be overwritten. 164 * 165 * @param packageName full package name (e.g.: "com.google.apps.contacts") of the app 166 * to use the given preference 167 * @param preference the desired network preference to use 168 * @return The builder to facilitate chaining. 169 */ 170 @NonNull addNetworkPreference(@onNull final String packageName, @OemNetworkPreference final int preference)171 public Builder addNetworkPreference(@NonNull final String packageName, 172 @OemNetworkPreference final int preference) { 173 Objects.requireNonNull(packageName); 174 mNetworkMappings.putInt(packageName, preference); 175 return this; 176 } 177 178 /** 179 * Remove a network preference for a given package. 180 * 181 * @param packageName full package name (e.g.: "com.google.apps.contacts") of the app to 182 * remove a preference for. 183 * @return The builder to facilitate chaining. 184 */ 185 @NonNull clearNetworkPreference(@onNull final String packageName)186 public Builder clearNetworkPreference(@NonNull final String packageName) { 187 Objects.requireNonNull(packageName); 188 mNetworkMappings.remove(packageName); 189 return this; 190 } 191 192 /** 193 * Build {@link OemNetworkPreferences} return the current OEM network preferences. 194 */ 195 @NonNull build()196 public OemNetworkPreferences build() { 197 return new OemNetworkPreferences(mNetworkMappings); 198 } 199 } 200 convertToUnmodifiableMap(@onNull final Bundle bundle)201 private static Map<String, Integer> convertToUnmodifiableMap(@NonNull final Bundle bundle) { 202 final Map<String, Integer> networkPreferences = new HashMap<>(); 203 for (final String key : bundle.keySet()) { 204 networkPreferences.put(key, bundle.getInt(key)); 205 } 206 return Collections.unmodifiableMap(networkPreferences); 207 } 208 209 /** @hide */ 210 @IntDef(prefix = "OEM_NETWORK_PREFERENCE_", value = { 211 OEM_NETWORK_PREFERENCE_TEST_ONLY, 212 OEM_NETWORK_PREFERENCE_TEST, 213 OEM_NETWORK_PREFERENCE_UNINITIALIZED, 214 OEM_NETWORK_PREFERENCE_OEM_PAID, 215 OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK, 216 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY, 217 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY 218 }) 219 @Retention(RetentionPolicy.SOURCE) 220 public @interface OemNetworkPreference {} 221 222 /** 223 * Return the string value for OemNetworkPreference 224 * 225 * @param value int value of OemNetworkPreference 226 * @return string version of OemNetworkPreference 227 * 228 * @hide 229 */ 230 @NonNull oemNetworkPreferenceToString(@emNetworkPreference int value)231 public static String oemNetworkPreferenceToString(@OemNetworkPreference int value) { 232 switch (value) { 233 case OEM_NETWORK_PREFERENCE_TEST_ONLY: 234 return "OEM_NETWORK_PREFERENCE_TEST_ONLY"; 235 case OEM_NETWORK_PREFERENCE_TEST: 236 return "OEM_NETWORK_PREFERENCE_TEST"; 237 case OEM_NETWORK_PREFERENCE_UNINITIALIZED: 238 return "OEM_NETWORK_PREFERENCE_UNINITIALIZED"; 239 case OEM_NETWORK_PREFERENCE_OEM_PAID: 240 return "OEM_NETWORK_PREFERENCE_OEM_PAID"; 241 case OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK: 242 return "OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK"; 243 case OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY: 244 return "OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY"; 245 case OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY: 246 return "OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY"; 247 default: 248 return Integer.toHexString(value); 249 } 250 } 251 252 @Override writeToParcel(@onNull android.os.Parcel dest, int flags)253 public void writeToParcel(@NonNull android.os.Parcel dest, int flags) { 254 dest.writeBundle(mNetworkMappings); 255 } 256 257 @Override describeContents()258 public int describeContents() { 259 return 0; 260 } 261 262 @NonNull 263 public static final Parcelable.Creator<OemNetworkPreferences> CREATOR = 264 new Parcelable.Creator<OemNetworkPreferences>() { 265 @Override 266 public OemNetworkPreferences[] newArray(int size) { 267 return new OemNetworkPreferences[size]; 268 } 269 270 @Override 271 public OemNetworkPreferences createFromParcel(@NonNull android.os.Parcel in) { 272 return new OemNetworkPreferences( 273 in.readBundle(getClass().getClassLoader())); 274 } 275 }; 276 } 277