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 com.android.server.net; 18 19 import android.net.NetworkIdentity; 20 import android.service.NetworkIdentitySetProto; 21 import android.util.proto.ProtoOutputStream; 22 23 import java.io.DataInput; 24 import java.io.DataOutput; 25 import java.io.IOException; 26 import java.util.HashSet; 27 28 import static android.net.ConnectivityManager.TYPE_MOBILE; 29 30 /** 31 * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity} 32 * active on that interface. 33 * 34 * @hide 35 */ 36 public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements 37 Comparable<NetworkIdentitySet> { 38 private static final int VERSION_INIT = 1; 39 private static final int VERSION_ADD_ROAMING = 2; 40 private static final int VERSION_ADD_NETWORK_ID = 3; 41 private static final int VERSION_ADD_METERED = 4; 42 private static final int VERSION_ADD_DEFAULT_NETWORK = 5; 43 private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6; 44 NetworkIdentitySet()45 public NetworkIdentitySet() { 46 } 47 NetworkIdentitySet(DataInput in)48 public NetworkIdentitySet(DataInput in) throws IOException { 49 final int version = in.readInt(); 50 final int size = in.readInt(); 51 for (int i = 0; i < size; i++) { 52 if (version <= VERSION_INIT) { 53 final int ignored = in.readInt(); 54 } 55 final int type = in.readInt(); 56 final int subType = in.readInt(); 57 final String subscriberId = readOptionalString(in); 58 final String networkId; 59 if (version >= VERSION_ADD_NETWORK_ID) { 60 networkId = readOptionalString(in); 61 } else { 62 networkId = null; 63 } 64 final boolean roaming; 65 if (version >= VERSION_ADD_ROAMING) { 66 roaming = in.readBoolean(); 67 } else { 68 roaming = false; 69 } 70 71 final boolean metered; 72 if (version >= VERSION_ADD_METERED) { 73 metered = in.readBoolean(); 74 } else { 75 // If this is the old data and the type is mobile, treat it as metered. (Note that 76 // if this is a mobile network, TYPE_MOBILE is the only possible type that could be 77 // used.) 78 metered = (type == TYPE_MOBILE); 79 } 80 81 final boolean defaultNetwork; 82 if (version >= VERSION_ADD_DEFAULT_NETWORK) { 83 defaultNetwork = in.readBoolean(); 84 } else { 85 defaultNetwork = true; 86 } 87 88 final int oemNetCapabilities; 89 if (version >= VERSION_ADD_OEM_MANAGED_NETWORK) { 90 oemNetCapabilities = in.readInt(); 91 } else { 92 oemNetCapabilities = NetworkIdentity.OEM_NONE; 93 } 94 95 add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered, 96 defaultNetwork, oemNetCapabilities)); 97 } 98 } 99 writeToStream(DataOutput out)100 public void writeToStream(DataOutput out) throws IOException { 101 out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK); 102 out.writeInt(size()); 103 for (NetworkIdentity ident : this) { 104 out.writeInt(ident.getType()); 105 out.writeInt(ident.getSubType()); 106 writeOptionalString(out, ident.getSubscriberId()); 107 writeOptionalString(out, ident.getNetworkId()); 108 out.writeBoolean(ident.getRoaming()); 109 out.writeBoolean(ident.getMetered()); 110 out.writeBoolean(ident.getDefaultNetwork()); 111 out.writeInt(ident.getOemManaged()); 112 } 113 } 114 115 /** @return whether any {@link NetworkIdentity} in this set is considered metered. */ isAnyMemberMetered()116 public boolean isAnyMemberMetered() { 117 if (isEmpty()) { 118 return false; 119 } 120 for (NetworkIdentity ident : this) { 121 if (ident.getMetered()) { 122 return true; 123 } 124 } 125 return false; 126 } 127 128 /** @return whether any {@link NetworkIdentity} in this set is considered roaming. */ isAnyMemberRoaming()129 public boolean isAnyMemberRoaming() { 130 if (isEmpty()) { 131 return false; 132 } 133 for (NetworkIdentity ident : this) { 134 if (ident.getRoaming()) { 135 return true; 136 } 137 } 138 return false; 139 } 140 141 /** @return whether any {@link NetworkIdentity} in this set is considered on the default 142 network. */ areAllMembersOnDefaultNetwork()143 public boolean areAllMembersOnDefaultNetwork() { 144 if (isEmpty()) { 145 return true; 146 } 147 for (NetworkIdentity ident : this) { 148 if (!ident.getDefaultNetwork()) { 149 return false; 150 } 151 } 152 return true; 153 } 154 writeOptionalString(DataOutput out, String value)155 private static void writeOptionalString(DataOutput out, String value) throws IOException { 156 if (value != null) { 157 out.writeByte(1); 158 out.writeUTF(value); 159 } else { 160 out.writeByte(0); 161 } 162 } 163 readOptionalString(DataInput in)164 private static String readOptionalString(DataInput in) throws IOException { 165 if (in.readByte() != 0) { 166 return in.readUTF(); 167 } else { 168 return null; 169 } 170 } 171 172 @Override compareTo(NetworkIdentitySet another)173 public int compareTo(NetworkIdentitySet another) { 174 if (isEmpty()) return -1; 175 if (another.isEmpty()) return 1; 176 177 final NetworkIdentity ident = iterator().next(); 178 final NetworkIdentity anotherIdent = another.iterator().next(); 179 return ident.compareTo(anotherIdent); 180 } 181 dumpDebug(ProtoOutputStream proto, long tag)182 public void dumpDebug(ProtoOutputStream proto, long tag) { 183 final long start = proto.start(tag); 184 185 for (NetworkIdentity ident : this) { 186 ident.dumpDebug(proto, NetworkIdentitySetProto.IDENTITIES); 187 } 188 189 proto.end(start); 190 } 191 } 192