1/* 2 * Copyright (C) 2017 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 17package android.net.wifi.aware; 18 19import android.net.NetworkSpecifier; 20import android.os.Parcel; 21import android.os.Parcelable; 22import android.util.Log; 23 24import libcore.util.HexEncoding; 25 26import java.security.MessageDigest; 27import java.security.NoSuchAlgorithmException; 28import java.util.Arrays; 29import java.util.HashSet; 30import java.util.Set; 31import java.util.StringJoiner; 32 33/** 34 * A network specifier object used to represent the capabilities of an network agent. A collection 35 * of multiple WifiAwareNetworkSpecifier objects whose matching critiera (satisfiedBy) is an OR: 36 * a match on any of the network specifiers in the collection is a match. 37 * 38 * This class is not intended for use in network requests. 39 * 40 * @hide 41 */ 42public class WifiAwareAgentNetworkSpecifier extends NetworkSpecifier implements Parcelable { 43 private static final String TAG = "WifiAwareAgentNs"; 44 45 private static final boolean VDBG = false; // STOPSHIP if true 46 47 private Set<ByteArrayWrapper> mNetworkSpecifiers = new HashSet<>(); 48 private MessageDigest mDigester; 49 50 public WifiAwareAgentNetworkSpecifier() { 51 // do nothing, already initialized to empty 52 } 53 54 public WifiAwareAgentNetworkSpecifier(WifiAwareNetworkSpecifier ns) { 55 initialize(); 56 mNetworkSpecifiers.add(convert(ns)); 57 } 58 59 public WifiAwareAgentNetworkSpecifier(WifiAwareNetworkSpecifier[] nss) { 60 initialize(); 61 for (WifiAwareNetworkSpecifier ns : nss) { 62 mNetworkSpecifiers.add(convert(ns)); 63 } 64 } 65 66 public boolean isEmpty() { 67 return mNetworkSpecifiers.isEmpty(); 68 } 69 70 @Override 71 public int describeContents() { 72 return 0; 73 } 74 75 @Override 76 public void writeToParcel(Parcel dest, int flags) { 77 dest.writeArray(mNetworkSpecifiers.toArray()); 78 } 79 80 public static final Creator<WifiAwareAgentNetworkSpecifier> CREATOR = 81 new Creator<WifiAwareAgentNetworkSpecifier>() { 82 @Override 83 public WifiAwareAgentNetworkSpecifier createFromParcel(Parcel in) { 84 WifiAwareAgentNetworkSpecifier agentNs = new WifiAwareAgentNetworkSpecifier(); 85 Object[] objs = in.readArray(null); 86 for (Object obj : objs) { 87 agentNs.mNetworkSpecifiers.add((ByteArrayWrapper) obj); 88 } 89 return agentNs; 90 } 91 92 @Override 93 public WifiAwareAgentNetworkSpecifier[] newArray(int size) { 94 return new WifiAwareAgentNetworkSpecifier[size]; 95 } 96 }; 97 98 @Override 99 public int hashCode() { 100 return mNetworkSpecifiers.hashCode(); 101 } 102 103 @Override 104 public boolean equals(Object obj) { 105 if (obj == this) { 106 return true; 107 } 108 if (!(obj instanceof WifiAwareAgentNetworkSpecifier)) { 109 return false; 110 } 111 return mNetworkSpecifiers.equals(((WifiAwareAgentNetworkSpecifier) obj).mNetworkSpecifiers); 112 } 113 114 @Override 115 public String toString() { 116 StringJoiner sj = new StringJoiner(","); 117 for (ByteArrayWrapper baw: mNetworkSpecifiers) { 118 sj.add(baw.toString()); 119 } 120 return sj.toString(); 121 } 122 123 @Override 124 public boolean satisfiedBy(NetworkSpecifier other) { 125 if (!(other instanceof WifiAwareAgentNetworkSpecifier)) { 126 return false; 127 } 128 WifiAwareAgentNetworkSpecifier otherNs = (WifiAwareAgentNetworkSpecifier) other; 129 130 // called as old.satifiedBy(new): satisfied if old contained in new 131 for (ByteArrayWrapper baw: mNetworkSpecifiers) { 132 if (!otherNs.mNetworkSpecifiers.contains(baw)) { 133 return false; 134 } 135 } 136 137 return true; 138 } 139 140 public boolean satisfiesAwareNetworkSpecifier(WifiAwareNetworkSpecifier ns) { 141 if (VDBG) Log.v(TAG, "satisfiesAwareNetworkSpecifier: ns=" + ns); 142 ByteArrayWrapper nsBytes = convert(ns); 143 return mNetworkSpecifiers.contains(nsBytes); 144 } 145 146 @Override 147 public void assertValidFromUid(int requestorUid) { 148 throw new SecurityException( 149 "WifiAwareAgentNetworkSpecifier should not be used in network requests"); 150 } 151 152 private void initialize() { 153 try { 154 mDigester = MessageDigest.getInstance("SHA-256"); 155 } catch (NoSuchAlgorithmException e) { 156 Log.e(TAG, "Can not instantiate a SHA-256 digester!? Will match nothing."); 157 return; 158 } 159 } 160 161 private ByteArrayWrapper convert(WifiAwareNetworkSpecifier ns) { 162 if (mDigester == null) { 163 return null; 164 } 165 166 Parcel parcel = Parcel.obtain(); 167 ns.writeToParcel(parcel, 0); 168 byte[] bytes = parcel.marshall(); 169 170 mDigester.reset(); 171 mDigester.update(bytes); 172 return new ByteArrayWrapper(mDigester.digest()); 173 } 174 175 private static class ByteArrayWrapper implements Parcelable { 176 private byte[] mData; 177 178 ByteArrayWrapper(byte[] data) { 179 mData = data; 180 } 181 182 @Override 183 public int hashCode() { 184 return Arrays.hashCode(mData); 185 } 186 187 @Override 188 public boolean equals(Object obj) { 189 if (obj == this) { 190 return true; 191 } 192 if (!(obj instanceof ByteArrayWrapper)) { 193 return false; 194 } 195 return Arrays.equals(((ByteArrayWrapper) obj).mData, mData); 196 } 197 198 @Override 199 public int describeContents() { 200 return 0; 201 } 202 203 @Override 204 public void writeToParcel(Parcel dest, int flags) { 205 dest.writeBlob(mData); 206 } 207 208 public static final Creator<ByteArrayWrapper> CREATOR = 209 new Creator<ByteArrayWrapper>() { 210 @Override 211 public ByteArrayWrapper createFromParcel(Parcel in) { 212 return new ByteArrayWrapper(in.readBlob()); 213 } 214 215 @Override 216 public ByteArrayWrapper[] newArray(int size) { 217 return new ByteArrayWrapper[size]; 218 } 219 }; 220 221 @Override 222 public String toString() { 223 return new String(HexEncoding.encode(mData)); 224 } 225 } 226} 227