• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.RequiresPermission;
22 import android.annotation.SystemApi;
23 import android.bluetooth.BluetoothDevice;
24 import android.bluetooth.BluetoothStatusCodes;
25 import android.bluetooth.IBluetoothGatt;
26 import android.content.AttributionSource;
27 import android.os.Binder;
28 import android.os.ParcelUuid;
29 import android.os.RemoteException;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 import java.util.Objects;
34 import java.util.concurrent.Executor;
35 
36 /**
37  * This class provides a way to control an active distance measurement session.
38  *
39  * <p>It also defines the required {@link DistanceMeasurementSession.Callback} that must be
40  * implemented in order to be notified of distance measurement results and status events related to
41  * the {@link DistanceMeasurementSession}.
42  *
43  * <p>To get an instance of {@link DistanceMeasurementSession}, first use {@link
44  * DistanceMeasurementManager#startMeasurementSession(DistanceMeasurementParams, Executor,
45  * DistanceMeasurementSession.Callback)} to request to start a session. Once the session is started,
46  * a {@link DistanceMeasurementSession} object is provided through {@link
47  * DistanceMeasurementSession.Callback#onStarted(DistanceMeasurementSession)}. If starting a session
48  * fails, the failure is reported through {@link
49  * DistanceMeasurementSession.Callback#onStartFail(int)} with the failure reason.
50  *
51  * @hide
52  */
53 @SystemApi
54 public final class DistanceMeasurementSession {
55     private static final String TAG = "DistanceMeasurementSession";
56 
57     private final IBluetoothGatt mGatt;
58     private final ParcelUuid mUuid;
59     private final DistanceMeasurementParams mDistanceMeasurementParams;
60     private final Executor mExecutor;
61     private final Callback mCallback;
62     private final AttributionSource mAttributionSource;
63 
64     /** @hide */
65     @Retention(RetentionPolicy.SOURCE)
66     @IntDef(
67             value = {
68                 BluetoothStatusCodes.SUCCESS,
69                 BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
70                 BluetoothStatusCodes.ERROR_DISTANCE_MEASUREMENT_INTERNAL,
71             })
72     public @interface StopSessionReturnValues {}
73 
74     /** @hide */
DistanceMeasurementSession( IBluetoothGatt gatt, ParcelUuid uuid, DistanceMeasurementParams params, Executor executor, AttributionSource attributionSource, Callback callback)75     public DistanceMeasurementSession(
76             IBluetoothGatt gatt,
77             ParcelUuid uuid,
78             DistanceMeasurementParams params,
79             Executor executor,
80             AttributionSource attributionSource,
81             Callback callback) {
82         Objects.requireNonNull(gatt, "gatt is null");
83         Objects.requireNonNull(params, "params is null");
84         Objects.requireNonNull(executor, "executor is null");
85         Objects.requireNonNull(callback, "callback is null");
86         mGatt = gatt;
87         mUuid = uuid;
88         mDistanceMeasurementParams = params;
89         mExecutor = executor;
90         mAttributionSource = attributionSource;
91         mCallback = callback;
92     }
93 
94     /**
95      * Stops actively ranging, {@link Callback#onStopped} will be invoked if this succeeds.
96      *
97      * @return whether successfully stop or not
98      * @hide
99      */
100     @SystemApi
101     @RequiresPermission(
102             allOf = {
103                 android.Manifest.permission.BLUETOOTH_CONNECT,
104                 android.Manifest.permission.BLUETOOTH_PRIVILEGED,
105             })
stopSession()106     public @StopSessionReturnValues int stopSession() {
107         try {
108             return mGatt.stopDistanceMeasurement(
109                     mUuid,
110                     mDistanceMeasurementParams.getDevice(),
111                     mDistanceMeasurementParams.getMethodId(),
112                     mAttributionSource);
113         } catch (RemoteException e) {
114             throw e.rethrowAsRuntimeException();
115         }
116     }
117 
118     /** @hide */
onStarted()119     void onStarted() {
120         executeCallback(() -> mCallback.onStarted(this));
121     }
122 
123     /** @hide */
onStartFail(int reason)124     void onStartFail(int reason) {
125         executeCallback(() -> mCallback.onStartFail(reason));
126     }
127 
128     /** @hide */
onStopped(int reason)129     void onStopped(int reason) {
130         executeCallback(() -> mCallback.onStopped(this, reason));
131     }
132 
133     /** @hide */
onResult(@onNull BluetoothDevice device, @NonNull DistanceMeasurementResult result)134     void onResult(@NonNull BluetoothDevice device, @NonNull DistanceMeasurementResult result) {
135         executeCallback(() -> mCallback.onResult(device, result));
136     }
137 
138     /** @hide */
executeCallback(@onNull Runnable runnable)139     private void executeCallback(@NonNull Runnable runnable) {
140         final long identity = Binder.clearCallingIdentity();
141         try {
142             mExecutor.execute(runnable);
143         } finally {
144             Binder.restoreCallingIdentity(identity);
145         }
146     }
147 
148     /**
149      * Interface for receiving {@link DistanceMeasurementSession} events.
150      *
151      * @hide
152      */
153     @SystemApi
154     public interface Callback {
155         /** @hide */
156         @Retention(RetentionPolicy.SOURCE)
157         @IntDef(
158                 value = {
159                     BluetoothStatusCodes.ERROR_UNKNOWN,
160                     BluetoothStatusCodes.FEATURE_NOT_SUPPORTED,
161                     BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED,
162                     BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST,
163                     BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST,
164                     BluetoothStatusCodes.REASON_REMOTE_REQUEST,
165                     BluetoothStatusCodes.ERROR_TIMEOUT,
166                     BluetoothStatusCodes.ERROR_NO_LE_CONNECTION,
167                     BluetoothStatusCodes.ERROR_BAD_PARAMETERS,
168                     BluetoothStatusCodes.ERROR_DISTANCE_MEASUREMENT_INTERNAL,
169                 })
170         @interface Reason {}
171 
172         /**
173          * Invoked when {@link DistanceMeasurementManager#startMeasurementSession(
174          * DistanceMeasurementParams, Executor, DistanceMeasurementSession.Callback)} is successful.
175          *
176          * @param session the started {@link DistanceMeasurementSession}
177          * @hide
178          */
179         @SystemApi
onStarted(@onNull DistanceMeasurementSession session)180         void onStarted(@NonNull DistanceMeasurementSession session);
181 
182         /**
183          * Invoked if {@link DistanceMeasurementManager#startMeasurementSession(
184          * DistanceMeasurementParams, Executor, DistanceMeasurementSession.Callback)} fails.
185          *
186          * @param reason the failure reason
187          * @hide
188          */
189         @SystemApi
onStartFail(@onNull @eason int reason)190         void onStartFail(@NonNull @Reason int reason);
191 
192         /**
193          * Invoked when a distance measurement session stopped.
194          *
195          * @param reason reason for the session stop
196          * @hide
197          */
198         @SystemApi
onStopped(@onNull DistanceMeasurementSession session, @NonNull @Reason int reason)199         void onStopped(@NonNull DistanceMeasurementSession session, @NonNull @Reason int reason);
200 
201         /**
202          * Invoked when get distance measurement result.
203          *
204          * @param device remote device
205          * @param result {@link DistanceMeasurementResult} for this device
206          * @hide
207          */
208         @SystemApi
onResult(@onNull BluetoothDevice device, @NonNull DistanceMeasurementResult result)209         void onResult(@NonNull BluetoothDevice device, @NonNull DistanceMeasurementResult result);
210     }
211 }
212