Home | History | Annotate | Download | only in aware
      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.os.Parcel;
     21 import android.os.Parcelable;
     22 import android.util.Log;
     23 
     24 import libcore.util.HexEncoding;
     25 
     26 import java.security.MessageDigest;
     27 import java.security.NoSuchAlgorithmException;
     28 import java.util.Arrays;
     29 import java.util.HashSet;
     30 import java.util.Set;
     31 import 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  */
     42 public 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