1 /* 2 * Copyright (C) 2011 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.net.ConnectivityManager.TYPE_MOBILE; 20 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; 21 22 import android.annotation.NonNull; 23 import android.service.NetworkIdentitySetProto; 24 import android.util.proto.ProtoOutputStream; 25 26 import java.io.DataInput; 27 import java.io.DataOutput; 28 import java.io.IOException; 29 import java.util.HashSet; 30 import java.util.Objects; 31 import java.util.Set; 32 33 /** 34 * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity} 35 * active on that interface. 36 * 37 * @hide 38 */ 39 public class NetworkIdentitySet extends HashSet<NetworkIdentity> { 40 private static final int VERSION_INIT = 1; 41 private static final int VERSION_ADD_ROAMING = 2; 42 private static final int VERSION_ADD_NETWORK_ID = 3; 43 private static final int VERSION_ADD_METERED = 4; 44 private static final int VERSION_ADD_DEFAULT_NETWORK = 5; 45 private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6; 46 private static final int VERSION_ADD_SUB_ID = 7; 47 48 /** 49 * Construct a {@link NetworkIdentitySet} object. 50 */ NetworkIdentitySet()51 public NetworkIdentitySet() { 52 super(); 53 } 54 55 /** @hide */ NetworkIdentitySet(@onNull Set<NetworkIdentity> ident)56 public NetworkIdentitySet(@NonNull Set<NetworkIdentity> ident) { 57 super(ident); 58 } 59 60 /** @hide */ NetworkIdentitySet(DataInput in)61 public NetworkIdentitySet(DataInput in) throws IOException { 62 final int version = in.readInt(); 63 final int size = in.readInt(); 64 for (int i = 0; i < size; i++) { 65 if (version <= VERSION_INIT) { 66 final int ignored = in.readInt(); 67 } 68 final int type = in.readInt(); 69 final int ratType = in.readInt(); 70 final String subscriberId = readOptionalString(in); 71 final String networkId; 72 if (version >= VERSION_ADD_NETWORK_ID) { 73 networkId = readOptionalString(in); 74 } else { 75 networkId = null; 76 } 77 final boolean roaming; 78 if (version >= VERSION_ADD_ROAMING) { 79 roaming = in.readBoolean(); 80 } else { 81 roaming = false; 82 } 83 84 final boolean metered; 85 if (version >= VERSION_ADD_METERED) { 86 metered = in.readBoolean(); 87 } else { 88 // If this is the old data and the type is mobile, treat it as metered. (Note that 89 // if this is a mobile network, TYPE_MOBILE is the only possible type that could be 90 // used.) 91 metered = (type == TYPE_MOBILE); 92 } 93 94 final boolean defaultNetwork; 95 if (version >= VERSION_ADD_DEFAULT_NETWORK) { 96 defaultNetwork = in.readBoolean(); 97 } else { 98 defaultNetwork = true; 99 } 100 101 final int oemNetCapabilities; 102 if (version >= VERSION_ADD_OEM_MANAGED_NETWORK) { 103 oemNetCapabilities = in.readInt(); 104 } else { 105 oemNetCapabilities = NetworkIdentity.OEM_NONE; 106 } 107 108 final int subId; 109 if (version >= VERSION_ADD_SUB_ID) { 110 subId = in.readInt(); 111 } else { 112 subId = INVALID_SUBSCRIPTION_ID; 113 } 114 115 add(new NetworkIdentity(type, ratType, subscriberId, networkId, roaming, metered, 116 defaultNetwork, oemNetCapabilities, subId)); 117 } 118 } 119 120 /** 121 * Method to serialize this object into a {@code DataOutput}. 122 * @hide 123 */ writeToStream(DataOutput out)124 public void writeToStream(DataOutput out) throws IOException { 125 out.writeInt(VERSION_ADD_SUB_ID); 126 out.writeInt(size()); 127 for (NetworkIdentity ident : this) { 128 out.writeInt(ident.getType()); 129 out.writeInt(ident.getRatType()); 130 writeOptionalString(out, ident.getSubscriberId()); 131 writeOptionalString(out, ident.getWifiNetworkKey()); 132 out.writeBoolean(ident.isRoaming()); 133 out.writeBoolean(ident.isMetered()); 134 out.writeBoolean(ident.isDefaultNetwork()); 135 out.writeInt(ident.getOemManaged()); 136 out.writeInt(ident.getSubId()); 137 } 138 } 139 140 /** 141 * @return whether any {@link NetworkIdentity} in this set is considered metered. 142 * @hide 143 */ isAnyMemberMetered()144 public boolean isAnyMemberMetered() { 145 if (isEmpty()) { 146 return false; 147 } 148 for (NetworkIdentity ident : this) { 149 if (ident.isMetered()) { 150 return true; 151 } 152 } 153 return false; 154 } 155 156 /** 157 * @return whether any {@link NetworkIdentity} in this set is considered roaming. 158 * @hide 159 */ isAnyMemberRoaming()160 public boolean isAnyMemberRoaming() { 161 if (isEmpty()) { 162 return false; 163 } 164 for (NetworkIdentity ident : this) { 165 if (ident.isRoaming()) { 166 return true; 167 } 168 } 169 return false; 170 } 171 172 /** 173 * @return whether any {@link NetworkIdentity} in this set is considered on the default 174 * network. 175 * @hide 176 */ areAllMembersOnDefaultNetwork()177 public boolean areAllMembersOnDefaultNetwork() { 178 if (isEmpty()) { 179 return true; 180 } 181 for (NetworkIdentity ident : this) { 182 if (!ident.isDefaultNetwork()) { 183 return false; 184 } 185 } 186 return true; 187 } 188 writeOptionalString(DataOutput out, String value)189 private static void writeOptionalString(DataOutput out, String value) throws IOException { 190 if (value != null) { 191 out.writeByte(1); 192 out.writeUTF(value); 193 } else { 194 out.writeByte(0); 195 } 196 } 197 readOptionalString(DataInput in)198 private static String readOptionalString(DataInput in) throws IOException { 199 if (in.readByte() != 0) { 200 return in.readUTF(); 201 } else { 202 return null; 203 } 204 } 205 compare(@onNull NetworkIdentitySet left, @NonNull NetworkIdentitySet right)206 public static int compare(@NonNull NetworkIdentitySet left, @NonNull NetworkIdentitySet right) { 207 Objects.requireNonNull(left); 208 Objects.requireNonNull(right); 209 if (left.isEmpty() && right.isEmpty()) return 0; 210 if (left.isEmpty()) return -1; 211 if (right.isEmpty()) return 1; 212 213 final NetworkIdentity leftIdent = left.iterator().next(); 214 final NetworkIdentity rightIdent = right.iterator().next(); 215 return NetworkIdentity.compare(leftIdent, rightIdent); 216 } 217 218 /** 219 * Method to dump this object into proto debug file. 220 * @hide 221 */ dumpDebug(ProtoOutputStream proto, long tag)222 public void dumpDebug(ProtoOutputStream proto, long tag) { 223 final long start = proto.start(tag); 224 225 for (NetworkIdentity ident : this) { 226 ident.dumpDebug(proto, NetworkIdentitySetProto.IDENTITIES); 227 } 228 229 proto.end(start); 230 } 231 } 232