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.V1_0.ContextHub; 22 import android.hardware.contexthub.V1_0.ContextHubMsg; 23 import android.hardware.contexthub.V1_0.TransactionResult; 24 import android.hardware.contexthub.V1_1.Setting; 25 import android.hardware.contexthub.V1_1.SettingValue; 26 import android.hardware.contexthub.V1_2.HubAppInfo; 27 import android.hardware.contexthub.V1_2.IContexthubCallback; 28 import android.hardware.location.ContextHubInfo; 29 import android.hardware.location.ContextHubTransaction; 30 import android.hardware.location.NanoAppBinary; 31 import android.hardware.location.NanoAppMessage; 32 import android.hardware.location.NanoAppState; 33 import android.os.Handler; 34 import android.os.HandlerThread; 35 import android.os.Process; 36 import android.os.RemoteException; 37 import android.os.ServiceManager; 38 import android.os.ServiceSpecificException; 39 import android.util.Log; 40 import android.util.Pair; 41 42 import java.util.ArrayList; 43 import java.util.Arrays; 44 import java.util.Collections; 45 import java.util.HashMap; 46 import java.util.HashSet; 47 import java.util.List; 48 import java.util.Map; 49 import java.util.NoSuchElementException; 50 import java.util.Set; 51 52 /** 53 * @hide 54 */ 55 public abstract class IContextHubWrapper { 56 private static final String TAG = "IContextHubWrapper"; 57 58 /** 59 * The callback interface to use in registerCallback. 60 */ 61 public interface ICallback { 62 /** 63 * @param transactionId The ID of the transaction that completed. 64 * @param success true if the transaction succeeded. 65 */ handleTransactionResult(int transactionId, boolean success)66 void handleTransactionResult(int transactionId, boolean success); 67 68 /** 69 * @param eventType The Context Hub event type defined by ContextHubService 70 * .CONTEXT_HUB_EVENT_*. 71 */ handleContextHubEvent(int eventType)72 void handleContextHubEvent(int eventType); 73 74 /** 75 * @param nanoappId The ID of the nanoapp that aborted. 76 * @param abortCode The nanoapp-defined abort code. 77 */ handleNanoappAbort(long nanoappId, int abortCode)78 void handleNanoappAbort(long nanoappId, int abortCode); 79 80 /** 81 * @param nanoappStateList The list of loaded nanoapps on the Context Hub. 82 */ handleNanoappInfo(List<NanoAppState> nanoappStateList)83 void handleNanoappInfo(List<NanoAppState> nanoappStateList); 84 85 /** 86 * Handles a message from a nanoapp to a ContextHubClient. 87 * 88 * @param hostEndpointId The host endpoint ID of the recipient. 89 * @param message The message from the nanoapp. 90 * @param nanoappPermissions The list of permissions held by the nanoapp. 91 * @param messagePermissions The list of permissions required to receive the message. 92 */ handleNanoappMessage(short hostEndpointId, NanoAppMessage message, List<String> nanoappPermissions, List<String> messagePermissions)93 void handleNanoappMessage(short hostEndpointId, NanoAppMessage message, 94 List<String> nanoappPermissions, List<String> messagePermissions); 95 } 96 97 /** 98 * Attempts to connect to the Contexthub HAL 1.0 service, if it exists. 99 * 100 * @return A valid IContextHubWrapper if the connection was successful, null otherwise. 101 */ 102 @Nullable maybeConnectTo1_0()103 public static IContextHubWrapper maybeConnectTo1_0() { 104 android.hardware.contexthub.V1_0.IContexthub proxy = null; 105 try { 106 proxy = android.hardware.contexthub.V1_0.IContexthub.getService(true /* retry */); 107 } catch (RemoteException e) { 108 Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e); 109 } catch (NoSuchElementException e) { 110 Log.i(TAG, "Context Hub HAL service not found"); 111 } 112 113 return (proxy == null) ? null : new ContextHubWrapperV1_0(proxy); 114 } 115 116 /** 117 * Attempts to connect to the Contexthub HAL 1.1 service, if it exists. 118 * 119 * @return A valid IContextHubWrapper if the connection was successful, null otherwise. 120 */ 121 @Nullable maybeConnectTo1_1()122 public static IContextHubWrapper maybeConnectTo1_1() { 123 android.hardware.contexthub.V1_1.IContexthub proxy = null; 124 try { 125 proxy = android.hardware.contexthub.V1_1.IContexthub.getService(true /* retry */); 126 } catch (RemoteException e) { 127 Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e); 128 } catch (NoSuchElementException e) { 129 Log.i(TAG, "Context Hub HAL service not found"); 130 } 131 132 return (proxy == null) ? null : new ContextHubWrapperV1_1(proxy); 133 } 134 135 /** 136 * Attempts to connect to the Contexthub HAL 1.2 service, if it exists. 137 * 138 * @return A valid IContextHubWrapper if the connection was successful, null otherwise. 139 */ 140 @Nullable maybeConnectTo1_2()141 public static IContextHubWrapper maybeConnectTo1_2() { 142 android.hardware.contexthub.V1_2.IContexthub proxy = null; 143 try { 144 proxy = android.hardware.contexthub.V1_2.IContexthub.getService(true /* retry */); 145 } catch (RemoteException e) { 146 Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e); 147 } catch (NoSuchElementException e) { 148 Log.i(TAG, "Context Hub HAL service not found"); 149 } 150 151 return (proxy == null) ? null : new ContextHubWrapperV1_2(proxy); 152 } 153 154 /** 155 * Attempts to connect to the Contexthub HAL AIDL service, if it exists. 156 * 157 * @return A valid IContextHubWrapper if the connection was successful, null otherwise. 158 */ 159 @Nullable maybeConnectToAidl()160 public static IContextHubWrapper maybeConnectToAidl() { 161 android.hardware.contexthub.IContextHub proxy = null; 162 final String aidlServiceName = 163 android.hardware.contexthub.IContextHub.class.getCanonicalName() + "/default"; 164 if (ServiceManager.isDeclared(aidlServiceName)) { 165 proxy = android.hardware.contexthub.IContextHub.Stub.asInterface( 166 ServiceManager.waitForService(aidlServiceName)); 167 if (proxy == null) { 168 Log.e(TAG, "Context Hub AIDL service was declared but was not found"); 169 } 170 } else { 171 Log.d(TAG, "Context Hub AIDL service is not declared"); 172 } 173 174 return (proxy == null) ? null : new ContextHubWrapperAidl(proxy); 175 } 176 177 /** 178 * Calls the appropriate getHubs function depending on the HAL version. 179 */ getHubs()180 public abstract Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException; 181 182 /** 183 * @return True if this version of the Contexthub HAL supports Location setting notifications. 184 */ supportsLocationSettingNotifications()185 public abstract boolean supportsLocationSettingNotifications(); 186 187 /** 188 * Notifies the Contexthub implementation of a user Location setting change. 189 * 190 * @param enabled True if the Location setting has been enabled. 191 */ onLocationSettingChanged(boolean enabled)192 public abstract void onLocationSettingChanged(boolean enabled); 193 194 /** 195 * @return True if this version of the Contexthub HAL supports WiFi availability setting 196 * notifications. 197 */ supportsWifiSettingNotifications()198 public abstract boolean supportsWifiSettingNotifications(); 199 200 /** 201 * Notifies the Contexthub implementation of a user WiFi availability setting change. 202 * 203 * @param enabled true if the WiFi availability setting has been enabled. 204 */ onWifiSettingChanged(boolean enabled)205 public abstract void onWifiSettingChanged(boolean enabled); 206 207 /** 208 * Notifies the Contexthub implementation of a user WiFi main setting change. 209 * 210 * @param enabled true if the WiFi main setting has been enabled. 211 */ onWifiMainSettingChanged(boolean enabled)212 public abstract void onWifiMainSettingChanged(boolean enabled); 213 214 /** 215 * Notifies the Contexthub implementation of a user WiFi scanning setting change. 216 * 217 * @param enabled true if the WiFi scanning setting has been enabled. 218 */ onWifiScanningSettingChanged(boolean enabled)219 public abstract void onWifiScanningSettingChanged(boolean enabled); 220 221 /** 222 * @return True if this version of the Contexthub HAL supports airplane mode setting 223 * notifications. 224 */ supportsAirplaneModeSettingNotifications()225 public abstract boolean supportsAirplaneModeSettingNotifications(); 226 227 /** 228 * Notifies the Contexthub implementation of an airplane mode setting change. 229 * 230 * @param enabled true if the airplane mode setting has been enabled. 231 */ onAirplaneModeSettingChanged(boolean enabled)232 public abstract void onAirplaneModeSettingChanged(boolean enabled); 233 234 /** 235 * @return True if this version of the Contexthub HAL supports microphone setting 236 * notifications. 237 */ supportsMicrophoneSettingNotifications()238 public abstract boolean supportsMicrophoneSettingNotifications(); 239 240 /** 241 * Notifies the Contexthub implementation of a microphone setting change. 242 */ onMicrophoneSettingChanged(boolean enabled)243 public abstract void onMicrophoneSettingChanged(boolean enabled); 244 245 /** 246 * @return True if this version of the Contexthub HAL supports BT availability setting 247 * notifications. 248 */ supportsBtSettingNotifications()249 public abstract boolean supportsBtSettingNotifications(); 250 251 /** 252 * Notifies the Contexthub implementation of a BT main setting change. 253 */ onBtMainSettingChanged(boolean enabled)254 public abstract void onBtMainSettingChanged(boolean enabled); 255 256 /** 257 * Notifies the Contexthub implementation of a BT scanning setting change. 258 */ onBtScanningSettingChanged(boolean enabled)259 public abstract void onBtScanningSettingChanged(boolean enabled); 260 261 /** 262 * Invoked whenever a host client connects with the framework. 263 * 264 * @param info The host endpoint info. 265 */ onHostEndpointConnected(HostEndpointInfo info)266 public void onHostEndpointConnected(HostEndpointInfo info) {} 267 268 /** 269 * Invoked whenever a host client disconnects from the framework. 270 * 271 * @param hostEndpointId The ID of the host endpoint that disconnected. 272 */ onHostEndpointDisconnected(short hostEndpointId)273 public void onHostEndpointDisconnected(short hostEndpointId) {} 274 275 /** 276 * Sends a message to the Context Hub. 277 * 278 * @param hostEndpointId The host endpoint ID of the sender. 279 * @param contextHubId The ID of the Context Hub to send the message to. 280 * @param message The message to send. 281 * @return the result of the message sending. 282 */ 283 @ContextHubTransaction.Result sendMessageToContextHub( short hostEndpointId, int contextHubId, NanoAppMessage message)284 public abstract int sendMessageToContextHub( 285 short hostEndpointId, int contextHubId, NanoAppMessage message) 286 throws RemoteException; 287 288 /** 289 * Loads a nanoapp on the Context Hub. 290 * 291 * @param contextHubId The ID of the Context Hub to load the nanoapp to. 292 * @param binary The nanoapp binary to load. 293 * @param transactionId The transaction ID of this load. 294 * @return the result of this load transaction. 295 */ 296 @ContextHubTransaction.Result loadNanoapp(int contextHubId, NanoAppBinary binary, int transactionId)297 public abstract int loadNanoapp(int contextHubId, NanoAppBinary binary, 298 int transactionId) throws RemoteException; 299 300 /** 301 * Unloads a nanoapp on the Context Hub. Semantics are similar to loadNanoapp(). 302 */ 303 @ContextHubTransaction.Result unloadNanoapp(int contextHubId, long nanoappId, int transactionId)304 public abstract int unloadNanoapp(int contextHubId, long nanoappId, 305 int transactionId) throws RemoteException; 306 307 /** 308 * Enables a nanoapp on the Context Hub. Semantics are similar to loadNanoapp(). 309 */ 310 @ContextHubTransaction.Result enableNanoapp(int contextHubId, long nanoappId, int transactionId)311 public abstract int enableNanoapp(int contextHubId, long nanoappId, 312 int transactionId) throws RemoteException; 313 314 /** 315 * Disables a nanoapp on the Context Hub. Semantics are similar to loadNanoapp(). 316 */ 317 @ContextHubTransaction.Result disableNanoapp(int contextHubId, long nanoappId, int transactionId)318 public abstract int disableNanoapp(int contextHubId, long nanoappId, 319 int transactionId) throws RemoteException; 320 321 /** 322 * Queries a list of nanoapp from the Context hub. 323 * 324 * @param contextHubId The ID of the Context Hub to query. 325 * @return the result of this query transaction. 326 */ 327 @ContextHubTransaction.Result queryNanoapps(int contextHubId)328 public abstract int queryNanoapps(int contextHubId) throws RemoteException; 329 330 /** 331 * Registers a callback with the Context Hub. 332 * 333 * @param contextHubId The ID of the Context Hub to register the callback with. 334 * @param callback The callback to register. 335 */ registerCallback(int contextHubId, @NonNull ICallback callback)336 public abstract void registerCallback(int contextHubId, @NonNull ICallback callback) 337 throws RemoteException; 338 339 private static class ContextHubWrapperAidl extends IContextHubWrapper { 340 private android.hardware.contexthub.IContextHub mHub; 341 342 private final Map<Integer, ContextHubAidlCallback> mAidlCallbackMap = 343 new HashMap<>(); 344 345 // Use this thread in case where the execution requires to be on a service thread. 346 // For instance, AppOpsManager.noteOp requires the UPDATE_APP_OPS_STATS permission. 347 private HandlerThread mHandlerThread = 348 new HandlerThread("Context Hub AIDL callback", Process.THREAD_PRIORITY_BACKGROUND); 349 private Handler mHandler; 350 351 private class ContextHubAidlCallback extends 352 android.hardware.contexthub.IContextHubCallback.Stub { 353 private final int mContextHubId; 354 private final ICallback mCallback; 355 ContextHubAidlCallback(int contextHubId, ICallback callback)356 ContextHubAidlCallback(int contextHubId, ICallback callback) { 357 mContextHubId = contextHubId; 358 mCallback = callback; 359 } 360 handleNanoappInfo(android.hardware.contexthub.NanoappInfo[] appInfo)361 public void handleNanoappInfo(android.hardware.contexthub.NanoappInfo[] appInfo) { 362 List<NanoAppState> nanoAppStateList = 363 ContextHubServiceUtil.createNanoAppStateList(appInfo); 364 mHandler.post(() -> { 365 mCallback.handleNanoappInfo(nanoAppStateList); 366 }); 367 } 368 handleContextHubMessage(android.hardware.contexthub.ContextHubMessage msg, String[] msgContentPerms)369 public void handleContextHubMessage(android.hardware.contexthub.ContextHubMessage msg, 370 String[] msgContentPerms) { 371 mHandler.post(() -> { 372 mCallback.handleNanoappMessage( 373 (short) msg.hostEndPoint, 374 ContextHubServiceUtil.createNanoAppMessage(msg), 375 new ArrayList<>(Arrays.asList(msg.permissions)), 376 new ArrayList<>(Arrays.asList(msgContentPerms))); 377 }); 378 } 379 handleContextHubAsyncEvent(int evt)380 public void handleContextHubAsyncEvent(int evt) { 381 mHandler.post(() -> { 382 mCallback.handleContextHubEvent( 383 ContextHubServiceUtil.toContextHubEventFromAidl(evt)); 384 }); 385 } 386 handleTransactionResult(int transactionId, boolean success)387 public void handleTransactionResult(int transactionId, boolean success) { 388 mHandler.post(() -> { 389 mCallback.handleTransactionResult(transactionId, success); 390 }); 391 } 392 @Override getInterfaceHash()393 public String getInterfaceHash() { 394 return android.hardware.contexthub.IContextHubCallback.HASH; 395 } 396 397 @Override getInterfaceVersion()398 public int getInterfaceVersion() { 399 return android.hardware.contexthub.IContextHubCallback.VERSION; 400 } 401 } 402 ContextHubWrapperAidl(android.hardware.contexthub.IContextHub hub)403 ContextHubWrapperAidl(android.hardware.contexthub.IContextHub hub) { 404 mHub = hub; 405 mHandlerThread.start(); 406 mHandler = new Handler(mHandlerThread.getLooper()); 407 } 408 getHubs()409 public Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException { 410 Set<String> supportedPermissions = new HashSet<>(); 411 ArrayList<ContextHubInfo> hubInfoList = new ArrayList<>(); 412 for (android.hardware.contexthub.ContextHubInfo hub : mHub.getContextHubs()) { 413 hubInfoList.add(new ContextHubInfo(hub)); 414 for (String permission : hub.supportedPermissions) { 415 supportedPermissions.add(permission); 416 } 417 } 418 return new Pair(hubInfoList, new ArrayList<String>(supportedPermissions)); 419 } 420 supportsLocationSettingNotifications()421 public boolean supportsLocationSettingNotifications() { 422 return true; 423 } 424 supportsWifiSettingNotifications()425 public boolean supportsWifiSettingNotifications() { 426 return true; 427 } 428 supportsAirplaneModeSettingNotifications()429 public boolean supportsAirplaneModeSettingNotifications() { 430 return true; 431 } 432 supportsMicrophoneSettingNotifications()433 public boolean supportsMicrophoneSettingNotifications() { 434 return true; 435 } 436 supportsBtSettingNotifications()437 public boolean supportsBtSettingNotifications() { 438 return true; 439 } 440 onLocationSettingChanged(boolean enabled)441 public void onLocationSettingChanged(boolean enabled) { 442 onSettingChanged(android.hardware.contexthub.Setting.LOCATION, enabled); 443 } 444 onWifiSettingChanged(boolean enabled)445 public void onWifiSettingChanged(boolean enabled) { 446 } 447 onAirplaneModeSettingChanged(boolean enabled)448 public void onAirplaneModeSettingChanged(boolean enabled) { 449 onSettingChanged(android.hardware.contexthub.Setting.AIRPLANE_MODE, enabled); 450 } 451 onMicrophoneSettingChanged(boolean enabled)452 public void onMicrophoneSettingChanged(boolean enabled) { 453 onSettingChanged(android.hardware.contexthub.Setting.MICROPHONE, enabled); 454 } 455 onWifiMainSettingChanged(boolean enabled)456 public void onWifiMainSettingChanged(boolean enabled) { 457 onSettingChanged(android.hardware.contexthub.Setting.WIFI_MAIN, enabled); 458 } 459 onWifiScanningSettingChanged(boolean enabled)460 public void onWifiScanningSettingChanged(boolean enabled) { 461 onSettingChanged(android.hardware.contexthub.Setting.WIFI_SCANNING, enabled); 462 } 463 onBtMainSettingChanged(boolean enabled)464 public void onBtMainSettingChanged(boolean enabled) { 465 onSettingChanged(android.hardware.contexthub.Setting.BT_MAIN, enabled); 466 } 467 onBtScanningSettingChanged(boolean enabled)468 public void onBtScanningSettingChanged(boolean enabled) { 469 onSettingChanged(android.hardware.contexthub.Setting.BT_SCANNING, enabled); 470 } 471 472 @Override onHostEndpointConnected(HostEndpointInfo info)473 public void onHostEndpointConnected(HostEndpointInfo info) { 474 try { 475 mHub.onHostEndpointConnected(info); 476 } catch (RemoteException | ServiceSpecificException e) { 477 Log.e(TAG, "Exception in onHostEndpointConnected" + e.getMessage()); 478 } 479 } 480 481 @Override onHostEndpointDisconnected(short hostEndpointId)482 public void onHostEndpointDisconnected(short hostEndpointId) { 483 try { 484 mHub.onHostEndpointDisconnected((char) hostEndpointId); 485 } catch (RemoteException | ServiceSpecificException e) { 486 Log.e(TAG, "Exception in onHostEndpointDisconnected" + e.getMessage()); 487 } 488 } 489 490 @ContextHubTransaction.Result sendMessageToContextHub( short hostEndpointId, int contextHubId, NanoAppMessage message)491 public int sendMessageToContextHub( 492 short hostEndpointId, int contextHubId, NanoAppMessage message) 493 throws RemoteException { 494 try { 495 mHub.sendMessageToHub(contextHubId, 496 ContextHubServiceUtil.createAidlContextHubMessage(hostEndpointId, message)); 497 return ContextHubTransaction.RESULT_SUCCESS; 498 } catch (RemoteException | ServiceSpecificException e) { 499 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 500 } catch (IllegalArgumentException e) { 501 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 502 } 503 } 504 505 @ContextHubTransaction.Result loadNanoapp(int contextHubId, NanoAppBinary binary, int transactionId)506 public int loadNanoapp(int contextHubId, NanoAppBinary binary, 507 int transactionId) throws RemoteException { 508 android.hardware.contexthub.NanoappBinary aidlNanoAppBinary = 509 ContextHubServiceUtil.createAidlNanoAppBinary(binary); 510 try { 511 mHub.loadNanoapp(contextHubId, aidlNanoAppBinary, transactionId); 512 return ContextHubTransaction.RESULT_SUCCESS; 513 } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { 514 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 515 } catch (IllegalArgumentException e) { 516 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 517 } 518 } 519 520 @ContextHubTransaction.Result unloadNanoapp(int contextHubId, long nanoappId, int transactionId)521 public int unloadNanoapp(int contextHubId, long nanoappId, int transactionId) 522 throws RemoteException { 523 try { 524 mHub.unloadNanoapp(contextHubId, nanoappId, transactionId); 525 return ContextHubTransaction.RESULT_SUCCESS; 526 } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { 527 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 528 } catch (IllegalArgumentException e) { 529 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 530 } 531 } 532 533 @ContextHubTransaction.Result enableNanoapp(int contextHubId, long nanoappId, int transactionId)534 public int enableNanoapp(int contextHubId, long nanoappId, int transactionId) 535 throws RemoteException { 536 try { 537 mHub.enableNanoapp(contextHubId, nanoappId, transactionId); 538 return ContextHubTransaction.RESULT_SUCCESS; 539 } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { 540 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 541 } catch (IllegalArgumentException e) { 542 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 543 } 544 } 545 546 @ContextHubTransaction.Result disableNanoapp(int contextHubId, long nanoappId, int transactionId)547 public int disableNanoapp(int contextHubId, long nanoappId, int transactionId) 548 throws RemoteException { 549 try { 550 mHub.disableNanoapp(contextHubId, nanoappId, transactionId); 551 return ContextHubTransaction.RESULT_SUCCESS; 552 } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { 553 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 554 } catch (IllegalArgumentException e) { 555 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 556 } 557 } 558 559 @ContextHubTransaction.Result queryNanoapps(int contextHubId)560 public int queryNanoapps(int contextHubId) throws RemoteException { 561 try { 562 mHub.queryNanoapps(contextHubId); 563 return ContextHubTransaction.RESULT_SUCCESS; 564 } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { 565 return ContextHubTransaction.RESULT_FAILED_UNKNOWN; 566 } catch (IllegalArgumentException e) { 567 return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; 568 } 569 } 570 registerCallback(int contextHubId, ICallback callback)571 public void registerCallback(int contextHubId, ICallback callback) throws RemoteException { 572 mAidlCallbackMap.put(contextHubId, new ContextHubAidlCallback(contextHubId, callback)); 573 try { 574 mHub.registerCallback(contextHubId, mAidlCallbackMap.get(contextHubId)); 575 } catch (RemoteException | ServiceSpecificException | IllegalArgumentException e) { 576 Log.e(TAG, "Exception while registering callback: " + e.getMessage()); 577 } 578 } 579 onSettingChanged(byte setting, boolean enabled)580 private void onSettingChanged(byte setting, boolean enabled) { 581 try { 582 mHub.onSettingChanged(setting, enabled); 583 } catch (RemoteException | ServiceSpecificException e) { 584 Log.e(TAG, "Exception while sending setting update: " + e.getMessage()); 585 } 586 } 587 } 588 589 /** 590 * An abstract call that defines methods common to all HIDL IContextHubWrappers. 591 */ 592 private abstract static class ContextHubWrapperHidl extends IContextHubWrapper { 593 private android.hardware.contexthub.V1_0.IContexthub mHub; 594 595 protected ICallback mCallback = null; 596 597 protected final Map<Integer, ContextHubWrapperHidlCallback> mHidlCallbackMap = 598 new HashMap<>(); 599 600 protected class ContextHubWrapperHidlCallback extends IContexthubCallback.Stub { 601 private final int mContextHubId; 602 private final ICallback mCallback; 603 ContextHubWrapperHidlCallback(int contextHubId, ICallback callback)604 ContextHubWrapperHidlCallback(int contextHubId, ICallback callback) { 605 mContextHubId = contextHubId; 606 mCallback = callback; 607 } 608 609 @Override handleClientMsg(ContextHubMsg message)610 public void handleClientMsg(ContextHubMsg message) { 611 mCallback.handleNanoappMessage( 612 message.hostEndPoint, 613 ContextHubServiceUtil.createNanoAppMessage(message), 614 Collections.emptyList() /* nanoappPermissions */, 615 Collections.emptyList() /* messagePermissions */); 616 } 617 618 @Override handleTxnResult(int transactionId, int result)619 public void handleTxnResult(int transactionId, int result) { 620 mCallback.handleTransactionResult(transactionId, 621 result == TransactionResult.SUCCESS); 622 } 623 624 @Override handleHubEvent(int eventType)625 public void handleHubEvent(int eventType) { 626 mCallback.handleContextHubEvent( 627 ContextHubServiceUtil.toContextHubEvent(eventType)); 628 } 629 630 @Override handleAppAbort(long nanoAppId, int abortCode)631 public void handleAppAbort(long nanoAppId, int abortCode) { 632 mCallback.handleNanoappAbort(nanoAppId, abortCode); 633 } 634 635 @Override handleAppsInfo( ArrayList<android.hardware.contexthub.V1_0.HubAppInfo> nanoAppInfoList)636 public void handleAppsInfo( 637 ArrayList<android.hardware.contexthub.V1_0.HubAppInfo> nanoAppInfoList) { 638 handleAppsInfo_1_2(ContextHubServiceUtil.toHubAppInfo_1_2(nanoAppInfoList)); 639 } 640 641 @Override handleClientMsg_1_2(android.hardware.contexthub.V1_2.ContextHubMsg message, ArrayList<String> messagePermissions)642 public void handleClientMsg_1_2(android.hardware.contexthub.V1_2.ContextHubMsg message, 643 ArrayList<String> messagePermissions) { 644 mCallback.handleNanoappMessage( 645 message.msg_1_0.hostEndPoint, 646 ContextHubServiceUtil.createNanoAppMessage(message.msg_1_0), 647 message.permissions, messagePermissions); 648 } 649 650 @Override handleAppsInfo_1_2(ArrayList<HubAppInfo> nanoAppInfoList)651 public void handleAppsInfo_1_2(ArrayList<HubAppInfo> nanoAppInfoList) { 652 List<NanoAppState> nanoAppStateList = 653 ContextHubServiceUtil.createNanoAppStateList(nanoAppInfoList); 654 mCallback.handleNanoappInfo(nanoAppStateList); 655 } 656 } 657 ContextHubWrapperHidl(android.hardware.contexthub.V1_0.IContexthub hub)658 ContextHubWrapperHidl(android.hardware.contexthub.V1_0.IContexthub hub) { 659 mHub = hub; 660 } 661 662 @ContextHubTransaction.Result sendMessageToContextHub( short hostEndpointId, int contextHubId, NanoAppMessage message)663 public int sendMessageToContextHub( 664 short hostEndpointId, int contextHubId, NanoAppMessage message) 665 throws RemoteException { 666 ContextHubMsg messageToNanoApp = 667 ContextHubServiceUtil.createHidlContextHubMessage(hostEndpointId, message); 668 return ContextHubServiceUtil.toTransactionResult( 669 mHub.sendMessageToHub(contextHubId, messageToNanoApp)); 670 } 671 672 @ContextHubTransaction.Result loadNanoapp(int contextHubId, NanoAppBinary binary, int transactionId)673 public int loadNanoapp(int contextHubId, NanoAppBinary binary, 674 int transactionId) throws RemoteException { 675 android.hardware.contexthub.V1_0.NanoAppBinary hidlNanoAppBinary = 676 ContextHubServiceUtil.createHidlNanoAppBinary(binary); 677 return ContextHubServiceUtil.toTransactionResult(mHub.loadNanoApp( 678 contextHubId, hidlNanoAppBinary, transactionId)); 679 } 680 681 @ContextHubTransaction.Result unloadNanoapp(int contextHubId, long nanoappId, int transactionId)682 public int unloadNanoapp(int contextHubId, long nanoappId, int transactionId) 683 throws RemoteException { 684 return ContextHubServiceUtil.toTransactionResult(mHub.unloadNanoApp( 685 contextHubId, nanoappId, transactionId)); 686 } 687 688 @ContextHubTransaction.Result enableNanoapp(int contextHubId, long nanoappId, int transactionId)689 public int enableNanoapp(int contextHubId, long nanoappId, int transactionId) 690 throws RemoteException { 691 return ContextHubServiceUtil.toTransactionResult(mHub.enableNanoApp( 692 contextHubId, nanoappId, transactionId)); 693 } 694 695 @ContextHubTransaction.Result disableNanoapp(int contextHubId, long nanoappId, int transactionId)696 public int disableNanoapp(int contextHubId, long nanoappId, int transactionId) 697 throws RemoteException { 698 return ContextHubServiceUtil.toTransactionResult(mHub.disableNanoApp( 699 contextHubId, nanoappId, transactionId)); 700 } 701 702 @ContextHubTransaction.Result queryNanoapps(int contextHubId)703 public int queryNanoapps(int contextHubId) throws RemoteException { 704 return ContextHubServiceUtil.toTransactionResult( 705 mHub.queryApps(contextHubId)); 706 } 707 registerCallback(int contextHubId, ICallback callback)708 public void registerCallback(int contextHubId, ICallback callback) throws RemoteException { 709 mHidlCallbackMap.put(contextHubId, 710 new ContextHubWrapperHidlCallback(contextHubId, callback)); 711 mHub.registerCallback(contextHubId, mHidlCallbackMap.get(contextHubId)); 712 } 713 supportsBtSettingNotifications()714 public boolean supportsBtSettingNotifications() { 715 return false; 716 } 717 onWifiMainSettingChanged(boolean enabled)718 public void onWifiMainSettingChanged(boolean enabled) {} onWifiScanningSettingChanged(boolean enabled)719 public void onWifiScanningSettingChanged(boolean enabled) {} onBtMainSettingChanged(boolean enabled)720 public void onBtMainSettingChanged(boolean enabled) {} onBtScanningSettingChanged(boolean enabled)721 public void onBtScanningSettingChanged(boolean enabled) {} 722 } 723 724 private static class ContextHubWrapperV1_0 extends ContextHubWrapperHidl { 725 private android.hardware.contexthub.V1_0.IContexthub mHub; 726 ContextHubWrapperV1_0(android.hardware.contexthub.V1_0.IContexthub hub)727 ContextHubWrapperV1_0(android.hardware.contexthub.V1_0.IContexthub hub) { 728 super(hub); 729 mHub = hub; 730 } 731 getHubs()732 public Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException { 733 ArrayList<ContextHubInfo> hubInfoList = new ArrayList<>(); 734 for (ContextHub hub : mHub.getHubs()) { 735 hubInfoList.add(new ContextHubInfo(hub)); 736 } 737 return new Pair(hubInfoList, new ArrayList<String>()); 738 } 739 supportsLocationSettingNotifications()740 public boolean supportsLocationSettingNotifications() { 741 return false; 742 } 743 supportsWifiSettingNotifications()744 public boolean supportsWifiSettingNotifications() { 745 return false; 746 } 747 supportsAirplaneModeSettingNotifications()748 public boolean supportsAirplaneModeSettingNotifications() { 749 return false; 750 } 751 supportsMicrophoneSettingNotifications()752 public boolean supportsMicrophoneSettingNotifications() { 753 return false; 754 } 755 onLocationSettingChanged(boolean enabled)756 public void onLocationSettingChanged(boolean enabled) { 757 } 758 onWifiSettingChanged(boolean enabled)759 public void onWifiSettingChanged(boolean enabled) { 760 } 761 onAirplaneModeSettingChanged(boolean enabled)762 public void onAirplaneModeSettingChanged(boolean enabled) { 763 } 764 onMicrophoneSettingChanged(boolean enabled)765 public void onMicrophoneSettingChanged(boolean enabled) { 766 } 767 } 768 769 private static class ContextHubWrapperV1_1 extends ContextHubWrapperHidl { 770 private android.hardware.contexthub.V1_1.IContexthub mHub; 771 ContextHubWrapperV1_1(android.hardware.contexthub.V1_1.IContexthub hub)772 ContextHubWrapperV1_1(android.hardware.contexthub.V1_1.IContexthub hub) { 773 super(hub); 774 mHub = hub; 775 } 776 getHubs()777 public Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException { 778 ArrayList<ContextHubInfo> hubInfoList = new ArrayList<>(); 779 for (ContextHub hub : mHub.getHubs()) { 780 hubInfoList.add(new ContextHubInfo(hub)); 781 } 782 return new Pair(hubInfoList, new ArrayList<String>()); 783 } 784 supportsLocationSettingNotifications()785 public boolean supportsLocationSettingNotifications() { 786 return true; 787 } 788 supportsWifiSettingNotifications()789 public boolean supportsWifiSettingNotifications() { 790 return false; 791 } 792 supportsAirplaneModeSettingNotifications()793 public boolean supportsAirplaneModeSettingNotifications() { 794 return false; 795 } 796 supportsMicrophoneSettingNotifications()797 public boolean supportsMicrophoneSettingNotifications() { 798 return false; 799 } 800 onLocationSettingChanged(boolean enabled)801 public void onLocationSettingChanged(boolean enabled) { 802 try { 803 mHub.onSettingChanged(Setting.LOCATION, 804 enabled ? SettingValue.ENABLED : SettingValue.DISABLED); 805 } catch (RemoteException e) { 806 Log.e(TAG, "Failed to send setting change to Contexthub", e); 807 } 808 } 809 onWifiSettingChanged(boolean enabled)810 public void onWifiSettingChanged(boolean enabled) { 811 } 812 onAirplaneModeSettingChanged(boolean enabled)813 public void onAirplaneModeSettingChanged(boolean enabled) { 814 } 815 onMicrophoneSettingChanged(boolean enabled)816 public void onMicrophoneSettingChanged(boolean enabled) { 817 } 818 } 819 820 private static class ContextHubWrapperV1_2 extends ContextHubWrapperHidl 821 implements android.hardware.contexthub.V1_2.IContexthub.getHubs_1_2Callback { 822 private final android.hardware.contexthub.V1_2.IContexthub mHub; 823 824 private Pair<List<ContextHubInfo>, List<String>> mHubInfo = 825 new Pair<>(Collections.emptyList(), Collections.emptyList()); 826 ContextHubWrapperV1_2(android.hardware.contexthub.V1_2.IContexthub hub)827 ContextHubWrapperV1_2(android.hardware.contexthub.V1_2.IContexthub hub) { 828 super(hub); 829 mHub = hub; 830 } 831 832 @Override onValues(ArrayList<ContextHub> hubs, ArrayList<String> supportedPermissions)833 public void onValues(ArrayList<ContextHub> hubs, ArrayList<String> supportedPermissions) { 834 ArrayList<ContextHubInfo> hubInfoList = new ArrayList<>(); 835 for (ContextHub hub : hubs) { 836 hubInfoList.add(new ContextHubInfo(hub)); 837 } 838 mHubInfo = new Pair(hubInfoList, supportedPermissions); 839 } 840 getHubs()841 public Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException { 842 mHub.getHubs_1_2(this); 843 return mHubInfo; 844 } 845 supportsLocationSettingNotifications()846 public boolean supportsLocationSettingNotifications() { 847 return true; 848 } 849 supportsWifiSettingNotifications()850 public boolean supportsWifiSettingNotifications() { 851 return true; 852 } 853 supportsAirplaneModeSettingNotifications()854 public boolean supportsAirplaneModeSettingNotifications() { 855 return true; 856 } 857 supportsMicrophoneSettingNotifications()858 public boolean supportsMicrophoneSettingNotifications() { 859 return true; 860 } 861 onLocationSettingChanged(boolean enabled)862 public void onLocationSettingChanged(boolean enabled) { 863 sendSettingChanged(Setting.LOCATION, 864 enabled ? SettingValue.ENABLED : SettingValue.DISABLED); 865 } 866 onWifiSettingChanged(boolean enabled)867 public void onWifiSettingChanged(boolean enabled) { 868 sendSettingChanged(android.hardware.contexthub.V1_2.Setting.WIFI_AVAILABLE, 869 enabled ? SettingValue.ENABLED : SettingValue.DISABLED); 870 } 871 onAirplaneModeSettingChanged(boolean enabled)872 public void onAirplaneModeSettingChanged(boolean enabled) { 873 sendSettingChanged(android.hardware.contexthub.V1_2.Setting.AIRPLANE_MODE, 874 enabled ? SettingValue.ENABLED : SettingValue.DISABLED); 875 } 876 onMicrophoneSettingChanged(boolean enabled)877 public void onMicrophoneSettingChanged(boolean enabled) { 878 sendSettingChanged(android.hardware.contexthub.V1_2.Setting.MICROPHONE, 879 enabled ? SettingValue.ENABLED : SettingValue.DISABLED); 880 } 881 registerCallback(int contextHubId, ICallback callback)882 public void registerCallback(int contextHubId, ICallback callback) throws RemoteException { 883 mHidlCallbackMap.put(contextHubId, 884 new ContextHubWrapperHidlCallback(contextHubId, callback)); 885 mHub.registerCallback_1_2(contextHubId, mHidlCallbackMap.get(contextHubId)); 886 } 887 sendSettingChanged(byte setting, byte newValue)888 private void sendSettingChanged(byte setting, byte newValue) { 889 try { 890 mHub.onSettingChanged_1_2(setting, newValue); 891 } catch (RemoteException e) { 892 Log.e(TAG, "Failed to send setting change to Contexthub", e); 893 } 894 } 895 } 896 } 897