1 /* 2 * Copyright (C) 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 package com.android.server.location.contexthub; 17 18 import android.annotation.NonNull; 19 import android.annotation.Nullable; 20 import android.hardware.contexthub.HostEndpointInfo; 21 import android.hardware.contexthub.NanSessionRequest; 22 import android.hardware.contexthub.V1_0.ContextHub; 23 import android.hardware.contexthub.V1_0.ContextHubMsg; 24 import android.hardware.contexthub.V1_0.TransactionResult; 25 import android.hardware.contexthub.V1_1.Setting; 26 import android.hardware.contexthub.V1_1.SettingValue; 27 import android.hardware.contexthub.V1_2.HubAppInfo; 28 import android.hardware.contexthub.V1_2.IContexthubCallback; 29 import android.hardware.location.ContextHubInfo; 30 import android.hardware.location.ContextHubTransaction; 31 import android.hardware.location.NanoAppBinary; 32 import android.hardware.location.NanoAppMessage; 33 import android.hardware.location.NanoAppState; 34 import android.os.Handler; 35 import android.os.HandlerThread; 36 import android.os.IBinder; 37 import android.os.Process; 38 import android.os.RemoteException; 39 import android.os.ServiceManager; 40 import android.os.ServiceSpecificException; 41 import android.util.Log; 42 import android.util.Pair; 43 44 import java.util.ArrayList; 45 import java.util.Arrays; 46 import java.util.Collections; 47 import java.util.HashMap; 48 import java.util.HashSet; 49 import java.util.List; 50 import java.util.Map; 51 import java.util.NoSuchElementException; 52 import java.util.Set; 53 54 /** 55 * @hide 56 */ 57 public abstract class IContextHubWrapper { 58 private static final String TAG = "IContextHubWrapper"; 59 60 /** 61 * The callback interface to use in registerCallback. 62 */ 63 public interface ICallback { 64 /** 65 * @param transactionId The ID of the transaction that completed. 66 * @param success true if the transaction succeeded. 67 */ handleTransactionResult(int transactionId, boolean success)68 void handleTransactionResult(int transactionId, boolean success); 69 70 /** 71 * @param eventType The Context Hub event type defined by ContextHubService 72 * .CONTEXT_HUB_EVENT_*. 73 */ handleContextHubEvent(int eventType)74 void handleContextHubEvent(int eventType); 75 76 /** 77 * @param nanoappId The ID of the nanoapp that aborted. 78 * @param abortCode The nanoapp-defined abort code. 79 */ handleNanoappAbort(long nanoappId, int abortCode)80 void handleNanoappAbort(long nanoappId, int abortCode); 81 82 /** 83 * @param nanoappStateList The list of loaded nanoapps on the Context Hub. 84 */ handleNanoappInfo(List<NanoAppState> nanoappStateList)85 void handleNanoappInfo(List<NanoAppState> nanoappStateList); 86 87 /** 88 * Handles a message from a nanoapp to a ContextHubClient. 89 * 90 * @param hostEndpointId The host endpoint ID of the recipient. 91 * @param message The message from the nanoapp. 92 * @param nanoappPermissions The list of permissions held by the nanoapp. 93 * @param messagePermissions The list of permissions required to receive the message. 94 */ handleNanoappMessage(short hostEndpointId, NanoAppMessage message, List<String> nanoappPermissions, List<String> messagePermissions)95 void handleNanoappMessage(short hostEndpointId, NanoAppMessage message, 96 List<String> nanoappPermissions, List<String> messagePermissions); 97 98 /** 99 * Handles a restart of the service 100 */ handleServiceRestart()101 void handleServiceRestart(); 102 } 103 104 /** 105 * @return the IContextHubWrapper interface 106 */ getContextHubWrapper()107 public static IContextHubWrapper getContextHubWrapper() { 108 IContextHubWrapper wrapper = maybeConnectToAidl(); 109 if (wrapper == null) { 110 wrapper = maybeConnectTo1_2(); 111 } 112 if (wrapper == null) { 113 wrapper = maybeConnectTo1_1(); 114 } 115 if (wrapper == null) { 116 wrapper = maybeConnectTo1_0(); 117 } 118 119 return wrapper; 120 } 121 122 /** 123 * Attempts to connect to the Contexthub HAL 1.0 service, if it exists. 124 * 125 * @return A valid IContextHubWrapper if the connection was successful, null otherwise. 126 */ 127 @Nullable maybeConnectTo1_0()128 public static IContextHubWrapper maybeConnectTo1_0() { 129 android.hardware.contexthub.V1_0.IContexthub proxy = null; 130 try { 131 proxy = android.hardware.contexthub.V1_0.IContexthub.getService(true /* retry */); 132 } catch (RemoteException e) { 133 Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e); 134 } catch (NoSuchElementException e) { 135 Log.i(TAG, "Context Hub HAL service not found"); 136 } 137 138 return (proxy == null) ? null : new ContextHubWrapperV1_0(proxy); 139 } 140 141 /** 142 * Attempts to connect to the Contexthub HAL 1.1 service, if it exists. 143 * 144 * @return A valid IContextHubWrapper if the connection was successful, null otherwise. 145 */ 146 @Nullable maybeConnectTo1_1()147 public static IContextHubWrapper maybeConnectTo1_1() { 148 android.hardware.contexthub.V1_1.IContexthub proxy = null; 149 try { 150 proxy = android.hardware.contexthub.V1_1.IContexthub.getService(true /* retry */); 151 } catch (RemoteException e) { 152 Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e); 153 } catch (NoSuchElementException e) { 154 Log.i(TAG, "Context Hub HAL service not found"); 155 } 156 157 return (proxy == null) ? null : new ContextHubWrapperV1_1(proxy); 158 } 159 160 /** 161 * Attempts to connect to the Contexthub HAL 1.2 service, if it exists. 162 * 163 * @return A valid IContextHubWrapper if the connection was successful, null otherwise. 164 */ 165 @Nullable maybeConnectTo1_2()166 public static IContextHubWrapper maybeConnectTo1_2() { 167 android.hardware.contexthub.V1_2.IContexthub proxy = null; 168 try { 169 proxy = android.hardware.contexthub.V1_2.IContexthub.getService(true /* retry */); 170 } catch (RemoteException e) { 171 Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e); 172 } catch (NoSuchElementException e) { 173 Log.i(TAG, "Context Hub HAL service not found"); 174 } 175 176 return (proxy == null) ? null : new ContextHubWrapperV1_2(proxy); 177 } 178 179 /** 180 * Attempts to connect to the AIDL HAL and returns the proxy IContextHub. 181 */ maybeConnectToAidlGetProxy()182 public static android.hardware.contexthub.IContextHub maybeConnectToAidlGetProxy() { 183 android.hardware.contexthub.IContextHub proxy = null; 184 final String aidlServiceName = 185 android.hardware.contexthub.IContextHub.class.getCanonicalName() + "/default"; 186 if (ServiceManager.isDeclared(aidlServiceName)) { 187 proxy = android.hardware.contexthub.IContextHub.Stub.asInterface( 188 ServiceManager.waitForService(aidlServiceName)); 189 if (proxy == null) { 190 Log.e(TAG, "Context Hub AIDL service was declared but was not found"); 191 } 192 } else { 193 Log.d(TAG, "Context Hub AIDL service is not declared"); 194 } 195 return proxy; 196 } 197 198 /** 199 * Attempts to connect to the Contexthub HAL AIDL service, if it exists. 200 * 201 * @return A valid IContextHubWrapper if the connection was successful, null otherwise. 202 */ 203 @Nullable maybeConnectToAidl()204 public static IContextHubWrapper maybeConnectToAidl() { 205 android.hardware.contexthub.IContextHub proxy = maybeConnectToAidlGetProxy(); 206 return proxy == null ? null : new ContextHubWrapperAidl(proxy); 207 } 208 209 /** 210 * Calls the appropriate getHubs function depending on the HAL version. 211 */ getHubs()212 public abstract Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException; 213 214 /** 215 * @return True if this version of the Contexthub HAL supports Location setting notifications. 216 */ supportsLocationSettingNotifications()217 public abstract boolean supportsLocationSettingNotifications(); 218 219 /** 220 * Notifies the Contexthub implementation of a user Location setting change. 221 * 222 * @param enabled True if the Location setting has been enabled. 223 */ onLocationSettingChanged(boolean enabled)224 public abstract void onLocationSettingChanged(boolean enabled); 225 226 /** 227 * @return True if this version of the Contexthub HAL supports WiFi availability setting 228 * notifications. 229 */ supportsWifiSettingNotifications()230 public abstract boolean supportsWifiSettingNotifications(); 231 232 /** 233 * Notifies the Contexthub implementation of a user WiFi availability setting change. 234 * 235 * @param enabled true if the WiFi availability setting has been enabled. 236 */ onWifiSettingChanged(boolean enabled)237 public abstract void onWifiSettingChanged(boolean enabled); 238 239 /** 240 * Notifies the Contexthub implementation of a user WiFi main setting change. 241 * 242 * @param enabled true if the WiFi main setting has been enabled. 243 */ onWifiMainSettingChanged(boolean enabled)244 public abstract void onWifiMainSettingChanged(boolean enabled); 245 246 /** 247 * Notifies the Contexthub implementation of a user WiFi scanning setting change. 248 * 249 * @param enabled true if the WiFi scanning setting has been enabled. 250 */ onWifiScanningSettingChanged(boolean enabled)251 public abstract void onWifiScanningSettingChanged(boolean enabled); 252 253 /** 254 * @return True if this version of the Contexthub HAL supports airplane mode setting 255 * notifications. 256 */ supportsAirplaneModeSettingNotifications()257 public abstract boolean supportsAirplaneModeSettingNotifications(); 258 259 /** 260 * Notifies the Contexthub implementation of an airplane mode setting change. 261 * 262 * @param enabled true if the airplane mode setting has been enabled. 263 */ onAirplaneModeSettingChanged(boolean enabled)264 public abstract void onAirplaneModeSettingChanged(boolean enabled); 265 266 /** 267 * @return True if this version of the Contexthub HAL supports microphone setting 268 * notifications. 269 */ supportsMicrophoneSettingNotifications()270 public abstract boolean supportsMicrophoneSettingNotifications(); 271 272 /** 273 * Notifies the Contexthub implementation of a microphone setting change. 274 */ onMicrophoneSettingChanged(boolean enabled)275 public abstract void onMicrophoneSettingChanged(boolean enabled); 276 277 /** 278 * @return True if this version of the Contexthub HAL supports BT availability setting 279 * notifications. 280 */ supportsBtSettingNotifications()281 public abstract boolean supportsBtSettingNotifications(); 282 283 /** 284 * Notifies the Contexthub implementation of a BT main setting change. 285 */ onBtMainSettingChanged(boolean enabled)286 public abstract void onBtMainSettingChanged(boolean enabled); 287 288 /** 289 * Notifies the Contexthub implementation of a BT scanning setting change. 290 */ onBtScanningSettingChanged(boolean enabled)291 public abstract void onBtScanningSettingChanged(boolean enabled); 292 293 /** 294 * Invoked whenever a host client connects with the framework. 295 * 296 * @param info The host endpoint info. 297 */ onHostEndpointConnected(HostEndpointInfo info)298 public void onHostEndpointConnected(HostEndpointInfo info) {} 299 300 /** 301 * Invoked whenever a host client disconnects from the framework. 302 * 303 * @param hostEndpointId The ID of the host endpoint that disconnected. 304 */ onHostEndpointDisconnected(short hostEndpointId)305 public void onHostEndpointDisconnected(short hostEndpointId) {} 306 307 /** 308 * Sends a message to the Context Hub. 309 * 310 * @param hostEndpointId The host endpoint ID of the sender. 311 * @param contextHubId The ID of the Context Hub to send the message to. 312 * @param message The message to send. 313 * @return the result of the message sending. 314 */ 315 @ContextHubTransaction.Result sendMessageToContextHub( short hostEndpointId, int contextHubId, NanoAppMessage message)316 public abstract int sendMessageToContextHub( 317 short hostEndpointId, int contextHubId, NanoAppMessage message) 318 throws RemoteException; 319 320 /** 321 * Loads a nanoapp on the Context Hub. 322 * 323 * @param contextHubId The ID of the Context Hub to load the nanoapp to. 324 * @param binary The nanoapp binary to load. 325 * @param transactionId The transaction ID of this load. 326 * @return the result of this load transaction. 327 */ 328 @ContextHubTransaction.Result loadNanoapp(int contextHubId, NanoAppBinary binary, int transactionId)329 public abstract int loadNanoapp(int contextHubId, NanoAppBinary binary, 330 int transactionId) throws RemoteException; 331 332 /** 333 * Unloads a nanoapp on the Context Hub. Semantics are similar to loadNanoapp(). 334 */ 335 @ContextHubTransaction.Result unloadNanoapp(int contextHubId, long nanoappId, int transactionId)336 public abstract int unloadNanoapp(int contextHubId, long nanoappId, 337 int transactionId) throws RemoteException; 338 339 /** 340 * Enables a nanoapp on the Context Hub. Semantics are similar to loadNanoapp(). 341 */ 342 @ContextHubTransaction.Result enableNanoapp(int contextHubId, long nanoappId, int transactionId)343 public abstract int enableNanoapp(int contextHubId, long nanoappId, 344 int transactionId) throws RemoteException; 345 346 /** 347 * Disables a nanoapp on the Context Hub. Semantics are similar to loadNanoapp(). 348 */ 349 @ContextHubTransaction.Result disableNanoapp(int contextHubId, long nanoappId, int transactionId)350 public abstract int disableNanoapp(int contextHubId, long nanoappId, 351 int transactionId) throws RemoteException; 352 353 /** 354 * Queries a list of nanoapp from the Context hub. 355 * 356 * @param contextHubId The ID of the Context Hub to query. 357 * @return the result of this query transaction. 358 */ 359 @ContextHubTransaction.Result queryNanoapps(int contextHubId)360 public abstract int queryNanoapps(int contextHubId) throws RemoteException; 361 362 /** 363 * Provides the list of preloaded nanoapp IDs on the system. The output of this API must 364 * not change. 365 * 366 * @param contextHubId The context Hub ID. 367 * 368 * @return The list of preloaded nanoapp IDs. 369 */ getPreloadedNanoappIds(int contextHubId)370 public abstract long[] getPreloadedNanoappIds(int contextHubId); 371 372 /** 373 * Registers a callback with the Context Hub. 374 * 375 * @param contextHubId The ID of the Context Hub to register the callback with. 376 * @param callback The callback to register. 377 */ registerCallback(int contextHubId, @NonNull ICallback callback)378 public abstract void registerCallback(int contextHubId, @NonNull ICallback callback) 379 throws RemoteException; 380 381 /** 382 * Registers an existing callback with the Context Hub. 383 * 384 * @param contextHubId The ID of the Context Hub to register the callback with. 385 */ registerExistingCallback(int contextHubId)386 public abstract void registerExistingCallback(int contextHubId) throws RemoteException; 387 388 /** 389 * Puts the context hub in and out of test mode. Test mode is a clean state 390 * where tests can be executed in the same environment. If enable is true, 391 * this will enable test mode by unloading all nanoapps. If enable is false, 392 * this will disable test mode and reverse the actions of enabling test mode 393 * by loading all preloaded nanoapps. This puts CHRE in a normal state. 394 * 395 * This should only be used for a test environment, either through a 396 * @TestApi or development tools. This should not be used in a production 397 * environment. 398 * 399 * @param enable If true, put the context hub in test mode. If false, disable 400 * test mode. 401 * @return If true, the operation was successful; false otherwise. 402 */ setTestMode(boolean enable)403 public abstract boolean setTestMode(boolean enable); 404 405 private static class ContextHubWrapperAidl extends IContextHubWrapper 406 implements IBinder.DeathRecipient { 407 private android.hardware.contexthub.IContextHub mHub; 408 409 private final Map<Integer, ContextHubAidlCallback> mAidlCallbackMap = 410 new HashMap<>(); 411 412 private Runnable mHandleServiceRestartCallback = null; 413 414 // Use this thread in case where the execution requires to be on a service thread. 415 // For instance, AppOpsManager.noteOp requires the UPDATE_APP_OPS_STATS permission. 416 private HandlerThread mHandlerThread = 417 new HandlerThread("Context Hub AIDL callback", Process.THREAD_PRIORITY_BACKGROUND); 418 private Handler mHandler; 419 420 private class ContextHubAidlCallback extends 421 android.hardware.contexthub.IContextHubCallback.Stub { 422 private final int mContextHubId; 423 private final ICallback mCallback; 424 ContextHubAidlCallback(int contextHubId, ICallback callback)425 ContextHubAidlCallback(int contextHubId, ICallback callback) { 426 mContextHubId = contextHubId; 427 mCallback = callback; 428 } 429 handleNanoappInfo(android.hardware.contexthub.NanoappInfo[] appInfo)430 public void handleNanoappInfo(android.hardware.contexthub.NanoappInfo[] appInfo) { 431 List<NanoAppState> nanoAppStateList = 432 ContextHubServiceUtil.createNanoAppStateList(appInfo); 433 mHandler.post(() -> { 434 mCallback.handleNanoappInfo(nanoAppStateList); 435 }); 436 } 437 handleContextHubMessage(android.hardware.contexthub.ContextHubMessage msg, String[] msgContentPerms)438 public void handleContextHubMessage(android.hardware.contexthub.ContextHubMessage msg, 439 String[] msgContentPerms) { 440 mHandler.post(() -> { 441 mCallback.handleNanoappMessage( 442 (short) msg.hostEndPoint, 443 ContextHubServiceUtil.createNanoAppMessage(msg), 444 new ArrayList<>(Arrays.asList(msg.permissions)), 445 new ArrayList<>(Arrays.asList(msgContentPerms))); 446 }); 447 } 448 handleContextHubAsyncEvent(int evt)449 public void handleContextHubAsyncEvent(int evt) { 450 mHandler.post(() -> { 451 mCallback.handleContextHubEvent( 452 ContextHubServiceUtil.toContextHubEventFromAidl(evt)); 453 }); 454 } 455 handleTransactionResult(int transactionId, boolean success)456 public void handleTransactionResult(int transactionId, boolean success) { 457 mHandler.post(() -> { 458 mCallback.handleTransactionResult(transactionId, success); 459 }); 460 } 461 handleNanSessionRequest(NanSessionRequest request)462 public void handleNanSessionRequest(NanSessionRequest request) { 463 // TODO(271471342): Implement 464 } 465 466 @Override getInterfaceHash()467 public String getInterfaceHash() { 468 return android.hardware.contexthub.IContextHubCallback.HASH; 469 } 470 471 @Override getInterfaceVersion()472 public int getInterfaceVersion() { 473 return android.hardware.contexthub.IContextHubCallback.VERSION; 474 } 475 } 476 ContextHubWrapperAidl(android.hardware.contexthub.IContextHub hub)477 ContextHubWrapperAidl(android.hardware.contexthub.IContextHub hub) { 478 setHub(hub); 479 mHandlerThread.start(); 480 mHandler = new Handler(mHandlerThread.getLooper()); 481 linkWrapperToHubDeath(); 482 } 483 getHub()484 private synchronized android.hardware.contexthub.IContextHub getHub() { 485 return mHub; 486 } 487 setHub(android.hardware.contexthub.IContextHub hub)488 private synchronized void setHub(android.hardware.contexthub.IContextHub hub) { 489 mHub = hub; 490 } 491 492 @Override binderDied()493 public void binderDied() { 494 Log.i(TAG, "Context Hub AIDL HAL died"); 495 496 setHub(maybeConnectToAidlGetProxy()); 497 if (getHub() == null) { 498 // TODO(b/256860015): Make this reconnection more robust 499 Log.e(TAG, "Could not reconnect to Context Hub AIDL HAL"); 500 return; 501 } 502 linkWrapperToHubDeath(); 503 504 if (mHandleServiceRestartCallback != null) { 505 mHandleServiceRestartCallback.run(); 506 } else { 507 Log.e(TAG, "mHandleServiceRestartCallback is not set"); 508 } 509 } 510 getHubs()511 public Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException { 512 android.hardware.contexthub.IContextHub hub = getHub(); 513 if (hub == null) { 514 return new Pair<List<ContextHubInfo>, List<String>>(new ArrayList<ContextHubInfo>(), 515 new ArrayList<String>()); 516 } 517 518 Set<String> supportedPermissions = new HashSet<>(); 519 ArrayList<ContextHubInfo> hubInfoList = new ArrayList<>(); 520 for (android.hardware.contexthub.ContextHubInfo hubInfo : hub.getContextHubs()) { 521 hubInfoList.add(new ContextHubInfo(hubInfo)); 522 for (String permission : hubInfo.supportedPermissions) { 523 supportedPermissions.add(permission); 524 } 525 } 526 return new Pair(hubInfoList, new ArrayList<String>(supportedPermissions)); 527 } 528 supportsLocationSettingNotifications()529 public boolean supportsLocationSettingNotifications() { 530 return true; 531 } 532 supportsWifiSettingNotifications()533 public boolean supportsWifiSettingNotifications() { 534 return true; 535 } 536 supportsAirplaneModeSettingNotifications()537 public boolean supportsAirplaneModeSettingNotifications() { 538 return true; 539 } 540 supportsMicrophoneSettingNotifications()541 public boolean supportsMicrophoneSettingNotifications() { 542 return true; 543 } 544 supportsBtSettingNotifications()545 public boolean supportsBtSettingNotifications() { 546 return true; 547 } 548 onLocationSettingChanged(boolean enabled)549 public void onLocationSettingChanged(boolean enabled) { 550 onSettingChanged(android.hardware.contexthub.Setting.LOCATION, enabled); 551 } 552 onWifiSettingChanged(boolean enabled)553 public void onWifiSettingChanged(boolean enabled) { 554 } 555 onAirplaneModeSettingChanged(boolean enabled)556 public void onAirplaneModeSettingChanged(boolean enabled) { 557 onSettingChanged(android.hardware.contexthub.Setting.AIRPLANE_MODE, enabled); 558 } 559 onMicrophoneSettingChanged(boolean enabled)560 public void onMicrophoneSettingChanged(boolean enabled) { 561 onSettingChanged(android.hardware.contexthub.Setting.MICROPHONE, enabled); 562 } 563 onWifiMainSettingChanged(boolean enabled)564 public void onWifiMainSettingChanged(boolean enabled) { 565 onSettingChanged(android.hardware.contexthub.Setting.WIFI_MAIN, enabled); 566 } 567 onWifiScanningSettingChanged(boolean enabled)568 public void onWifiScanningSettingChanged(boolean enabled) { 569 onSettingChanged(android.hardware.contexthub.Setting.WIFI_SCANNING, enabled); 570 } 571 onBtMainSettingChanged(boolean enabled)572 public void onBtMainSettingChanged(boolean enabled) { 573 onSettingChanged(android.hardware.contexthub.Setting.BT_MAIN, enabled); 574 } 575 onBtScanningSettingChanged(boolean enabled)576 public void onBtScanningSettingChanged(boolean enabled) { 577 onSettingChanged(android.hardware.contexthub.Setting.BT_SCANNING, enabled); 578 } 579 580 @Override onHostEndpointConnected(HostEndpointInfo info)581 public void onHostEndpointConnected(HostEndpointInfo info) { 582 android.hardware.contexthub.IContextHub hub = getHub(); 583 if (hub == null) { 584 return; 585 } 586 587 try { 588 hub.onHostEndpointConnected(info); 589 } catch (RemoteException | ServiceSpecificException e) { 590 Log.e(TAG, "Exception in onHostEndpointConnected" + e.getMessage()); 591 } 592 } 593 594 @Override onHostEndpointDisconnected(short hostEndpointId)595 public void onHostEndpointDisconnected(short hostEndpointId) { 596 android.hardware.contexthub.IContextHub hub = getHub(); 597 if (hub == null) { 598 return; 599 } 600 601 try { 602 hub.onHostEndpointDisconnected((char) hostEndpointId); 603 } catch (RemoteException | ServiceSpecificException e) { 604 Log.e(TAG, "Exception in onHostEndpointDisconnected" + e.getMessage()); 605 } 606 } 607 608 @ContextHubTransaction.Result sendMessageToContextHub( short hostEndpointId, int contextHubId, NanoAppMessage message)609 public int sendMessageToContextHub( 610 short hostEndpointId, int contextHubId, NanoAppMessage message) 611 throws RemoteException { 612 android.hardware.contexthub.IContextHub hub = getHub(); 613 if (hub == null) { 614 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 615 } 616 617 try { 618 hub.sendMessageToHub(contextHubId, 619 ContextHubServiceUtil.createAidlContextHubMessage(hostEndpointId, message)); 620 return ContextHubTransaction.RESULT_SUCCESS; 621 } catch (RemoteException | ServiceSpecificException e) { 622 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 623 } catch (IllegalArgumentException e) { 624 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 625 } 626 } 627 628 @ContextHubTransaction.Result loadNanoapp(int contextHubId, NanoAppBinary binary, int transactionId)629 public int loadNanoapp(int contextHubId, NanoAppBinary binary, 630 int transactionId) throws RemoteException { 631 android.hardware.contexthub.IContextHub hub = getHub(); 632 if (hub == null) { 633 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 634 } 635 636 android.hardware.contexthub.NanoappBinary aidlNanoAppBinary = 637 ContextHubServiceUtil.createAidlNanoAppBinary(binary); 638 try { 639 hub.loadNanoapp(contextHubId, aidlNanoAppBinary, transactionId); 640 return ContextHubTransaction.RESULT_SUCCESS; 641 } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { 642 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 643 } catch (IllegalArgumentException e) { 644 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 645 } 646 } 647 648 @ContextHubTransaction.Result unloadNanoapp(int contextHubId, long nanoappId, int transactionId)649 public int unloadNanoapp(int contextHubId, long nanoappId, int transactionId) 650 throws RemoteException { 651 android.hardware.contexthub.IContextHub hub = getHub(); 652 if (hub == null) { 653 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 654 } 655 656 try { 657 hub.unloadNanoapp(contextHubId, nanoappId, transactionId); 658 return ContextHubTransaction.RESULT_SUCCESS; 659 } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { 660 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 661 } catch (IllegalArgumentException e) { 662 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 663 } 664 } 665 666 @ContextHubTransaction.Result enableNanoapp(int contextHubId, long nanoappId, int transactionId)667 public int enableNanoapp(int contextHubId, long nanoappId, int transactionId) 668 throws RemoteException { 669 android.hardware.contexthub.IContextHub hub = getHub(); 670 if (hub == null) { 671 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 672 } 673 674 try { 675 hub.enableNanoapp(contextHubId, nanoappId, transactionId); 676 return ContextHubTransaction.RESULT_SUCCESS; 677 } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { 678 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 679 } catch (IllegalArgumentException e) { 680 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 681 } 682 } 683 684 @ContextHubTransaction.Result disableNanoapp(int contextHubId, long nanoappId, int transactionId)685 public int disableNanoapp(int contextHubId, long nanoappId, int transactionId) 686 throws RemoteException { 687 android.hardware.contexthub.IContextHub hub = getHub(); 688 if (hub == null) { 689 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 690 } 691 692 try { 693 hub.disableNanoapp(contextHubId, nanoappId, transactionId); 694 return ContextHubTransaction.RESULT_SUCCESS; 695 } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { 696 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 697 } catch (IllegalArgumentException e) { 698 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 699 } 700 } 701 702 @ContextHubTransaction.Result queryNanoapps(int contextHubId)703 public int queryNanoapps(int contextHubId) throws RemoteException { 704 android.hardware.contexthub.IContextHub hub = getHub(); 705 if (hub == null) { 706 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 707 } 708 709 try { 710 hub.queryNanoapps(contextHubId); 711 return ContextHubTransaction.RESULT_SUCCESS; 712 } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { 713 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 714 } catch (IllegalArgumentException e) { 715 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 716 } 717 } 718 getPreloadedNanoappIds(int contextHubId)719 public long[] getPreloadedNanoappIds(int contextHubId) { 720 android.hardware.contexthub.IContextHub hub = getHub(); 721 if (hub == null) { 722 return null; 723 } 724 725 try { 726 return hub.getPreloadedNanoappIds(contextHubId); 727 } catch (RemoteException e) { 728 Log.e(TAG, "Exception while getting preloaded nanoapp IDs: " + e.getMessage()); 729 return null; 730 } 731 } 732 registerExistingCallback(int contextHubId)733 public void registerExistingCallback(int contextHubId) { 734 android.hardware.contexthub.IContextHub hub = getHub(); 735 if (hub == null) { 736 return; 737 } 738 739 ContextHubAidlCallback callback = mAidlCallbackMap.get(contextHubId); 740 if (callback == null) { 741 Log.e(TAG, "Could not find existing callback to register for context hub ID = " 742 + contextHubId); 743 return; 744 } 745 746 try { 747 hub.registerCallback(contextHubId, callback); 748 } catch (RemoteException | ServiceSpecificException | IllegalArgumentException e) { 749 Log.e(TAG, "Exception while registering callback: " + e.getMessage()); 750 } 751 } 752 registerCallback(int contextHubId, ICallback callback)753 public void registerCallback(int contextHubId, ICallback callback) { 754 android.hardware.contexthub.IContextHub hub = getHub(); 755 if (hub == null) { 756 return; 757 } 758 759 mHandleServiceRestartCallback = callback::handleServiceRestart; 760 mAidlCallbackMap.put(contextHubId, new ContextHubAidlCallback(contextHubId, callback)); 761 registerExistingCallback(contextHubId); 762 } 763 setTestMode(boolean enable)764 public boolean setTestMode(boolean enable) { 765 android.hardware.contexthub.IContextHub hub = getHub(); 766 if (hub == null) { 767 return false; 768 } 769 770 try { 771 hub.setTestMode(enable); 772 return true; 773 } catch (RemoteException | ServiceSpecificException e) { 774 Log.e(TAG, "Exception while setting test mode (enable: " 775 + (enable ? "true" : "false") + "): " + e.getMessage()); 776 return false; 777 } 778 } 779 onSettingChanged(byte setting, boolean enabled)780 private void onSettingChanged(byte setting, boolean enabled) { 781 android.hardware.contexthub.IContextHub hub = getHub(); 782 if (hub == null) { 783 return; 784 } 785 786 try { 787 hub.onSettingChanged(setting, enabled); 788 } catch (RemoteException | ServiceSpecificException e) { 789 Log.e(TAG, "Exception while sending setting update: " + e.getMessage()); 790 } 791 } 792 793 /** 794 * Links the mHub death handler to this 795 */ linkWrapperToHubDeath()796 private void linkWrapperToHubDeath() { 797 android.hardware.contexthub.IContextHub hub = getHub(); 798 if (hub == null) { 799 return; 800 } 801 802 try { 803 hub.asBinder().linkToDeath(this, 0); 804 } catch (RemoteException exception) { 805 Log.e(TAG, "Context Hub AIDL service death receipt could not be linked"); 806 } 807 } 808 } 809 810 /** 811 * An abstract call that defines methods common to all HIDL IContextHubWrappers. 812 */ 813 private abstract static class ContextHubWrapperHidl extends IContextHubWrapper { 814 private android.hardware.contexthub.V1_0.IContexthub mHub; 815 816 protected ICallback mCallback = null; 817 818 protected final Map<Integer, ContextHubWrapperHidlCallback> mHidlCallbackMap = 819 new HashMap<>(); 820 821 protected class ContextHubWrapperHidlCallback extends IContexthubCallback.Stub { 822 private final int mContextHubId; 823 private final ICallback mCallback; 824 ContextHubWrapperHidlCallback(int contextHubId, ICallback callback)825 ContextHubWrapperHidlCallback(int contextHubId, ICallback callback) { 826 mContextHubId = contextHubId; 827 mCallback = callback; 828 } 829 830 @Override handleClientMsg(ContextHubMsg message)831 public void handleClientMsg(ContextHubMsg message) { 832 mCallback.handleNanoappMessage( 833 message.hostEndPoint, 834 ContextHubServiceUtil.createNanoAppMessage(message), 835 Collections.emptyList() /* nanoappPermissions */, 836 Collections.emptyList() /* messagePermissions */); 837 } 838 839 @Override handleTxnResult(int transactionId, int result)840 public void handleTxnResult(int transactionId, int result) { 841 mCallback.handleTransactionResult(transactionId, 842 result == TransactionResult.SUCCESS); 843 } 844 845 @Override handleHubEvent(int eventType)846 public void handleHubEvent(int eventType) { 847 mCallback.handleContextHubEvent( 848 ContextHubServiceUtil.toContextHubEvent(eventType)); 849 } 850 851 @Override handleAppAbort(long nanoAppId, int abortCode)852 public void handleAppAbort(long nanoAppId, int abortCode) { 853 mCallback.handleNanoappAbort(nanoAppId, abortCode); 854 } 855 856 @Override handleAppsInfo( ArrayList<android.hardware.contexthub.V1_0.HubAppInfo> nanoAppInfoList)857 public void handleAppsInfo( 858 ArrayList<android.hardware.contexthub.V1_0.HubAppInfo> nanoAppInfoList) { 859 handleAppsInfo_1_2(ContextHubServiceUtil.toHubAppInfo_1_2(nanoAppInfoList)); 860 } 861 862 @Override handleClientMsg_1_2(android.hardware.contexthub.V1_2.ContextHubMsg message, ArrayList<String> messagePermissions)863 public void handleClientMsg_1_2(android.hardware.contexthub.V1_2.ContextHubMsg message, 864 ArrayList<String> messagePermissions) { 865 mCallback.handleNanoappMessage( 866 message.msg_1_0.hostEndPoint, 867 ContextHubServiceUtil.createNanoAppMessage(message.msg_1_0), 868 message.permissions, messagePermissions); 869 } 870 871 @Override handleAppsInfo_1_2(ArrayList<HubAppInfo> nanoAppInfoList)872 public void handleAppsInfo_1_2(ArrayList<HubAppInfo> nanoAppInfoList) { 873 List<NanoAppState> nanoAppStateList = 874 ContextHubServiceUtil.createNanoAppStateList(nanoAppInfoList); 875 mCallback.handleNanoappInfo(nanoAppStateList); 876 } 877 } 878 ContextHubWrapperHidl(android.hardware.contexthub.V1_0.IContexthub hub)879 ContextHubWrapperHidl(android.hardware.contexthub.V1_0.IContexthub hub) { 880 mHub = hub; 881 } 882 883 @ContextHubTransaction.Result sendMessageToContextHub( short hostEndpointId, int contextHubId, NanoAppMessage message)884 public int sendMessageToContextHub( 885 short hostEndpointId, int contextHubId, NanoAppMessage message) 886 throws RemoteException { 887 ContextHubMsg messageToNanoApp = 888 ContextHubServiceUtil.createHidlContextHubMessage(hostEndpointId, message); 889 return ContextHubServiceUtil.toTransactionResult( 890 mHub.sendMessageToHub(contextHubId, messageToNanoApp)); 891 } 892 893 @ContextHubTransaction.Result loadNanoapp(int contextHubId, NanoAppBinary binary, int transactionId)894 public int loadNanoapp(int contextHubId, NanoAppBinary binary, 895 int transactionId) throws RemoteException { 896 android.hardware.contexthub.V1_0.NanoAppBinary hidlNanoAppBinary = 897 ContextHubServiceUtil.createHidlNanoAppBinary(binary); 898 return ContextHubServiceUtil.toTransactionResult(mHub.loadNanoApp( 899 contextHubId, hidlNanoAppBinary, transactionId)); 900 } 901 902 @ContextHubTransaction.Result unloadNanoapp(int contextHubId, long nanoappId, int transactionId)903 public int unloadNanoapp(int contextHubId, long nanoappId, int transactionId) 904 throws RemoteException { 905 return ContextHubServiceUtil.toTransactionResult(mHub.unloadNanoApp( 906 contextHubId, nanoappId, transactionId)); 907 } 908 909 @ContextHubTransaction.Result enableNanoapp(int contextHubId, long nanoappId, int transactionId)910 public int enableNanoapp(int contextHubId, long nanoappId, int transactionId) 911 throws RemoteException { 912 return ContextHubServiceUtil.toTransactionResult(mHub.enableNanoApp( 913 contextHubId, nanoappId, transactionId)); 914 } 915 916 @ContextHubTransaction.Result disableNanoapp(int contextHubId, long nanoappId, int transactionId)917 public int disableNanoapp(int contextHubId, long nanoappId, int transactionId) 918 throws RemoteException { 919 return ContextHubServiceUtil.toTransactionResult(mHub.disableNanoApp( 920 contextHubId, nanoappId, transactionId)); 921 } 922 923 @ContextHubTransaction.Result queryNanoapps(int contextHubId)924 public int queryNanoapps(int contextHubId) throws RemoteException { 925 return ContextHubServiceUtil.toTransactionResult( 926 mHub.queryApps(contextHubId)); 927 } 928 getPreloadedNanoappIds(int contextHubId)929 public long[] getPreloadedNanoappIds(int contextHubId) { 930 return new long[0]; 931 } 932 registerCallback(int contextHubId, ICallback callback)933 public void registerCallback(int contextHubId, ICallback callback) throws RemoteException { 934 mHidlCallbackMap.put(contextHubId, 935 new ContextHubWrapperHidlCallback(contextHubId, callback)); 936 mHub.registerCallback(contextHubId, mHidlCallbackMap.get(contextHubId)); 937 } 938 registerExistingCallback(int contextHubId)939 public void registerExistingCallback(int contextHubId) throws RemoteException { 940 ContextHubWrapperHidlCallback callback = mHidlCallbackMap.get(contextHubId); 941 if (callback == null) { 942 Log.e(TAG, "Could not find existing callback for context hub with ID = " 943 + contextHubId); 944 return; 945 } 946 947 mHub.registerCallback(contextHubId, callback); 948 } 949 setTestMode(boolean enable)950 public boolean setTestMode(boolean enable) { 951 return false; 952 } 953 supportsBtSettingNotifications()954 public boolean supportsBtSettingNotifications() { 955 return false; 956 } 957 onWifiMainSettingChanged(boolean enabled)958 public void onWifiMainSettingChanged(boolean enabled) {} onWifiScanningSettingChanged(boolean enabled)959 public void onWifiScanningSettingChanged(boolean enabled) {} onBtMainSettingChanged(boolean enabled)960 public void onBtMainSettingChanged(boolean enabled) {} onBtScanningSettingChanged(boolean enabled)961 public void onBtScanningSettingChanged(boolean enabled) {} 962 } 963 964 private static class ContextHubWrapperV1_0 extends ContextHubWrapperHidl { 965 private android.hardware.contexthub.V1_0.IContexthub mHub; 966 ContextHubWrapperV1_0(android.hardware.contexthub.V1_0.IContexthub hub)967 ContextHubWrapperV1_0(android.hardware.contexthub.V1_0.IContexthub hub) { 968 super(hub); 969 mHub = hub; 970 } 971 getHubs()972 public Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException { 973 ArrayList<ContextHubInfo> hubInfoList = new ArrayList<>(); 974 for (ContextHub hub : mHub.getHubs()) { 975 hubInfoList.add(new ContextHubInfo(hub)); 976 } 977 return new Pair(hubInfoList, new ArrayList<String>()); 978 } 979 supportsLocationSettingNotifications()980 public boolean supportsLocationSettingNotifications() { 981 return false; 982 } 983 supportsWifiSettingNotifications()984 public boolean supportsWifiSettingNotifications() { 985 return false; 986 } 987 supportsAirplaneModeSettingNotifications()988 public boolean supportsAirplaneModeSettingNotifications() { 989 return false; 990 } 991 supportsMicrophoneSettingNotifications()992 public boolean supportsMicrophoneSettingNotifications() { 993 return false; 994 } 995 onLocationSettingChanged(boolean enabled)996 public void onLocationSettingChanged(boolean enabled) { 997 } 998 onWifiSettingChanged(boolean enabled)999 public void onWifiSettingChanged(boolean enabled) { 1000 } 1001 onAirplaneModeSettingChanged(boolean enabled)1002 public void onAirplaneModeSettingChanged(boolean enabled) { 1003 } 1004 onMicrophoneSettingChanged(boolean enabled)1005 public void onMicrophoneSettingChanged(boolean enabled) { 1006 } 1007 } 1008 1009 private static class ContextHubWrapperV1_1 extends ContextHubWrapperHidl { 1010 private android.hardware.contexthub.V1_1.IContexthub mHub; 1011 ContextHubWrapperV1_1(android.hardware.contexthub.V1_1.IContexthub hub)1012 ContextHubWrapperV1_1(android.hardware.contexthub.V1_1.IContexthub hub) { 1013 super(hub); 1014 mHub = hub; 1015 } 1016 getHubs()1017 public Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException { 1018 ArrayList<ContextHubInfo> hubInfoList = new ArrayList<>(); 1019 for (ContextHub hub : mHub.getHubs()) { 1020 hubInfoList.add(new ContextHubInfo(hub)); 1021 } 1022 return new Pair(hubInfoList, new ArrayList<String>()); 1023 } 1024 supportsLocationSettingNotifications()1025 public boolean supportsLocationSettingNotifications() { 1026 return true; 1027 } 1028 supportsWifiSettingNotifications()1029 public boolean supportsWifiSettingNotifications() { 1030 return false; 1031 } 1032 supportsAirplaneModeSettingNotifications()1033 public boolean supportsAirplaneModeSettingNotifications() { 1034 return false; 1035 } 1036 supportsMicrophoneSettingNotifications()1037 public boolean supportsMicrophoneSettingNotifications() { 1038 return false; 1039 } 1040 onLocationSettingChanged(boolean enabled)1041 public void onLocationSettingChanged(boolean enabled) { 1042 try { 1043 mHub.onSettingChanged(Setting.LOCATION, 1044 enabled ? SettingValue.ENABLED : SettingValue.DISABLED); 1045 } catch (RemoteException e) { 1046 Log.e(TAG, "Failed to send setting change to Contexthub", e); 1047 } 1048 } 1049 onWifiSettingChanged(boolean enabled)1050 public void onWifiSettingChanged(boolean enabled) { 1051 } 1052 onAirplaneModeSettingChanged(boolean enabled)1053 public void onAirplaneModeSettingChanged(boolean enabled) { 1054 } 1055 onMicrophoneSettingChanged(boolean enabled)1056 public void onMicrophoneSettingChanged(boolean enabled) { 1057 } 1058 } 1059 1060 private static class ContextHubWrapperV1_2 extends ContextHubWrapperHidl 1061 implements android.hardware.contexthub.V1_2.IContexthub.getHubs_1_2Callback { 1062 private final android.hardware.contexthub.V1_2.IContexthub mHub; 1063 1064 private Pair<List<ContextHubInfo>, List<String>> mHubInfo = 1065 new Pair<>(Collections.emptyList(), Collections.emptyList()); 1066 ContextHubWrapperV1_2(android.hardware.contexthub.V1_2.IContexthub hub)1067 ContextHubWrapperV1_2(android.hardware.contexthub.V1_2.IContexthub hub) { 1068 super(hub); 1069 mHub = hub; 1070 } 1071 1072 @Override onValues(ArrayList<ContextHub> hubs, ArrayList<String> supportedPermissions)1073 public void onValues(ArrayList<ContextHub> hubs, ArrayList<String> supportedPermissions) { 1074 ArrayList<ContextHubInfo> hubInfoList = new ArrayList<>(); 1075 for (ContextHub hub : hubs) { 1076 hubInfoList.add(new ContextHubInfo(hub)); 1077 } 1078 mHubInfo = new Pair(hubInfoList, supportedPermissions); 1079 } 1080 getHubs()1081 public Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException { 1082 mHub.getHubs_1_2(this); 1083 return mHubInfo; 1084 } 1085 supportsLocationSettingNotifications()1086 public boolean supportsLocationSettingNotifications() { 1087 return true; 1088 } 1089 supportsWifiSettingNotifications()1090 public boolean supportsWifiSettingNotifications() { 1091 return true; 1092 } 1093 supportsAirplaneModeSettingNotifications()1094 public boolean supportsAirplaneModeSettingNotifications() { 1095 return true; 1096 } 1097 supportsMicrophoneSettingNotifications()1098 public boolean supportsMicrophoneSettingNotifications() { 1099 return true; 1100 } 1101 onLocationSettingChanged(boolean enabled)1102 public void onLocationSettingChanged(boolean enabled) { 1103 sendSettingChanged(Setting.LOCATION, 1104 enabled ? SettingValue.ENABLED : SettingValue.DISABLED); 1105 } 1106 onWifiSettingChanged(boolean enabled)1107 public void onWifiSettingChanged(boolean enabled) { 1108 sendSettingChanged(android.hardware.contexthub.V1_2.Setting.WIFI_AVAILABLE, 1109 enabled ? SettingValue.ENABLED : SettingValue.DISABLED); 1110 } 1111 onAirplaneModeSettingChanged(boolean enabled)1112 public void onAirplaneModeSettingChanged(boolean enabled) { 1113 sendSettingChanged(android.hardware.contexthub.V1_2.Setting.AIRPLANE_MODE, 1114 enabled ? SettingValue.ENABLED : SettingValue.DISABLED); 1115 } 1116 onMicrophoneSettingChanged(boolean enabled)1117 public void onMicrophoneSettingChanged(boolean enabled) { 1118 sendSettingChanged(android.hardware.contexthub.V1_2.Setting.MICROPHONE, 1119 enabled ? SettingValue.ENABLED : SettingValue.DISABLED); 1120 } 1121 registerCallback(int contextHubId, ICallback callback)1122 public void registerCallback(int contextHubId, ICallback callback) throws RemoteException { 1123 mHidlCallbackMap.put(contextHubId, 1124 new ContextHubWrapperHidlCallback(contextHubId, callback)); 1125 mHub.registerCallback_1_2(contextHubId, mHidlCallbackMap.get(contextHubId)); 1126 } 1127 sendSettingChanged(byte setting, byte newValue)1128 private void sendSettingChanged(byte setting, byte newValue) { 1129 try { 1130 mHub.onSettingChanged_1_2(setting, newValue); 1131 } catch (RemoteException e) { 1132 Log.e(TAG, "Failed to send setting change to Contexthub", e); 1133 } 1134 } 1135 } 1136 } 1137