• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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