1 /*
2  * Copyright (C) 2023 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.sharedconnectivity.app;
18 
19 import static android.net.wifi.WifiAnnotations.SecurityType;
20 
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.SystemApi;
25 import android.net.wifi.sharedconnectivity.service.SharedConnectivityService;
26 import android.os.Bundle;
27 import android.os.Parcel;
28 import android.os.Parcelable;
29 import android.util.ArraySet;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 import java.util.Objects;
34 import java.util.Set;
35 
36 /**
37  * A data class representing a hotspot network.
38  * This class is used in IPC calls between the implementer of {@link SharedConnectivityService} and
39  * the consumers of {@link com.android.wifitrackerlib}.
40  *
41  * @hide
42  */
43 @SystemApi
44 public final class HotspotNetwork implements Parcelable {
45     /**
46      * Remote device is connected to the internet via an unknown connection.
47      */
48     public static final int NETWORK_TYPE_UNKNOWN = 0;
49 
50     /**
51      * Remote device is connected to the internet via a cellular connection.
52      */
53     public static final int NETWORK_TYPE_CELLULAR = 1;
54 
55     /**
56      * Remote device is connected to the internet via a Wi-Fi connection.
57      */
58     public static final int NETWORK_TYPE_WIFI = 2;
59 
60     /**
61      * Remote device is connected to the internet via an ethernet connection.
62      */
63     public static final int NETWORK_TYPE_ETHERNET = 3;
64 
65     /**
66      * @hide
67      */
68     @Retention(RetentionPolicy.SOURCE)
69     @IntDef({
70             NETWORK_TYPE_UNKNOWN,
71             NETWORK_TYPE_CELLULAR,
72             NETWORK_TYPE_WIFI,
73             NETWORK_TYPE_ETHERNET
74     })
75     public @interface NetworkType {
76     }
77 
78     private final long mDeviceId;
79     private final NetworkProviderInfo mNetworkProviderInfo;
80     @NetworkType
81     private final int mNetworkType;
82     private final String mNetworkName;
83     @Nullable
84     private final String mHotspotSsid;
85     @Nullable
86     private final String mHotspotBssid;
87     @Nullable
88     @SecurityType
89     private final ArraySet<Integer> mHotspotSecurityTypes;
90     private final Bundle mExtras;
91 
92     /**
93      * Builder class for {@link HotspotNetwork}.
94      */
95     public static final class Builder {
96         private long mDeviceId = -1;
97         private NetworkProviderInfo mNetworkProviderInfo;
98         @NetworkType
99         private int mNetworkType;
100         private String mNetworkName;
101         @Nullable
102         private String mHotspotSsid;
103         @Nullable
104         private String mHotspotBssid;
105         @Nullable
106         @SecurityType
107         private final ArraySet<Integer> mHotspotSecurityTypes = new ArraySet<>();
108         private Bundle mExtras = Bundle.EMPTY;
109 
110         /**
111          * Set the remote device ID.
112          *
113          * @param deviceId Locally unique ID for this Hotspot network.
114          * @return Returns the Builder object.
115          */
116         @NonNull
setDeviceId(long deviceId)117         public Builder setDeviceId(long deviceId) {
118             mDeviceId = deviceId;
119             return this;
120         }
121 
122         /**
123          * Sets information about the device providing connectivity.
124          *
125          * @param networkProviderInfo The device information object.
126          * @return Returns the Builder object.
127          */
128         @NonNull
setNetworkProviderInfo(@onNull NetworkProviderInfo networkProviderInfo)129         public Builder setNetworkProviderInfo(@NonNull NetworkProviderInfo networkProviderInfo) {
130             mNetworkProviderInfo = networkProviderInfo;
131             return this;
132         }
133 
134         /**
135          * Sets the network type that the remote device is connected to.
136          *
137          * @param networkType Network type as represented by IntDef {@link NetworkType}.
138          * @return Returns the Builder object.
139          */
140         @NonNull
setHostNetworkType(@etworkType int networkType)141         public Builder setHostNetworkType(@NetworkType int networkType) {
142             mNetworkType = networkType;
143             return this;
144         }
145 
146         /**
147          * Sets the display name of the network the remote device is connected to.
148          *
149          * @param networkName Network display name. (e.g. "Google Fi", "Hotel WiFi", "Ethernet")
150          * @return Returns the Builder object.
151          */
152         @NonNull
setNetworkName(@onNull String networkName)153         public Builder setNetworkName(@NonNull String networkName) {
154             mNetworkName = networkName;
155             return this;
156         }
157 
158         /**
159          * Sets the hotspot SSID being broadcast by the remote device, or null if hotspot is off.
160          *
161          * @param hotspotSsid The SSID of the hotspot. Surrounded by double quotes if UTF-8.
162          * @return Returns the Builder object.
163          */
164         @NonNull
setHotspotSsid(@onNull String hotspotSsid)165         public Builder setHotspotSsid(@NonNull String hotspotSsid) {
166             mHotspotSsid = hotspotSsid;
167             return this;
168         }
169 
170         /**
171          * Sets the hotspot BSSID being broadcast by the remote device, or null if hotspot is off.
172          *
173          * @param hotspotBssid The BSSID of the hotspot.
174          * @return Returns the Builder object.
175          */
176         @NonNull
setHotspotBssid(@onNull String hotspotBssid)177         public Builder setHotspotBssid(@NonNull String hotspotBssid) {
178             mHotspotBssid = hotspotBssid;
179             return this;
180         }
181 
182         /**
183          * Adds a security type supported by the hotspot created by the remote device.
184          *
185          * @param hotspotSecurityType A security type supported by the hotspot.
186          * @return Returns the Builder object.
187          */
188         @NonNull
addHotspotSecurityType(@ecurityType int hotspotSecurityType)189         public Builder addHotspotSecurityType(@SecurityType int hotspotSecurityType) {
190             mHotspotSecurityTypes.add(hotspotSecurityType);
191             return this;
192         }
193 
194         /**
195          * Sets the extras bundle
196          *
197          * @return Returns the Builder object.
198          */
199         @NonNull
setExtras(@onNull Bundle extras)200         public Builder setExtras(@NonNull Bundle extras) {
201             mExtras = extras;
202             return this;
203         }
204 
205         /**
206          * Builds the {@link HotspotNetwork} object.
207          *
208          * @return Returns the built {@link HotspotNetwork} object.
209          */
210         @NonNull
build()211         public HotspotNetwork build() {
212             return new HotspotNetwork(
213                     mDeviceId,
214                     mNetworkProviderInfo,
215                     mNetworkType,
216                     mNetworkName,
217                     mHotspotSsid,
218                     mHotspotBssid,
219                     mHotspotSecurityTypes,
220                     mExtras);
221         }
222     }
223 
validate(long deviceId, @NetworkType int networkType, String networkName, NetworkProviderInfo networkProviderInfo)224     private static void validate(long deviceId, @NetworkType int networkType, String networkName,
225             NetworkProviderInfo networkProviderInfo) {
226         if (deviceId < 0) {
227             throw new IllegalArgumentException("DeviceId must be set");
228         }
229         if (Objects.isNull(networkProviderInfo)) {
230             throw new IllegalArgumentException("NetworkProviderInfo must be set");
231         }
232         if (networkType != NETWORK_TYPE_CELLULAR && networkType != NETWORK_TYPE_WIFI
233                 && networkType != NETWORK_TYPE_ETHERNET && networkType != NETWORK_TYPE_UNKNOWN) {
234             throw new IllegalArgumentException("Illegal network type");
235         }
236         if (Objects.isNull(networkName)) {
237             throw new IllegalArgumentException("NetworkName must be set");
238         }
239     }
240 
HotspotNetwork( long deviceId, NetworkProviderInfo networkProviderInfo, @NetworkType int networkType, @NonNull String networkName, @Nullable String hotspotSsid, @Nullable String hotspotBssid, @Nullable @SecurityType ArraySet<Integer> hotspotSecurityTypes, @NonNull Bundle extras)241     private HotspotNetwork(
242             long deviceId,
243             NetworkProviderInfo networkProviderInfo,
244             @NetworkType int networkType,
245             @NonNull String networkName,
246             @Nullable String hotspotSsid,
247             @Nullable String hotspotBssid,
248             @Nullable @SecurityType ArraySet<Integer> hotspotSecurityTypes,
249             @NonNull Bundle extras) {
250         validate(deviceId,
251                 networkType,
252                 networkName,
253                 networkProviderInfo);
254         mDeviceId = deviceId;
255         mNetworkProviderInfo = networkProviderInfo;
256         mNetworkType = networkType;
257         mNetworkName = networkName;
258         mHotspotSsid = hotspotSsid;
259         mHotspotBssid = hotspotBssid;
260         mHotspotSecurityTypes = new ArraySet<>(hotspotSecurityTypes);
261         mExtras = extras;
262     }
263 
264     /**
265      * Gets the remote device ID.
266      *
267      * @return Returns the locally unique ID for this Hotspot network.
268      */
getDeviceId()269     public long getDeviceId() {
270         return mDeviceId;
271     }
272 
273     /**
274      * Gets information about the device providing connectivity.
275      *
276      * @return Returns the information of the device providing the Hotspot network.
277      */
278     @NonNull
getNetworkProviderInfo()279     public NetworkProviderInfo getNetworkProviderInfo() {
280         return mNetworkProviderInfo;
281     }
282 
283     /**
284      * Gets the network type that the remote device is connected to.
285      *
286      * @return Returns the network type as represented by IntDef {@link NetworkType}.
287      */
288     @NetworkType
getHostNetworkType()289     public int getHostNetworkType() {
290         return mNetworkType;
291     }
292 
293     /**
294      * Gets the display name of the network the remote device is connected to.
295      *
296      * @return Returns the network display name. (e.g. "Google Fi", "Hotel WiFi", "Ethernet")
297      */
298     @NonNull
getNetworkName()299     public String getNetworkName() {
300         return mNetworkName;
301     }
302 
303     /**
304      * Gets the hotspot SSID being broadcast by the remote device, or null if hotspot is off.
305      *
306      * @return Returns the SSID of the hotspot. Surrounded by double quotes if UTF-8.
307      */
308     @Nullable
getHotspotSsid()309     public String getHotspotSsid() {
310         return mHotspotSsid;
311     }
312 
313     /**
314      * Gets the hotspot BSSID being broadcast by the remote device, or null if hotspot is off.
315      *
316      * @return Returns the BSSID of the hotspot.
317      */
318     @Nullable
getHotspotBssid()319     public String getHotspotBssid() {
320         return mHotspotBssid;
321     }
322 
323     /**
324      * Gets the hotspot security types supported by the remote device.
325      *
326      * @return Returns a set of the security types supported by the hotspot.
327      */
328     @NonNull
329     @SecurityType
getHotspotSecurityTypes()330     public Set<Integer> getHotspotSecurityTypes() {
331         return mHotspotSecurityTypes;
332     }
333 
334     /**
335      * Gets the extras Bundle.
336      *
337      * @return Returns a Bundle object.
338      */
339     @NonNull
getExtras()340     public Bundle getExtras() {
341         return mExtras;
342     }
343 
344     @Override
equals(Object obj)345     public boolean equals(Object obj) {
346         if (!(obj instanceof HotspotNetwork)) return false;
347         HotspotNetwork other = (HotspotNetwork) obj;
348         return mDeviceId == other.getDeviceId()
349                 && Objects.equals(mNetworkProviderInfo, other.getNetworkProviderInfo())
350                 && mNetworkType == other.getHostNetworkType()
351                 && Objects.equals(mNetworkName, other.getNetworkName())
352                 && Objects.equals(mHotspotSsid, other.getHotspotSsid())
353                 && Objects.equals(mHotspotBssid, other.getHotspotBssid())
354                 && Objects.equals(mHotspotSecurityTypes, other.getHotspotSecurityTypes());
355     }
356 
357     @Override
hashCode()358     public int hashCode() {
359         return Objects.hash(mDeviceId, mNetworkProviderInfo, mNetworkName, mHotspotSsid,
360                 mHotspotBssid, mHotspotSecurityTypes);
361     }
362 
363     @Override
describeContents()364     public int describeContents() {
365         return 0;
366     }
367 
368     @Override
writeToParcel(@onNull Parcel dest, int flags)369     public void writeToParcel(@NonNull Parcel dest, int flags) {
370         dest.writeLong(mDeviceId);
371         mNetworkProviderInfo.writeToParcel(dest, flags);
372         dest.writeInt(mNetworkType);
373         dest.writeString(mNetworkName);
374         dest.writeString(mHotspotSsid);
375         dest.writeString(mHotspotBssid);
376         dest.writeArraySet(mHotspotSecurityTypes);
377         dest.writeBundle(mExtras);
378     }
379 
380     /**
381      * Creates a {@link HotspotNetwork} object from a parcel.
382      *
383      * @hide
384      */
385     @NonNull
readFromParcel(@onNull Parcel in)386     public static HotspotNetwork readFromParcel(@NonNull Parcel in) {
387         return new HotspotNetwork(in.readLong(), NetworkProviderInfo.readFromParcel(in),
388                 in.readInt(), in.readString(), in.readString(), in.readString(),
389                 (ArraySet<Integer>) in.readArraySet(null), in.readBundle());
390     }
391 
392     @NonNull
393     public static final Creator<HotspotNetwork> CREATOR = new Creator<>() {
394         @Override
395         public HotspotNetwork createFromParcel(Parcel in) {
396             return readFromParcel(in);
397         }
398 
399         @Override
400         public HotspotNetwork[] newArray(int size) {
401             return new HotspotNetwork[size];
402         }
403     };
404 
405     @Override
toString()406     public String toString() {
407         return new StringBuilder("HotspotNetwork[")
408                 .append("deviceId=").append(mDeviceId)
409                 .append(", networkType=").append(mNetworkType)
410                 .append(", networkProviderInfo=").append(mNetworkProviderInfo.toString())
411                 .append(", networkName=").append(mNetworkName)
412                 .append(", hotspotSsid=").append(mHotspotSsid)
413                 .append(", hotspotBssid=").append(mHotspotBssid)
414                 .append(", hotspotSecurityTypes=").append(mHotspotSecurityTypes.toString())
415                 .append(", extras=").append(mExtras.toString())
416                 .append("]").toString();
417     }
418 }
419