1 /* 2 * Copyright (C) 2021 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 package com.android.server.uwb.jni; 17 18 import android.annotation.NonNull; 19 import android.util.Log; 20 21 import com.android.internal.annotations.Keep; 22 import com.android.server.uwb.UciLogModeStore; 23 import com.android.server.uwb.UwbInjector; 24 import com.android.server.uwb.data.DtTagUpdateRangingRoundsStatus; 25 import com.android.server.uwb.data.UwbConfigStatusData; 26 import com.android.server.uwb.data.UwbMulticastListUpdateStatus; 27 import com.android.server.uwb.data.UwbRangingData; 28 import com.android.server.uwb.data.UwbTlvData; 29 import com.android.server.uwb.data.UwbUciConstants; 30 import com.android.server.uwb.data.UwbVendorUciResponse; 31 import com.android.server.uwb.info.UwbPowerStats; 32 import com.android.server.uwb.multchip.UwbMultichipData; 33 34 import java.util.Arrays; 35 36 @Keep 37 public class NativeUwbManager { 38 private static final String TAG = NativeUwbManager.class.getSimpleName(); 39 40 public final Object mNativeLock = new Object(); 41 private final UwbInjector mUwbInjector; 42 private final UciLogModeStore mUciLogModeStore; 43 private final UwbMultichipData mUwbMultichipData; 44 protected INativeUwbManager.DeviceNotification mDeviceListener; 45 protected INativeUwbManager.SessionNotification mSessionListener; 46 private long mDispatcherPointer; 47 protected INativeUwbManager.VendorNotification mVendorListener; 48 NativeUwbManager(@onNull UwbInjector uwbInjector, UciLogModeStore uciLogModeStore, UwbMultichipData uwbMultichipData)49 public NativeUwbManager(@NonNull UwbInjector uwbInjector, UciLogModeStore uciLogModeStore, 50 UwbMultichipData uwbMultichipData) { 51 mUwbInjector = uwbInjector; 52 mUciLogModeStore = uciLogModeStore; 53 mUwbMultichipData = uwbMultichipData; 54 loadLibrary(); 55 } 56 loadLibrary()57 protected void loadLibrary() { 58 System.loadLibrary("uwb_uci_jni_rust"); 59 synchronized (mNativeLock) { 60 nativeInit(); 61 } 62 } 63 setDeviceListener(INativeUwbManager.DeviceNotification deviceListener)64 public void setDeviceListener(INativeUwbManager.DeviceNotification deviceListener) { 65 mDeviceListener = deviceListener; 66 } 67 setSessionListener(INativeUwbManager.SessionNotification sessionListener)68 public void setSessionListener(INativeUwbManager.SessionNotification sessionListener) { 69 mSessionListener = sessionListener; 70 } 71 setVendorListener(INativeUwbManager.VendorNotification vendorListener)72 public void setVendorListener(INativeUwbManager.VendorNotification vendorListener) { 73 mVendorListener = vendorListener; 74 } 75 76 /** 77 * Device status callback invoked via the JNI 78 */ onDeviceStatusNotificationReceived(int deviceState, String chipId)79 public void onDeviceStatusNotificationReceived(int deviceState, String chipId) { 80 Log.d(TAG, "onDeviceStatusNotificationReceived(" + deviceState + ", " + chipId + ")"); 81 mDeviceListener.onDeviceStatusNotificationReceived(deviceState, chipId); 82 } 83 84 /** 85 * Error callback invoked via the JNI 86 */ onCoreGenericErrorNotificationReceived(int status, String chipId)87 public void onCoreGenericErrorNotificationReceived(int status, String chipId) { 88 Log.d(TAG, "onCoreGenericErrorNotificationReceived(" + status + ", " + chipId + ")"); 89 mDeviceListener.onCoreGenericErrorNotificationReceived(status, chipId); 90 } 91 onSessionStatusNotificationReceived(long id, int state, int reasonCode)92 public void onSessionStatusNotificationReceived(long id, int state, int reasonCode) { 93 Log.d(TAG, "onSessionStatusNotificationReceived(" + id + ", " + state + ", " + reasonCode 94 + ")"); 95 mSessionListener.onSessionStatusNotificationReceived(id, state, reasonCode); 96 } 97 onRangeDataNotificationReceived(UwbRangingData rangeData)98 public void onRangeDataNotificationReceived(UwbRangingData rangeData) { 99 Log.d(TAG, "onRangeDataNotificationReceived : " + rangeData); 100 mSessionListener.onRangeDataNotificationReceived(rangeData); 101 } 102 onMulticastListUpdateNotificationReceived( UwbMulticastListUpdateStatus multicastListUpdateData)103 public void onMulticastListUpdateNotificationReceived( 104 UwbMulticastListUpdateStatus multicastListUpdateData) { 105 Log.d(TAG, "onMulticastListUpdateNotificationReceived : " + multicastListUpdateData); 106 mSessionListener.onMulticastListUpdateNotificationReceived(multicastListUpdateData); 107 } 108 109 /** 110 * Vendor callback invoked via the JNI 111 */ onVendorUciNotificationReceived(int gid, int oid, byte[] payload)112 public void onVendorUciNotificationReceived(int gid, int oid, byte[] payload) { 113 Log.d(TAG, "onVendorUciNotificationReceived: " + gid + ", " + oid + ", " 114 + Arrays.toString(payload)); 115 mVendorListener.onVendorUciNotificationReceived(gid, oid, payload); 116 } 117 118 /** 119 * Enable UWB hardware. 120 * 121 * @return : If this returns true, UWB is on 122 */ doInitialize()123 public boolean doInitialize() { 124 synchronized (mNativeLock) { 125 mDispatcherPointer = nativeDispatcherNew(mUwbMultichipData.getChipIds().toArray()); 126 for (String chipId : mUwbMultichipData.getChipIds()) { 127 if (!nativeDoInitialize(chipId)) { 128 return false; 129 } 130 } 131 nativeSetLogMode(mUciLogModeStore.getMode()); 132 } 133 return true; 134 } 135 136 /** 137 * Disable UWB hardware. 138 * 139 * @return : If this returns true, UWB is off 140 */ doDeinitialize()141 public boolean doDeinitialize() { 142 synchronized (mNativeLock) { 143 for (String chipId : mUwbMultichipData.getChipIds()) { 144 nativeDoDeinitialize(chipId); 145 } 146 147 nativeDispatcherDestroy(); 148 mDispatcherPointer = 0L; 149 } 150 return true; 151 } 152 153 /** 154 * Gets the timestamp resolution in nanosecond 155 * 156 * @return : timestamp resolution in nanosecond 157 */ getTimestampResolutionNanos()158 public long getTimestampResolutionNanos() { 159 return 0L; 160 /* TODO: Not Implemented in native stack 161 return nativeGetTimestampResolutionNanos(); */ 162 } 163 164 /** 165 * Retrieves power related stats 166 */ getPowerStats(String chipId)167 public UwbPowerStats getPowerStats(String chipId) { 168 synchronized (mNativeLock) { 169 return nativeGetPowerStats(chipId); 170 } 171 } 172 173 /** 174 * Creates the new UWB session with parameter session ID and type of the session. 175 * 176 * @param sessionId : Session ID is 4 Octets unique random number generated by application 177 * @param sessionType : Type of session 0x00: Ranging session 0x01: Data transfer 0x02-0x9F: RFU 178 * 0xA0-0xCF: Reserved for Vendor Specific use case 0xD0: Device Test Mode 179 * 0xD1-0xDF: RFU 0xE0-0xFF: Vendor Specific use 180 * @param chipId : Identifier of UWB chip for multi-HAL devices 181 * @return : {@link UwbUciConstants} Status code 182 */ initSession(int sessionId, byte sessionType, String chipId)183 public byte initSession(int sessionId, byte sessionType, String chipId) { 184 synchronized (mNativeLock) { 185 return nativeSessionInit(sessionId, sessionType, chipId); 186 } 187 } 188 189 /** 190 * De-initializes the session. 191 * 192 * @param sessionId : Session ID for which session to be de-initialized 193 * @param chipId : Identifier of UWB chip for multi-HAL devices 194 * @return : {@link UwbUciConstants} Status code 195 */ deInitSession(int sessionId, String chipId)196 public byte deInitSession(int sessionId, String chipId) { 197 synchronized (mNativeLock) { 198 return nativeSessionDeInit(sessionId, chipId); 199 } 200 } 201 202 /** 203 * reset the UWBs 204 * 205 * @param resetConfig : Reset config 206 * @param chipId : Identifier of UWB chip for multi-HAL devices 207 * @return : {@link UwbUciConstants} Status code 208 */ deviceReset(byte resetConfig, String chipId)209 public byte deviceReset(byte resetConfig, String chipId) { 210 synchronized (mNativeLock) { 211 return nativeDeviceReset(resetConfig, chipId); 212 } 213 } 214 215 /** 216 * Retrieves number of UWB sessions in the UWBS. 217 * 218 * @param chipId : Identifier of UWB chip for multi-HAL devices 219 * @return : Number of UWB sessions present in the UWBS. 220 */ getSessionCount(String chipId)221 public byte getSessionCount(String chipId) { 222 synchronized (mNativeLock) { 223 return nativeGetSessionCount(chipId); 224 } 225 } 226 227 /** 228 * Queries the current state of the UWB session. 229 * 230 * @param sessionId : Session of the UWB session for which current session state to be queried 231 * @param chipId : Identifier of UWB chip for multi-HAL devices 232 * @return : {@link UwbUciConstants} Session State 233 */ getSessionState(int sessionId, String chipId)234 public byte getSessionState(int sessionId, String chipId) { 235 synchronized (mNativeLock) { 236 return nativeGetSessionState(sessionId, chipId); 237 } 238 } 239 240 /** 241 * Starts a UWB session. 242 * 243 * @param sessionId : Session ID for which ranging shall start 244 * @param chipId : Identifier of UWB chip for multi-HAL devices 245 * @return : {@link UwbUciConstants} Status code 246 */ startRanging(int sessionId, String chipId)247 public byte startRanging(int sessionId, String chipId) { 248 synchronized (mNativeLock) { 249 return nativeRangingStart(sessionId, chipId); 250 } 251 } 252 253 /** 254 * Stops the ongoing UWB session. 255 * 256 * @param sessionId : Stop the requested ranging session. 257 * @param chipId : Identifier of UWB chip for multi-HAL devices 258 * @return : {@link UwbUciConstants} Status code 259 */ stopRanging(int sessionId, String chipId)260 public byte stopRanging(int sessionId, String chipId) { 261 synchronized (mNativeLock) { 262 return nativeRangingStop(sessionId, chipId); 263 } 264 } 265 266 /** 267 * set APP Configuration Parameters for the requested UWB session 268 * 269 * @param noOfParams : The number (n) of APP Configuration Parameters 270 * @param appConfigParamLen : The length of APP Configuration Parameters 271 * @param appConfigParams : APP Configuration Parameter 272 * @param chipId : Identifier of UWB chip for multi-HAL devices 273 * @return : {@link UwbConfigStatusData} : Contains statuses for all cfg_id 274 */ setAppConfigurations(int sessionId, int noOfParams, int appConfigParamLen, byte[] appConfigParams, String chipId)275 public UwbConfigStatusData setAppConfigurations(int sessionId, int noOfParams, 276 int appConfigParamLen, byte[] appConfigParams, String chipId) { 277 synchronized (mNativeLock) { 278 return nativeSetAppConfigurations(sessionId, noOfParams, appConfigParamLen, 279 appConfigParams, chipId); 280 } 281 } 282 283 /** 284 * Get APP Configuration Parameters for the requested UWB session 285 * 286 * @param noOfParams : The number (n) of APP Configuration Parameters 287 * @param appConfigParamLen : The length of APP Configuration Parameters 288 * @param appConfigIds : APP Configuration Parameter 289 * @param chipId : Identifier of UWB chip for multi-HAL devices 290 * @return : {@link UwbTlvData} : All tlvs that are to be decoded 291 */ getAppConfigurations(int sessionId, int noOfParams, int appConfigParamLen, byte[] appConfigIds, String chipId)292 public UwbTlvData getAppConfigurations(int sessionId, int noOfParams, int appConfigParamLen, 293 byte[] appConfigIds, String chipId) { 294 synchronized (mNativeLock) { 295 return nativeGetAppConfigurations(sessionId, noOfParams, appConfigParamLen, 296 appConfigIds, chipId); 297 } 298 } 299 300 /** 301 * Get Core Capabilities information 302 * 303 * @param chipId : Identifier of UWB chip for multi-HAL devices 304 * @return : {@link UwbTlvData} : All tlvs that are to be decoded 305 */ getCapsInfo(String chipId)306 public UwbTlvData getCapsInfo(String chipId) { 307 synchronized (mNativeLock) { 308 return nativeGetCapsInfo(chipId); 309 } 310 } 311 312 /** 313 * Update Multicast list for the requested UWB session using V1 command. 314 * 315 * @param sessionId : Session ID to which multicast list to be updated 316 * @param action : Update the multicast list by adding or removing 317 * 0x00 - Adding 318 * 0x01 - removing 319 * 0x02 - Adding with 16 bits sub-session key 320 * 0x03 - Adding with 32 bits sub-session key 321 * @param noOfControlee : The number(n) of Controlees 322 * @param addresses : address list of Controlees 323 * @param subSessionIds : Specific sub-session ID list of Controlees 324 * @param subSessionKeyList : Sub-session key list of Controlees 325 * @return : refer to SESSION_SET_APP_CONFIG_RSP 326 * in the Table 16: Control messages to set Application configurations 327 */ controllerMulticastListUpdate(int sessionId, int action, int noOfControlee, byte[] addresses, int[] subSessionIds, byte[] subSessionKeyList, String chipId)328 public byte controllerMulticastListUpdate(int sessionId, int action, int noOfControlee, 329 byte[] addresses, int[] subSessionIds, byte[] subSessionKeyList, 330 String chipId) { 331 synchronized (mNativeLock) { 332 return nativeControllerMulticastListUpdate(sessionId, (byte) action, 333 (byte) noOfControlee, addresses, subSessionIds, subSessionKeyList, chipId); 334 } 335 } 336 337 /** 338 * Set country code. 339 * 340 * @param countryCode 2 char ISO country code 341 */ setCountryCode(byte[] countryCode)342 public byte setCountryCode(byte[] countryCode) { 343 Log.i(TAG, "setCountryCode: " + new String(countryCode)); 344 345 synchronized (mNativeLock) { 346 for (String chipId : mUwbMultichipData.getChipIds()) { 347 byte status = nativeSetCountryCode(countryCode, chipId); 348 if (status != UwbUciConstants.STATUS_CODE_OK) { 349 return status; 350 } 351 } 352 return UwbUciConstants.STATUS_CODE_OK; 353 } 354 } 355 356 /** 357 * Sets the log mode for the current and future UWB UCI messages. 358 * 359 * @param logModeStr is one of Disabled, Filtered, or Unfiltered (case insensitive). 360 * @return true if the log mode is set successfully, false otherwise. 361 */ setLogMode(String logModeStr)362 public boolean setLogMode(String logModeStr) { 363 synchronized (mNativeLock) { 364 return nativeSetLogMode(mUciLogModeStore.getMode()); 365 } 366 } 367 368 @NonNull sendRawVendorCmd(int mt, int gid, int oid, byte[] payload, String chipId)369 public UwbVendorUciResponse sendRawVendorCmd(int mt, int gid, int oid, byte[] payload, 370 String chipId) { 371 synchronized (mNativeLock) { 372 return nativeSendRawVendorCmd(mt, gid, oid, payload, chipId); 373 } 374 } 375 376 /** 377 * Receive payload data from a remote device in a UWB ranging session. 378 */ onDataReceived( long sessionID, int status, long sequenceNum, byte[] address, int sourceEndPoint, int destEndPoint, byte[] data)379 public void onDataReceived( 380 long sessionID, int status, long sequenceNum, byte[] address, 381 int sourceEndPoint, int destEndPoint, byte[] data) { 382 Log.d(TAG, "onDataReceived "); 383 mSessionListener.onDataReceived( 384 sessionID, status, sequenceNum, address, sourceEndPoint, destEndPoint, data); 385 } 386 387 /** 388 * Send payload data to a remote device in a UWB ranging session. 389 */ sendData( int sessionId, byte[] address, byte destEndPoint, byte sequenceNum, byte[] appData, String chipId)390 public byte sendData( 391 int sessionId, byte[] address, byte destEndPoint, byte sequenceNum, byte[] appData, 392 String chipId) { 393 synchronized (mNativeLock) { 394 return nativeSendData(sessionId, address, destEndPoint, sequenceNum, appData, chipId); 395 } 396 } 397 398 /** 399 * Receive the data transfer status for a UCI data packet earlier sent from Host to UWBS. 400 */ onDataSendStatus(long sessionId, int dataTransferStatus, long sequenceNum)401 public void onDataSendStatus(long sessionId, int dataTransferStatus, long sequenceNum) { 402 Log.d(TAG, "onDataSendStatus "); 403 mSessionListener.onDataSendStatus(sessionId, dataTransferStatus, sequenceNum); 404 } 405 406 /** 407 * Update Ranging Rounds for DT Tag 408 * 409 * @param sessionId Session ID to which ranging round to be updated 410 * @param noOfRangingRounds new active ranging round 411 * @param rangingRoundIndexes Indexes of ranging rounds 412 * @return refer to SESSION_SET_APP_CONFIG_RSP 413 * in the Table 16: Control messages to set Application configurations 414 */ sessionUpdateDtTagRangingRounds(int sessionId, int noOfRangingRounds, byte[] rangingRoundIndexes, String chipId)415 public DtTagUpdateRangingRoundsStatus sessionUpdateDtTagRangingRounds(int sessionId, 416 int noOfRangingRounds, byte[] rangingRoundIndexes, String chipId) { 417 synchronized (mNativeLock) { 418 return nativeSessionUpdateDtTagRangingRounds(sessionId, noOfRangingRounds, 419 rangingRoundIndexes, chipId); 420 } 421 } 422 423 /** 424 * Queries the max Application data size for the UWB session. 425 * 426 * @param sessionId : Session of the UWB session for which current max data size to be queried 427 * @param chipId : Identifier of UWB chip for multi-HAL devices 428 * @return : Max application data size that can be sent by UWBS. 429 */ queryMaxDataSizeBytes(int sessionId, String chipId)430 public int queryMaxDataSizeBytes(int sessionId, String chipId) { 431 synchronized (mNativeLock) { 432 return nativeQueryDataSize(sessionId, chipId); 433 } 434 } 435 436 /** 437 * Get session token from session id. 438 * 439 * @param sessionId : session id of uwb session 440 * @param chipId : Identifier of UWB chip for multi-HAL devices 441 * @return : session token generated for the session. 442 */ getSessionToken(int sessionId, String chipId)443 public int getSessionToken(int sessionId, String chipId) { 444 synchronized (mNativeLock) { 445 return nativeGetSessionToken(sessionId, chipId); 446 } 447 } 448 nativeSendData(int sessionId, byte[] address, byte destEndPoint, byte sequenceNum, byte[] appData, String chipId)449 private native byte nativeSendData(int sessionId, byte[] address, byte destEndPoint, 450 byte sequenceNum, byte[] appData, String chipId); 451 nativeDispatcherNew(Object[] chipIds)452 private native long nativeDispatcherNew(Object[] chipIds); 453 nativeDispatcherDestroy()454 private native void nativeDispatcherDestroy(); 455 nativeInit()456 private native boolean nativeInit(); 457 nativeDoInitialize(String chipIds)458 private native boolean nativeDoInitialize(String chipIds); 459 nativeDoDeinitialize(String chipId)460 private native boolean nativeDoDeinitialize(String chipId); 461 nativeGetTimestampResolutionNanos()462 private native long nativeGetTimestampResolutionNanos(); 463 nativeGetPowerStats(String chipId)464 private native UwbPowerStats nativeGetPowerStats(String chipId); 465 nativeDeviceReset(byte resetConfig, String chipId)466 private native byte nativeDeviceReset(byte resetConfig, String chipId); 467 nativeSessionInit(int sessionId, byte sessionType, String chipId)468 private native byte nativeSessionInit(int sessionId, byte sessionType, String chipId); 469 nativeSessionDeInit(int sessionId, String chipId)470 private native byte nativeSessionDeInit(int sessionId, String chipId); 471 nativeGetSessionCount(String chipId)472 private native byte nativeGetSessionCount(String chipId); 473 nativeRangingStart(int sessionId, String chipId)474 private native byte nativeRangingStart(int sessionId, String chipId); 475 nativeRangingStop(int sessionId, String chipId)476 private native byte nativeRangingStop(int sessionId, String chipId); 477 nativeGetSessionState(int sessionId, String chipId)478 private native byte nativeGetSessionState(int sessionId, String chipId); 479 nativeSetAppConfigurations(int sessionId, int noOfParams, int appConfigParamLen, byte[] appConfigParams, String chipId)480 private native UwbConfigStatusData nativeSetAppConfigurations(int sessionId, int noOfParams, 481 int appConfigParamLen, byte[] appConfigParams, String chipId); 482 nativeGetAppConfigurations(int sessionId, int noOfParams, int appConfigParamLen, byte[] appConfigParams, String chipId)483 private native UwbTlvData nativeGetAppConfigurations(int sessionId, int noOfParams, 484 int appConfigParamLen, byte[] appConfigParams, String chipId); 485 nativeGetCapsInfo(String chipId)486 private native UwbTlvData nativeGetCapsInfo(String chipId); 487 nativeControllerMulticastListUpdate(int sessionId, byte action, byte noOfControlee, byte[] address, int[] subSessionId, byte[] subSessionKeyList, String chipId)488 private native byte nativeControllerMulticastListUpdate(int sessionId, byte action, 489 byte noOfControlee, byte[] address, int[] subSessionId, byte[] subSessionKeyList, 490 String chipId); 491 nativeSetCountryCode(byte[] countryCode, String chipId)492 private native byte nativeSetCountryCode(byte[] countryCode, String chipId); 493 nativeSetLogMode(String logMode)494 private native boolean nativeSetLogMode(String logMode); 495 nativeSendRawVendorCmd(int mt, int gid, int oid, byte[] payload, String chipId)496 private native UwbVendorUciResponse nativeSendRawVendorCmd(int mt, int gid, int oid, 497 byte[] payload, String chipId); 498 nativeSessionUpdateDtTagRangingRounds( int sessionId, int noOfActiveRangingRounds, byte[] rangingRoundIndexes, String chipId)499 private native DtTagUpdateRangingRoundsStatus nativeSessionUpdateDtTagRangingRounds( 500 int sessionId, int noOfActiveRangingRounds, byte[] rangingRoundIndexes, String chipId); 501 nativeQueryDataSize(int sessionId, String chipId)502 private native short nativeQueryDataSize(int sessionId, String chipId); 503 nativeGetSessionToken(int sessionId, String chipId)504 private native int nativeGetSessionToken(int sessionId, String chipId); 505 } 506