1 /* 2 * Copyright (C) 2025 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 com.android.cts.verifier.presence.cs; 18 19 import android.bluetooth.BluetoothDevice; 20 import android.content.Context; 21 import android.os.CancellationSignal; 22 import android.ranging.RangingData; 23 import android.ranging.RangingDevice; 24 import android.ranging.RangingManager; 25 import android.ranging.RangingPreference; 26 import android.ranging.RangingSession; 27 import android.ranging.SensorFusionParams; 28 import android.ranging.SessionConfig; 29 import android.ranging.ble.cs.BleCsRangingParams; 30 import android.ranging.raw.RawInitiatorRangingConfig; 31 import android.ranging.raw.RawRangingDevice; 32 import android.util.Log; 33 34 import androidx.annotation.Nullable; 35 36 import java.util.UUID; 37 import java.util.concurrent.Executor; 38 39 /** Measure the distance between 2 ble devices using channan sounding. */ 40 class CsRanger { 41 private static final String TAG = CsRanger.class.getName(); 42 private final Context mApplicationContext; 43 private final BluetoothDevice mTargetDevice; 44 private final UUID mTargetDeviceId; 45 private final RangingManager mRangingManager; 46 private final CsDistanceMeasurementCallback mDistanceMeasurementCallback; 47 private final Executor mExecutor; 48 @Nullable private RangingSession mSession = null; 49 @Nullable private CancellationSignal mCancellationSignal = null; 50 CsRanger( Context applicationContext, BluetoothDevice targetDevice, UUID targetDeviceId, CsDistanceMeasurementCallback distanceMeasurementCallback, Executor executor)51 CsRanger( 52 Context applicationContext, 53 BluetoothDevice targetDevice, 54 UUID targetDeviceId, 55 CsDistanceMeasurementCallback distanceMeasurementCallback, 56 Executor executor) { 57 this.mApplicationContext = applicationContext; 58 this.mTargetDevice = targetDevice; 59 this.mTargetDeviceId = targetDeviceId; 60 this.mDistanceMeasurementCallback = distanceMeasurementCallback; 61 this.mExecutor = executor; 62 mRangingManager = mApplicationContext.getSystemService(RangingManager.class); 63 } 64 startRanging()65 public void startRanging() { 66 RawRangingDevice.Builder rawRangingDeviceBuilder = 67 new RawRangingDevice.Builder() 68 .setRangingDevice( 69 new RangingDevice.Builder().setUuid(mTargetDeviceId).build()); 70 // Set the BLE channel sounding paramsters 71 rawRangingDeviceBuilder.setCsRangingParams( 72 new BleCsRangingParams.Builder(mTargetDevice.getAddress()).build()); 73 RawInitiatorRangingConfig rawInitiatorRangingConfig = 74 new RawInitiatorRangingConfig.Builder() 75 .addRawRangingDevice(rawRangingDeviceBuilder.build()) 76 .build(); 77 // disable the filter, test the raw device performance. 78 SessionConfig sessionConfig = 79 new SessionConfig.Builder() 80 .setSensorFusionParams( 81 new SensorFusionParams.Builder() 82 .setSensorFusionEnabled(false) 83 .build()) 84 .build(); 85 RangingPreference rangingPreference = 86 new RangingPreference.Builder( 87 RangingPreference.DEVICE_ROLE_INITIATOR, rawInitiatorRangingConfig) 88 .setSessionConfig(sessionConfig) 89 .build(); 90 mSession = mRangingManager.createRangingSession(mExecutor, mRangingSessionCallback); 91 mCancellationSignal = mSession.start(rangingPreference); 92 } 93 stopRanging()94 public void stopRanging() { 95 if (mSession == null || mCancellationSignal == null) { 96 return; 97 } 98 mCancellationSignal.cancel(); 99 mSession = null; 100 mCancellationSignal = null; 101 } 102 103 private RangingSession.Callback mRangingSessionCallback = 104 new RangingSession.Callback() { 105 106 public void onOpened() { 107 Log.d(TAG, "DistanceMeasurement onOpened! "); 108 } 109 110 public void onOpenFailed(int reason) { 111 Log.d(TAG, "DistanceMeasurement onOpenFailed! " + reason); 112 mDistanceMeasurementCallback.onStopWithError(mTargetDeviceId); 113 } 114 115 public void onStarted(RangingDevice peer, int technology) { 116 Log.d(TAG, "DistanceMeasurement onStarted ! "); 117 } 118 119 public void onStopped(RangingDevice peer, int technology) { 120 Log.d(TAG, "DistanceMeasurement onStopped! " + technology); 121 } 122 123 public void onClosed(int reason) { 124 Log.d(TAG, "DistanceMeasurement onClosed! " + reason); 125 if (reason != RangingSession.Callback.REASON_LOCAL_REQUEST) { 126 mDistanceMeasurementCallback.onStopWithError(mTargetDeviceId); 127 } 128 } 129 130 public void onResults(RangingDevice peer, RangingData data) { 131 Log.d(TAG, "DistanceMeasurement onResults ! " + peer + ": " + data); 132 mDistanceMeasurementCallback.onDistanceResult( 133 peer.getUuid(), data.getDistance().getMeasurement()); 134 } 135 }; 136 137 interface CsDistanceMeasurementCallback { onStopWithError(UUID deviceId)138 void onStopWithError(UUID deviceId); 139 onDistanceResult(UUID deviceId, double distanceMeters)140 void onDistanceResult(UUID deviceId, double distanceMeters); 141 } 142 } 143