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