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 android.annotation.FlaggedApi;
20 import android.annotation.IntDef;
21 import android.annotation.IntRange;
22 import android.annotation.NonNull;
23 import android.annotation.SystemApi;
24 import android.net.wifi.flags.Flags;
25 import android.net.wifi.sharedconnectivity.service.SharedConnectivityService;
26 import android.os.Bundle;
27 import android.os.Parcel;
28 import android.os.Parcelable;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.util.Objects;
33 
34 /**
35  * A data class representing a device providing connectivity.
36  * This class is used in IPC calls between the implementer of {@link SharedConnectivityService} and
37  * the consumers of {@link com.android.wifitrackerlib}.
38  *
39  * @hide
40  */
41 @SystemApi
42 public final class NetworkProviderInfo implements Parcelable {
43 
44     /**
45      * Device type providing connectivity is unknown.
46      */
47     public static final int DEVICE_TYPE_UNKNOWN = 0;
48 
49     /**
50      * Device providing connectivity is a mobile phone.
51      */
52     public static final int DEVICE_TYPE_PHONE = 1;
53 
54     /**
55      * Device providing connectivity is a tablet.
56      */
57     public static final int DEVICE_TYPE_TABLET = 2;
58 
59     /**
60      * Device providing connectivity is a laptop.
61      */
62     public static final int DEVICE_TYPE_LAPTOP = 3;
63 
64     /**
65      * Device providing connectivity is a watch.
66      */
67     public static final int DEVICE_TYPE_WATCH = 4;
68 
69     /**
70      * Device providing connectivity is a watch.
71      */
72     public static final int DEVICE_TYPE_AUTO = 5;
73 
74     /**
75      * @hide
76      */
77     @Retention(RetentionPolicy.SOURCE)
78     @IntDef({
79             DEVICE_TYPE_UNKNOWN,
80             DEVICE_TYPE_PHONE,
81             DEVICE_TYPE_TABLET,
82             DEVICE_TYPE_LAPTOP,
83             DEVICE_TYPE_WATCH,
84             DEVICE_TYPE_AUTO
85     })
86     public @interface DeviceType {
87     }
88 
89     @DeviceType
90     private final int mDeviceType;
91     private final String mDeviceName;
92     private final String mModelName;
93     private final int mBatteryPercentage;
94     private final boolean mIsBatteryCharging;
95     private final int mConnectionStrength;
96     private final Bundle mExtras;
97 
98     /**
99      * Builder class for {@link NetworkProviderInfo}.
100      */
101     public static final class Builder {
102         private int mDeviceType;
103         private String mDeviceName;
104         private String mModelName;
105         private int mBatteryPercentage;
106         private boolean mIsBatteryCharging;
107         private int mConnectionStrength;
108         private Bundle mExtras = Bundle.EMPTY;
109 
Builder(@onNull String deviceName, @NonNull String modelName)110         public Builder(@NonNull String deviceName, @NonNull String modelName) {
111             Objects.requireNonNull(deviceName);
112             Objects.requireNonNull(modelName);
113             mDeviceName = deviceName;
114             mModelName = modelName;
115         }
116 
117         /**
118          * Sets the device type that provides connectivity.
119          *
120          * @param deviceType Device type as represented by IntDef {@link DeviceType}.
121          * @return Returns the Builder object.
122          */
123         @NonNull
setDeviceType(@eviceType int deviceType)124         public Builder setDeviceType(@DeviceType int deviceType) {
125             mDeviceType = deviceType;
126             return this;
127         }
128 
129         /**
130          * Sets the device name of the remote device.
131          *
132          * @param deviceName The user configurable device name.
133          * @return Returns the Builder object.
134          */
135         @NonNull
setDeviceName(@onNull String deviceName)136         public Builder setDeviceName(@NonNull String deviceName) {
137             Objects.requireNonNull(deviceName);
138             mDeviceName = deviceName;
139             return this;
140         }
141 
142         /**
143          * Sets the model name of the remote device.
144          *
145          * @param modelName The OEM configured name for the device model.
146          * @return Returns the Builder object.
147          */
148         @NonNull
setModelName(@onNull String modelName)149         public Builder setModelName(@NonNull String modelName) {
150             Objects.requireNonNull(modelName);
151             mModelName = modelName;
152             return this;
153         }
154 
155         /**
156          * Sets the battery charge percentage of the remote device.
157          *
158          * @param batteryPercentage The battery charge percentage in the range 0 to 100.
159          * @return Returns the Builder object.
160          */
161         @NonNull
setBatteryPercentage(@ntRangefrom = 0, to = 100) int batteryPercentage)162         public Builder setBatteryPercentage(@IntRange(from = 0, to = 100) int batteryPercentage) {
163             mBatteryPercentage = batteryPercentage;
164             return this;
165         }
166 
167         /**
168          * Sets if the battery of the remote device is charging.
169          *
170          * @param isBatteryCharging True if battery is charging.
171          * @return Returns the Builder object.
172          */
173         @NonNull
174         @FlaggedApi(Flags.FLAG_NETWORK_PROVIDER_BATTERY_CHARGING_STATUS)
setBatteryCharging(boolean isBatteryCharging)175         public Builder setBatteryCharging(boolean isBatteryCharging) {
176             mIsBatteryCharging = isBatteryCharging;
177             return this;
178         }
179 
180         /**
181          * Sets the displayed connection strength of the remote device to the internet.
182          *
183          * @param connectionStrength Connection strength in range 0 to 4.
184          * @return Returns the Builder object.
185          */
186         @NonNull
setConnectionStrength(@ntRangefrom = 0, to = 4) int connectionStrength)187         public Builder setConnectionStrength(@IntRange(from = 0, to = 4) int connectionStrength) {
188             mConnectionStrength = connectionStrength;
189             return this;
190         }
191 
192         /**
193          * Sets the extras bundle
194          *
195          * @return Returns the Builder object.
196          */
197         @NonNull
setExtras(@onNull Bundle extras)198         public Builder setExtras(@NonNull Bundle extras) {
199             Objects.requireNonNull(extras);
200             mExtras = extras;
201             return this;
202         }
203 
204         /**
205          * Builds the {@link NetworkProviderInfo} object.
206          *
207          * @return Returns the built {@link NetworkProviderInfo} object.
208          */
209         @NonNull
build()210         public NetworkProviderInfo build() {
211             return new NetworkProviderInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
212                     mIsBatteryCharging, mConnectionStrength, mExtras);
213         }
214     }
215 
validate(@eviceType int deviceType, String deviceName, String modelName, int batteryPercentage, int connectionStrength)216     private static void validate(@DeviceType int deviceType, String deviceName, String modelName,
217             int batteryPercentage, int connectionStrength) {
218         if (deviceType != DEVICE_TYPE_UNKNOWN && deviceType != DEVICE_TYPE_PHONE
219                 && deviceType != DEVICE_TYPE_TABLET && deviceType != DEVICE_TYPE_LAPTOP
220                 && deviceType != DEVICE_TYPE_WATCH && deviceType != DEVICE_TYPE_AUTO) {
221             throw new IllegalArgumentException("Illegal device type");
222         }
223         if (batteryPercentage < 0 || batteryPercentage > 100) {
224             throw new IllegalArgumentException("BatteryPercentage must be in range 0-100");
225         }
226         if (connectionStrength < 0 || connectionStrength > 4) {
227             throw new IllegalArgumentException("ConnectionStrength must be in range 0-4");
228         }
229     }
230 
NetworkProviderInfo(@eviceType int deviceType, @NonNull String deviceName, @NonNull String modelName, int batteryPercentage, boolean isBatteryCharging, int connectionStrength, @NonNull Bundle extras)231     private NetworkProviderInfo(@DeviceType int deviceType, @NonNull String deviceName,
232             @NonNull String modelName, int batteryPercentage, boolean isBatteryCharging,
233             int connectionStrength, @NonNull Bundle extras) {
234         validate(deviceType, deviceName, modelName, batteryPercentage, connectionStrength);
235         mDeviceType = deviceType;
236         mDeviceName = deviceName;
237         mModelName = modelName;
238         mBatteryPercentage = batteryPercentage;
239         mIsBatteryCharging = isBatteryCharging;
240         mConnectionStrength = connectionStrength;
241         mExtras = extras;
242     }
243 
244     /**
245      * Gets the device type that provides connectivity.
246      *
247      * @return Returns the device type as represented by IntDef {@link DeviceType}.
248      */
249     @DeviceType
getDeviceType()250     public int getDeviceType() {
251         return mDeviceType;
252     }
253 
254     /**
255      * Gets the device name of the remote device.
256      *
257      * @return Returns the user configurable device name.
258      */
259     @NonNull
getDeviceName()260     public String getDeviceName() {
261         return mDeviceName;
262     }
263 
264     /**
265      * Gets the model name of the remote device.
266      *
267      * @return Returns the OEM configured name for the device model.
268      */
269     @NonNull
getModelName()270     public String getModelName() {
271         return mModelName;
272     }
273 
274     /**
275      * Gets the battery charge percentage of the remote device.
276      *
277      * @return Returns the battery charge percentage in the range 0 to 100.
278      */
279     @IntRange(from = 0, to = 100)
getBatteryPercentage()280     public int getBatteryPercentage() {
281         return mBatteryPercentage;
282     }
283 
284     /**
285      * Gets the charging state of the battery on the remote device.
286      *
287      * @return Returns true if the battery of the remote device is charging.
288      */
289     @FlaggedApi(Flags.FLAG_NETWORK_PROVIDER_BATTERY_CHARGING_STATUS)
isBatteryCharging()290     public boolean isBatteryCharging() {
291         return mIsBatteryCharging;
292     }
293 
294     /**
295      * Gets the displayed connection strength of the remote device to the internet.
296      *
297      * @return Returns the connection strength in range 0 to 4.
298      */
299     @IntRange(from = 0, to = 4)
getConnectionStrength()300     public int getConnectionStrength() {
301         return mConnectionStrength;
302     }
303 
304     /**
305      * Gets the extras Bundle.
306      *
307      * @return Returns a Bundle object.
308      */
309     @NonNull
getExtras()310     public Bundle getExtras() {
311         return mExtras;
312     }
313 
314     @Override
equals(Object obj)315     public boolean equals(Object obj) {
316         if (!(obj instanceof NetworkProviderInfo)) return false;
317         NetworkProviderInfo other = (NetworkProviderInfo) obj;
318         return mDeviceType == other.getDeviceType()
319                 && Objects.equals(mDeviceName, other.mDeviceName)
320                 && Objects.equals(mModelName, other.mModelName)
321                 && mBatteryPercentage == other.mBatteryPercentage
322                 && mIsBatteryCharging == other.mIsBatteryCharging
323                 && mConnectionStrength == other.mConnectionStrength;
324     }
325 
326     @Override
hashCode()327     public int hashCode() {
328         return Objects.hash(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
329                 mIsBatteryCharging, mConnectionStrength);
330     }
331 
332     @Override
writeToParcel(@onNull Parcel dest, int flags)333     public void writeToParcel(@NonNull Parcel dest, int flags) {
334         dest.writeInt(mDeviceType);
335         dest.writeString(mDeviceName);
336         dest.writeString(mModelName);
337         dest.writeInt(mBatteryPercentage);
338         dest.writeBoolean(mIsBatteryCharging);
339         dest.writeInt(mConnectionStrength);
340         dest.writeBundle(mExtras);
341     }
342 
343     @Override
describeContents()344     public int describeContents() {
345         return 0;
346     }
347 
348     /**
349      * Creates a {@link NetworkProviderInfo} object from a parcel.
350      *
351      * @hide
352      */
353     @NonNull
readFromParcel(@onNull Parcel in)354     public static NetworkProviderInfo readFromParcel(@NonNull Parcel in) {
355         return new NetworkProviderInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
356                 in.readBoolean(), in.readInt(), in.readBundle());
357     }
358 
359     @NonNull
360     public static final Creator<NetworkProviderInfo> CREATOR = new Creator<NetworkProviderInfo>() {
361         @Override
362         public NetworkProviderInfo createFromParcel(Parcel in) {
363             return readFromParcel(in);
364         }
365 
366         @Override
367         public NetworkProviderInfo[] newArray(int size) {
368             return new NetworkProviderInfo[size];
369         }
370     };
371 
372     @Override
toString()373     public String toString() {
374         return new StringBuilder("NetworkProviderInfo[")
375                 .append("deviceType=").append(mDeviceType)
376                 .append(", deviceName=").append(mDeviceName)
377                 .append(", modelName=").append(mModelName)
378                 .append(", batteryPercentage=").append(mBatteryPercentage)
379                 .append(", isBatteryCharging=").append(mIsBatteryCharging)
380                 .append(", connectionStrength=").append(mConnectionStrength)
381                 .append(", extras=").append(mExtras.toString())
382                 .append("]").toString();
383     }
384 }
385