1 /* 2 * Copyright 2020 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.uwb; 18 19 import android.annotation.NonNull; 20 import android.content.AttributionSource; 21 import android.os.CancellationSignal; 22 import android.os.PersistableBundle; 23 import android.os.RemoteException; 24 import android.util.Log; 25 26 import java.util.Hashtable; 27 import java.util.concurrent.Executor; 28 29 /** 30 * @hide 31 */ 32 public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub { 33 private static final String TAG = "Uwb.RangingManager"; 34 35 private final IUwbAdapter mAdapter; 36 private final Hashtable<SessionHandle, RangingSession> mRangingSessionTable = new Hashtable<>(); 37 private int mNextSessionId = 1; 38 RangingManager(IUwbAdapter adapter)39 public RangingManager(IUwbAdapter adapter) { 40 mAdapter = adapter; 41 } 42 43 /** 44 * Open a new ranging session 45 * 46 * @param attributionSource Attribution source to use for the enforcement of 47 * {@link android.Manifest.permission#ULTRAWIDEBAND_RANGING} runtime 48 * permission. 49 * @param params the parameters that define the ranging session 50 * @param executor {@link Executor} to run callbacks 51 * @param callbacks {@link RangingSession.Callback} to associate with the {@link RangingSession} 52 * that is being opened. 53 * @return a {@link CancellationSignal} that may be used to cancel the opening of the 54 * {@link RangingSession}. 55 */ openSession(@onNull AttributionSource attributionSource, @NonNull PersistableBundle params, @NonNull Executor executor, @NonNull RangingSession.Callback callbacks)56 public CancellationSignal openSession(@NonNull AttributionSource attributionSource, 57 @NonNull PersistableBundle params, 58 @NonNull Executor executor, 59 @NonNull RangingSession.Callback callbacks) { 60 synchronized (this) { 61 SessionHandle sessionHandle = new SessionHandle(mNextSessionId++); 62 RangingSession session = 63 new RangingSession(executor, callbacks, mAdapter, sessionHandle); 64 mRangingSessionTable.put(sessionHandle, session); 65 try { 66 mAdapter.openRanging(attributionSource, sessionHandle, this, params); 67 } catch (RemoteException e) { 68 throw e.rethrowFromSystemServer(); 69 } 70 71 CancellationSignal cancellationSignal = new CancellationSignal(); 72 cancellationSignal.setOnCancelListener(() -> session.close()); 73 return cancellationSignal; 74 } 75 } 76 hasSession(SessionHandle sessionHandle)77 private boolean hasSession(SessionHandle sessionHandle) { 78 return mRangingSessionTable.containsKey(sessionHandle); 79 } 80 81 @Override onRangingOpened(SessionHandle sessionHandle)82 public void onRangingOpened(SessionHandle sessionHandle) { 83 synchronized (this) { 84 if (!hasSession(sessionHandle)) { 85 Log.w(TAG, 86 "onRangingOpened - received unexpected SessionHandle: " + sessionHandle); 87 return; 88 } 89 90 RangingSession session = mRangingSessionTable.get(sessionHandle); 91 session.onRangingOpened(); 92 } 93 } 94 95 @Override onRangingOpenFailed(SessionHandle sessionHandle, @RangingChangeReason int reason, PersistableBundle parameters)96 public void onRangingOpenFailed(SessionHandle sessionHandle, @RangingChangeReason int reason, 97 PersistableBundle parameters) { 98 synchronized (this) { 99 if (!hasSession(sessionHandle)) { 100 Log.w(TAG, 101 "onRangingOpenedFailed - received unexpected SessionHandle: " 102 + sessionHandle); 103 return; 104 } 105 106 RangingSession session = mRangingSessionTable.get(sessionHandle); 107 session.onRangingOpenFailed(convertToReason(reason), parameters); 108 mRangingSessionTable.remove(sessionHandle); 109 } 110 } 111 112 @Override onRangingReconfigured(SessionHandle sessionHandle, PersistableBundle parameters)113 public void onRangingReconfigured(SessionHandle sessionHandle, PersistableBundle parameters) { 114 synchronized (this) { 115 if (!hasSession(sessionHandle)) { 116 Log.w(TAG, 117 "onRangingReconfigured - received unexpected SessionHandle: " 118 + sessionHandle); 119 return; 120 } 121 122 RangingSession session = mRangingSessionTable.get(sessionHandle); 123 session.onRangingReconfigured(parameters); 124 } 125 } 126 127 @Override onRangingReconfigureFailed(SessionHandle sessionHandle, @RangingChangeReason int reason, PersistableBundle params)128 public void onRangingReconfigureFailed(SessionHandle sessionHandle, 129 @RangingChangeReason int reason, PersistableBundle params) { 130 synchronized (this) { 131 if (!hasSession(sessionHandle)) { 132 Log.w(TAG, "onRangingReconfigureFailed - received unexpected SessionHandle: " 133 + sessionHandle); 134 return; 135 } 136 137 RangingSession session = mRangingSessionTable.get(sessionHandle); 138 session.onRangingReconfigureFailed(convertToReason(reason), params); 139 } 140 } 141 142 143 @Override onRangingStarted(SessionHandle sessionHandle, PersistableBundle parameters)144 public void onRangingStarted(SessionHandle sessionHandle, PersistableBundle parameters) { 145 synchronized (this) { 146 if (!hasSession(sessionHandle)) { 147 Log.w(TAG, 148 "onRangingStarted - received unexpected SessionHandle: " + sessionHandle); 149 return; 150 } 151 152 RangingSession session = mRangingSessionTable.get(sessionHandle); 153 session.onRangingStarted(parameters); 154 } 155 } 156 157 @Override onRangingStartFailed(SessionHandle sessionHandle, @RangingChangeReason int reason, PersistableBundle params)158 public void onRangingStartFailed(SessionHandle sessionHandle, @RangingChangeReason int reason, 159 PersistableBundle params) { 160 synchronized (this) { 161 if (!hasSession(sessionHandle)) { 162 Log.w(TAG, "onRangingStartFailed - received unexpected SessionHandle: " 163 + sessionHandle); 164 return; 165 } 166 167 RangingSession session = mRangingSessionTable.get(sessionHandle); 168 session.onRangingStartFailed(convertToReason(reason), params); 169 } 170 } 171 172 @Override onRangingStopped(SessionHandle sessionHandle, @RangingChangeReason int reason, PersistableBundle params)173 public void onRangingStopped(SessionHandle sessionHandle, @RangingChangeReason int reason, 174 PersistableBundle params) { 175 synchronized (this) { 176 if (!hasSession(sessionHandle)) { 177 Log.w(TAG, "onRangingStopped - received unexpected SessionHandle: " 178 + sessionHandle); 179 return; 180 } 181 182 RangingSession session = mRangingSessionTable.get(sessionHandle); 183 session.onRangingStopped(convertToReason(reason), params); 184 } 185 } 186 187 @Override onRangingStopFailed(SessionHandle sessionHandle, @RangingChangeReason int reason, PersistableBundle parameters)188 public void onRangingStopFailed(SessionHandle sessionHandle, @RangingChangeReason int reason, 189 PersistableBundle parameters) { 190 synchronized (this) { 191 if (!hasSession(sessionHandle)) { 192 Log.w(TAG, "onRangingStopFailed - received unexpected SessionHandle: " 193 + sessionHandle); 194 return; 195 } 196 197 RangingSession session = mRangingSessionTable.get(sessionHandle); 198 session.onRangingStopFailed(convertToReason(reason), parameters); 199 } 200 } 201 202 @Override onRangingClosed(SessionHandle sessionHandle, @RangingChangeReason int reason, PersistableBundle params)203 public void onRangingClosed(SessionHandle sessionHandle, @RangingChangeReason int reason, 204 PersistableBundle params) { 205 synchronized (this) { 206 if (!hasSession(sessionHandle)) { 207 Log.w(TAG, "onRangingClosed - received unexpected SessionHandle: " + sessionHandle); 208 return; 209 } 210 211 RangingSession session = mRangingSessionTable.get(sessionHandle); 212 session.onRangingClosed(convertToReason(reason), params); 213 mRangingSessionTable.remove(sessionHandle); 214 } 215 } 216 217 @Override onRangingResult(SessionHandle sessionHandle, RangingReport result)218 public void onRangingResult(SessionHandle sessionHandle, RangingReport result) { 219 synchronized (this) { 220 if (!hasSession(sessionHandle)) { 221 Log.w(TAG, "onRangingResult - received unexpected SessionHandle: " + sessionHandle); 222 return; 223 } 224 225 RangingSession session = mRangingSessionTable.get(sessionHandle); 226 session.onRangingResult(result); 227 } 228 } 229 230 @RangingSession.Callback.Reason convertToReason(@angingChangeReason int reason)231 private static int convertToReason(@RangingChangeReason int reason) { 232 switch (reason) { 233 case RangingChangeReason.LOCAL_API: 234 return RangingSession.Callback.REASON_LOCAL_REQUEST; 235 236 case RangingChangeReason.MAX_SESSIONS_REACHED: 237 return RangingSession.Callback.REASON_MAX_SESSIONS_REACHED; 238 239 case RangingChangeReason.SYSTEM_POLICY: 240 return RangingSession.Callback.REASON_SYSTEM_POLICY; 241 242 case RangingChangeReason.REMOTE_REQUEST: 243 return RangingSession.Callback.REASON_REMOTE_REQUEST; 244 245 case RangingChangeReason.PROTOCOL_SPECIFIC: 246 return RangingSession.Callback.REASON_PROTOCOL_SPECIFIC_ERROR; 247 248 case RangingChangeReason.BAD_PARAMETERS: 249 return RangingSession.Callback.REASON_BAD_PARAMETERS; 250 251 case RangingChangeReason.UNKNOWN: 252 default: 253 return RangingSession.Callback.REASON_UNKNOWN; 254 } 255 } 256 } 257