1 /*
2  * Copyright 2022 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.bluetooth.le;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.SystemApi;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 import com.android.bluetooth.flags.Flags;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 import java.util.Objects;
31 
32 /**
33  * Method of distance measurement. A list of this class will be returned by {@link
34  * DistanceMeasurementManager#getSupportedMethods()} to indicate the supported methods and their
35  * capability about angle measurement.
36  *
37  * @hide
38  */
39 @SystemApi
40 public final class DistanceMeasurementMethod implements Parcelable {
41 
42     private final int mId;
43     private final boolean mIsAzimuthAngleSupported;
44     private final boolean mIsAltitudeAngleSupported;
45 
46     /** @hide */
47     @Retention(RetentionPolicy.SOURCE)
48     @IntDef(
49             value = {
50                 DISTANCE_MEASUREMENT_METHOD_AUTO,
51                 DISTANCE_MEASUREMENT_METHOD_RSSI,
52                 DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING
53             })
54     @interface DistanceMeasurementMethodId {}
55 
56     /**
57      * Choose method automatically, Bluetooth will use the most accurate method that local device
58      * supported to measurement distance.
59      *
60      * @hide
61      */
62     @SystemApi public static final int DISTANCE_MEASUREMENT_METHOD_AUTO = 0;
63 
64     /**
65      * Use remote RSSI and transmit power to measure the distance.
66      *
67      * @hide
68      */
69     @SystemApi public static final int DISTANCE_MEASUREMENT_METHOD_RSSI = 1;
70 
71     /**
72      * Use Channel Sounding to measure the distance.
73      *
74      * @hide
75      */
76     @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING)
77     @SystemApi
78     public static final int DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING = 2;
79 
DistanceMeasurementMethod( int id, boolean isAzimuthAngleSupported, boolean isAltitudeAngleSupported)80     private DistanceMeasurementMethod(
81             int id, boolean isAzimuthAngleSupported, boolean isAltitudeAngleSupported) {
82         mId = id;
83         mIsAzimuthAngleSupported = isAzimuthAngleSupported;
84         mIsAltitudeAngleSupported = isAltitudeAngleSupported;
85     }
86 
87     /**
88      * Id of the method used for {@link DistanceMeasurementParams.Builder#setMethod(int)}
89      *
90      * @return id of the method
91      * @hide
92      */
93     @SystemApi
getId()94     public @DistanceMeasurementMethodId double getId() {
95         return mId;
96     }
97 
98     /**
99      * Checks whether the azimuth angle is supported for this method.
100      *
101      * @return true if azimuth angle is supported, false otherwise
102      * @hide
103      */
104     @SystemApi
isAzimuthAngleSupported()105     public boolean isAzimuthAngleSupported() {
106         return mIsAzimuthAngleSupported;
107     }
108 
109     /**
110      * Checks whether the altitude angle is supported for this method.
111      *
112      * @return true if altitude angle is supported, false otherwise
113      * @hide
114      */
115     @SystemApi
isAltitudeAngleSupported()116     public boolean isAltitudeAngleSupported() {
117         return mIsAltitudeAngleSupported;
118     }
119 
120     /**
121      * {@inheritDoc}
122      *
123      * @hide
124      */
125     @Override
describeContents()126     public int describeContents() {
127         return 0;
128     }
129 
130     /**
131      * {@inheritDoc}
132      *
133      * @hide
134      */
135     @Override
writeToParcel(Parcel out, int flags)136     public void writeToParcel(Parcel out, int flags) {
137         out.writeInt(mId);
138         out.writeBoolean(mIsAzimuthAngleSupported);
139         out.writeBoolean(mIsAltitudeAngleSupported);
140     }
141 
142     /**
143      * @hide *
144      */
145     @Override
toString()146     public String toString() {
147         return "DistanceMeasurementMethod["
148                 + "id: "
149                 + mId
150                 + ", isAzimuthAngleSupported: "
151                 + mIsAzimuthAngleSupported
152                 + ", isAltitudeAngleSupported: "
153                 + mIsAltitudeAngleSupported
154                 + "]";
155     }
156 
157     @Override
equals(Object o)158     public boolean equals(Object o) {
159         if (o == null) return false;
160 
161         if (!(o instanceof DistanceMeasurementMethod)) return false;
162 
163         final DistanceMeasurementMethod u = (DistanceMeasurementMethod) o;
164 
165         if (mId != u.getId()) {
166             return false;
167         }
168 
169         return true;
170     }
171 
172     @Override
hashCode()173     public int hashCode() {
174         return Objects.hash(mId);
175     }
176 
177     /** A {@link Parcelable.Creator} to create {@link DistanceMeasurementMethod} from parcel. */
178     public static final @NonNull Parcelable.Creator<DistanceMeasurementMethod> CREATOR =
179             new Parcelable.Creator<DistanceMeasurementMethod>() {
180                 @Override
181                 public @NonNull DistanceMeasurementMethod createFromParcel(@NonNull Parcel in) {
182                     return new Builder(in.readInt())
183                             .setAzimuthAngleSupported(in.readBoolean())
184                             .setAltitudeAngleSupported(in.readBoolean())
185                             .build();
186                 }
187 
188                 @Override
189                 public @NonNull DistanceMeasurementMethod[] newArray(int size) {
190                     return new DistanceMeasurementMethod[size];
191                 }
192             };
193 
194     /**
195      * Builder for {@link DistanceMeasurementMethod}.
196      *
197      * @hide
198      */
199     @SystemApi
200     public static final class Builder {
201         private int mId;
202         private boolean mIsAzimuthAngleSupported = false;
203         private boolean mIsAltitudeAngleSupported = false;
204 
205         /**
206          * Constructor of the Builder.
207          *
208          * @param id id of the method
209          */
Builder(@istanceMeasurementMethodId int id)210         public Builder(@DistanceMeasurementMethodId int id) {
211             switch (id) {
212                 case DISTANCE_MEASUREMENT_METHOD_AUTO:
213                 case DISTANCE_MEASUREMENT_METHOD_RSSI:
214                 case DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING:
215                     mId = id;
216                     break;
217                 default:
218                     throw new IllegalArgumentException("unknown method id " + id);
219             }
220         }
221 
222         /**
223          * Set if azimuth angle supported or not.
224          *
225          * @param supported {@code true} if azimuth angle supported, {@code false} otherwise
226          * @hide
227          */
228         @SystemApi
229         @NonNull
setAzimuthAngleSupported(boolean supported)230         public Builder setAzimuthAngleSupported(boolean supported) {
231             mIsAzimuthAngleSupported = supported;
232             return this;
233         }
234 
235         /**
236          * Set if altitude angle supported or not.
237          *
238          * @param supported {@code true} if altitude angle supported, {@code false} otherwise
239          * @hide
240          */
241         @SystemApi
242         @NonNull
setAltitudeAngleSupported(boolean supported)243         public Builder setAltitudeAngleSupported(boolean supported) {
244             mIsAltitudeAngleSupported = supported;
245             return this;
246         }
247 
248         /**
249          * Builds the {@link DistanceMeasurementMethod} object.
250          *
251          * @hide
252          */
253         @SystemApi
254         @NonNull
build()255         public DistanceMeasurementMethod build() {
256             return new DistanceMeasurementMethod(
257                     mId, mIsAzimuthAngleSupported, mIsAltitudeAngleSupported);
258         }
259     }
260 }
261