blob: 96e9337a7932514a6c04797558c03f0397b59748 [file] [log] [blame]
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -08001/*
2 * Copyright (C) 2016 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
Ashutosh Joshi420e45e2016-12-20 16:34:41 -080017package com.android.server.location;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080018
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080019import android.content.Context;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070020import android.hardware.contexthub.V1_0.AsyncEventType;
21import android.hardware.contexthub.V1_0.ContextHub;
22import android.hardware.contexthub.V1_0.ContextHubMsg;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070023import android.hardware.contexthub.V1_0.HubAppInfo;
24import android.hardware.contexthub.V1_0.IContexthub;
25import android.hardware.contexthub.V1_0.IContexthubCallback;
26import android.hardware.contexthub.V1_0.Result;
27import android.hardware.contexthub.V1_0.TransactionResult;
Ashutosh Joshi420e45e2016-12-20 16:34:41 -080028import android.hardware.location.ContextHubInfo;
Ashutosh Joshi420e45e2016-12-20 16:34:41 -080029import android.hardware.location.ContextHubMessage;
Arthur Ishiguroebb0e862017-11-17 14:55:32 -080030import android.hardware.location.ContextHubTransaction;
Ashutosh Joshi420e45e2016-12-20 16:34:41 -080031import android.hardware.location.IContextHubCallback;
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -080032import android.hardware.location.IContextHubClient;
33import android.hardware.location.IContextHubClientCallback;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070034import android.hardware.location.IContextHubService;
35import android.hardware.location.IContextHubTransactionCallback;
Ashutosh Joshi420e45e2016-12-20 16:34:41 -080036import android.hardware.location.NanoApp;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070037import android.hardware.location.NanoAppBinary;
38import android.hardware.location.NanoAppFilter;
Ashutosh Joshi420e45e2016-12-20 16:34:41 -080039import android.hardware.location.NanoAppInstanceInfo;
Arthur Ishiguroebb0e862017-11-17 14:55:32 -080040import android.hardware.location.NanoAppMessage;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070041import android.hardware.location.NanoAppState;
destradaa78cebca2016-04-14 18:40:14 -070042import android.os.RemoteCallbackList;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080043import android.os.RemoteException;
44import android.util.Log;
45
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060046import com.android.internal.util.DumpUtils;
47
Ashutosh Joshi6239cc62016-04-04 16:19:29 -070048import java.io.FileDescriptor;
49import java.io.PrintWriter;
Ashutosh Joshi19753cc2016-11-23 13:56:39 -080050import java.nio.ByteBuffer;
51import java.nio.ByteOrder;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080052import java.util.ArrayList;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070053import java.util.Collections;
Arthur Ishiguroebb0e862017-11-17 14:55:32 -080054import java.util.HashMap;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070055import java.util.List;
Arthur Ishiguroebb0e862017-11-17 14:55:32 -080056import java.util.Map;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070057import java.util.NoSuchElementException;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080058
59/**
60 * @hide
61 */
Peng Xu9ff7d222016-02-11 13:02:05 -080062public class ContextHubService extends IContextHubService.Stub {
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080063 private static final String TAG = "ContextHubService";
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080064
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070065 /*
66 * Constants for the type of transaction that is defined by ContextHubService.
67 * This is used to report the transaction callback to clients, and is different from
68 * ContextHubTransaction.Type.
69 */
70 public static final int MSG_ENABLE_NANO_APP = 1;
71 public static final int MSG_DISABLE_NANO_APP = 2;
72 public static final int MSG_LOAD_NANO_APP = 3;
Ashutosh Joshicafdee92016-04-04 16:19:29 -070073 public static final int MSG_UNLOAD_NANO_APP = 4;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070074 public static final int MSG_QUERY_NANO_APPS = 5;
75 public static final int MSG_QUERY_MEMORY = 6;
76 public static final int MSG_HUB_RESET = 7;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070077
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070078 private static final int OS_APP_INSTANCE = -1;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080079
Arthur Ishigurob4f59872018-07-31 16:38:08 -070080 /*
81 * Local flag to enable debug logging.
82 */
83 private static final boolean DEBUG_LOG_ENABLED = false;
84
Peng Xu9ff7d222016-02-11 13:02:05 -080085 private final Context mContext;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070086
Arthur Ishiguroab7113d2017-12-15 14:32:51 -080087 private final Map<Integer, ContextHubInfo> mContextHubIdToInfoMap;
Arthur Ishigurofdbbd462017-11-27 16:33:36 -080088 private final List<ContextHubInfo> mContextHubInfoList;
destradaa78cebca2016-04-14 18:40:14 -070089 private final RemoteCallbackList<IContextHubCallback> mCallbacksList =
90 new RemoteCallbackList<>();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080091
Arthur Ishiguro7a23a962017-11-01 10:52:28 -070092 // Proxy object to communicate with the Context Hub HAL
93 private final IContexthub mContextHubProxy;
94
95 // The manager for transaction queue
96 private final ContextHubTransactionManager mTransactionManager;
97
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -080098 // The manager for sending messages to/from clients
99 private final ContextHubClientManager mClientManager;
100
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800101 // The default client for old API clients
102 private final Map<Integer, IContextHubClient> mDefaultClientMap;
103
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800104 // The manager for the internal nanoapp state cache
105 private final NanoAppStateManager mNanoAppStateManager = new NanoAppStateManager();
106
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700107 /**
108 * Class extending the callback to register with a Context Hub.
109 */
110 private class ContextHubServiceCallback extends IContexthubCallback.Stub {
111 private final int mContextHubId;
112
113 ContextHubServiceCallback(int contextHubId) {
114 mContextHubId = contextHubId;
115 }
116
117 @Override
118 public void handleClientMsg(ContextHubMsg message) {
119 handleClientMessageCallback(mContextHubId, message);
120 }
121
122 @Override
123 public void handleTxnResult(int transactionId, int result) {
124 handleTransactionResultCallback(mContextHubId, transactionId, result);
125 }
126
127 @Override
128 public void handleHubEvent(int eventType) {
129 handleHubEventCallback(mContextHubId, eventType);
130 }
131
132 @Override
133 public void handleAppAbort(long nanoAppId, int abortCode) {
134 handleAppAbortCallback(mContextHubId, nanoAppId, abortCode);
135 }
136
137 @Override
138 public void handleAppsInfo(ArrayList<HubAppInfo> nanoAppInfoList) {
139 handleQueryAppsCallback(mContextHubId, nanoAppInfoList);
140 }
141 }
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700142
Peng Xu9ff7d222016-02-11 13:02:05 -0800143 public ContextHubService(Context context) {
144 mContext = context;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700145
146 mContextHubProxy = getContextHubProxy();
147 if (mContextHubProxy == null) {
148 mTransactionManager = null;
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800149 mClientManager = null;
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800150 mDefaultClientMap = Collections.emptyMap();
151 mContextHubIdToInfoMap = Collections.emptyMap();
Arthur Ishigurofdbbd462017-11-27 16:33:36 -0800152 mContextHubInfoList = Collections.emptyList();
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700153 return;
154 }
155
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800156 mClientManager = new ContextHubClientManager(mContext, mContextHubProxy);
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800157 mTransactionManager = new ContextHubTransactionManager(
158 mContextHubProxy, mClientManager, mNanoAppStateManager);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700159
160 List<ContextHub> hubList;
161 try {
162 hubList = mContextHubProxy.getHubs();
163 } catch (RemoteException e) {
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800164 Log.e(TAG, "RemoteException while getting Context Hub info", e);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700165 hubList = Collections.emptyList();
166 }
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800167 mContextHubIdToInfoMap = Collections.unmodifiableMap(
168 ContextHubServiceUtil.createContextHubInfoMap(hubList));
Arthur Ishigurofdbbd462017-11-27 16:33:36 -0800169 mContextHubInfoList = new ArrayList<>(mContextHubIdToInfoMap.values());
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700170
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800171 HashMap<Integer, IContextHubClient> defaultClientMap = new HashMap<>();
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800172 for (int contextHubId : mContextHubIdToInfoMap.keySet()) {
Arthur Ishiguro622ebcb2018-10-17 14:02:27 -0700173 ContextHubInfo contextHubInfo = mContextHubIdToInfoMap.get(contextHubId);
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800174 IContextHubClient client = mClientManager.registerClient(
Arthur Ishiguro622ebcb2018-10-17 14:02:27 -0700175 createDefaultClientCallback(contextHubId), contextHubInfo);
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800176 defaultClientMap.put(contextHubId, client);
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800177
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700178 try {
179 mContextHubProxy.registerCallback(
180 contextHubId, new ContextHubServiceCallback(contextHubId));
181 } catch (RemoteException e) {
182 Log.e(TAG, "RemoteException while registering service callback for hub (ID = "
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800183 + contextHubId + ")", e);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700184 }
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700185
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800186 // Do a query to initialize the service cache list of nanoapps
187 // TODO(b/69270990): Remove this when old API is deprecated
188 queryNanoAppsInternal(contextHubId);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700189 }
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800190 mDefaultClientMap = Collections.unmodifiableMap(defaultClientMap);
Peng Xu9ff7d222016-02-11 13:02:05 -0800191 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800192
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700193 /**
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800194 * Creates a default client callback for old API clients.
195 *
196 * @param contextHubId the ID of the hub to attach this client to
197 * @return the internal callback interface
198 */
199 private IContextHubClientCallback createDefaultClientCallback(int contextHubId) {
200 return new IContextHubClientCallback.Stub() {
201 @Override
202 public void onMessageFromNanoApp(NanoAppMessage message) {
Arthur Ishiguro2fc5a4b2017-12-11 15:15:44 -0800203 int nanoAppHandle = mNanoAppStateManager.getNanoAppHandle(
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800204 contextHubId, message.getNanoAppId());
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800205
206 onMessageReceiptOldApi(
Arthur Ishiguro2fc5a4b2017-12-11 15:15:44 -0800207 message.getMessageType(), contextHubId, nanoAppHandle,
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800208 message.getMessageBody());
209 }
210
211 @Override
212 public void onHubReset() {
Arthur Ishiguro6d47c542017-11-17 15:49:07 -0800213 byte[] data = {TransactionResult.SUCCESS};
214 onMessageReceiptOldApi(MSG_HUB_RESET, contextHubId, OS_APP_INSTANCE, data);
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800215 }
216
217 @Override
218 public void onNanoAppAborted(long nanoAppId, int abortCode) {
219 }
220
221 @Override
222 public void onNanoAppLoaded(long nanoAppId) {
223 }
224
225 @Override
226 public void onNanoAppUnloaded(long nanoAppId) {
227 }
228
229 @Override
230 public void onNanoAppEnabled(long nanoAppId) {
231 }
232
233 @Override
234 public void onNanoAppDisabled(long nanoAppId) {
235 }
236 };
237 }
238
239 /**
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700240 * @return the IContexthub proxy interface
241 */
242 private IContexthub getContextHubProxy() {
243 IContexthub proxy = null;
244 try {
245 proxy = IContexthub.getService(true /* retry */);
246 } catch (RemoteException e) {
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800247 Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700248 } catch (NoSuchElementException e) {
249 Log.i(TAG, "Context Hub HAL service not found");
250 }
251
252 return proxy;
253 }
254
Peng Xu9ff7d222016-02-11 13:02:05 -0800255 @Override
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700256 public int registerCallback(IContextHubCallback callback) throws RemoteException {
destradaa8bad3fe2016-03-15 12:33:40 -0700257 checkPermissions();
destradaa78cebca2016-04-14 18:40:14 -0700258 mCallbacksList.register(callback);
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800259
Ashutosh Joshi1d941812017-03-09 15:21:24 -0800260 Log.d(TAG, "Added callback, total callbacks " +
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700261 mCallbacksList.getRegisteredCallbackCount());
Peng Xu9ff7d222016-02-11 13:02:05 -0800262 return 0;
263 }
264
265 @Override
266 public int[] getContextHubHandles() throws RemoteException {
destradaa8bad3fe2016-03-15 12:33:40 -0700267 checkPermissions();
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800268 return ContextHubServiceUtil.createPrimitiveIntArray(mContextHubIdToInfoMap.keySet());
Peng Xu9ff7d222016-02-11 13:02:05 -0800269 }
270
271 @Override
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800272 public ContextHubInfo getContextHubInfo(int contextHubHandle) throws RemoteException {
destradaa8bad3fe2016-03-15 12:33:40 -0700273 checkPermissions();
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800274 if (!mContextHubIdToInfoMap.containsKey(contextHubHandle)) {
275 Log.e(TAG, "Invalid Context Hub handle " + contextHubHandle + " in getContextHubInfo");
276 return null;
Peng Xu9ff7d222016-02-11 13:02:05 -0800277 }
278
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800279 return mContextHubIdToInfoMap.get(contextHubHandle);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700280 }
281
282 /**
Arthur Ishigurofdbbd462017-11-27 16:33:36 -0800283 * Returns a List of ContextHubInfo object describing the available hubs.
284 *
285 * @return the List of ContextHubInfo objects
286 */
287 @Override
288 public List<ContextHubInfo> getContextHubs() throws RemoteException {
289 checkPermissions();
290 return mContextHubInfoList;
291 }
292
293 /**
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700294 * Creates an internal load transaction callback to be used for old API clients
295 *
296 * @param contextHubId the ID of the hub to load the binary
297 * @param nanoAppBinary the binary to load
298 * @return the callback interface
299 */
300 private IContextHubTransactionCallback createLoadTransactionCallback(
301 int contextHubId, NanoAppBinary nanoAppBinary) {
302 return new IContextHubTransactionCallback.Stub() {
303 @Override
304 public void onTransactionComplete(int result) {
305 handleLoadResponseOldApi(contextHubId, result, nanoAppBinary);
306 }
307
308 @Override
309 public void onQueryResponse(int result, List<NanoAppState> nanoAppStateList) {
310 }
311 };
312 }
313
314 /**
315 * Creates an internal unload transaction callback to be used for old API clients
316 *
317 * @param contextHubId the ID of the hub to unload the nanoapp
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700318 * @return the callback interface
319 */
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800320 private IContextHubTransactionCallback createUnloadTransactionCallback(int contextHubId) {
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700321 return new IContextHubTransactionCallback.Stub() {
322 @Override
323 public void onTransactionComplete(int result) {
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800324 handleUnloadResponseOldApi(contextHubId, result);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700325 }
326
327 @Override
328 public void onQueryResponse(int result, List<NanoAppState> nanoAppStateList) {
329 }
330 };
331 }
332
333 /**
334 * Creates an internal query transaction callback to be used for old API clients
335 *
336 * @param contextHubId the ID of the hub to query
337 * @return the callback interface
338 */
339 private IContextHubTransactionCallback createQueryTransactionCallback(int contextHubId) {
340 return new IContextHubTransactionCallback.Stub() {
341 @Override
342 public void onTransactionComplete(int result) {
343 }
344
345 @Override
346 public void onQueryResponse(int result, List<NanoAppState> nanoAppStateList) {
347 byte[] data = {(byte) result};
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800348 onMessageReceiptOldApi(MSG_QUERY_NANO_APPS, contextHubId, OS_APP_INSTANCE, data);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700349 }
350 };
351 }
352
Peng Xu9ff7d222016-02-11 13:02:05 -0800353 @Override
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800354 public int loadNanoApp(int contextHubHandle, NanoApp nanoApp) throws RemoteException {
destradaa8bad3fe2016-03-15 12:33:40 -0700355 checkPermissions();
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700356 if (mContextHubProxy == null) {
357 return -1;
358 }
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800359 if (!isValidContextHubId(contextHubHandle)) {
360 Log.e(TAG, "Invalid Context Hub handle " + contextHubHandle + " in loadNanoApp");
Ashutosh Joshi6239cc62016-04-04 16:19:29 -0700361 return -1;
Peng Xu9ff7d222016-02-11 13:02:05 -0800362 }
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800363 if (nanoApp == null) {
364 Log.e(TAG, "NanoApp cannot be null in loadNanoApp");
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600365 return -1;
366 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800367
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700368 // Create an internal IContextHubTransactionCallback for the old API clients
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800369 NanoAppBinary nanoAppBinary = new NanoAppBinary(nanoApp.getAppBinary());
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700370 IContextHubTransactionCallback onCompleteCallback =
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800371 createLoadTransactionCallback(contextHubHandle, nanoAppBinary);
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700372
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700373 ContextHubServiceTransaction transaction = mTransactionManager.createLoadTransaction(
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800374 contextHubHandle, nanoAppBinary, onCompleteCallback);
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700375
Arthur Ishiguroe60f91a2017-11-30 09:48:00 -0800376 mTransactionManager.addTransaction(transaction);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700377 return 0;
Peng Xu9ff7d222016-02-11 13:02:05 -0800378 }
379
destradaa8bad3fe2016-03-15 12:33:40 -0700380 @Override
Arthur Ishiguro2fc5a4b2017-12-11 15:15:44 -0800381 public int unloadNanoApp(int nanoAppHandle) throws RemoteException {
destradaa8bad3fe2016-03-15 12:33:40 -0700382 checkPermissions();
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700383 if (mContextHubProxy == null) {
384 return -1;
385 }
386
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800387 NanoAppInstanceInfo info =
Arthur Ishiguro2fc5a4b2017-12-11 15:15:44 -0800388 mNanoAppStateManager.getNanoAppInstanceInfo(nanoAppHandle);
Peng Xu9ff7d222016-02-11 13:02:05 -0800389 if (info == null) {
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800390 Log.e(TAG, "Invalid nanoapp handle " + nanoAppHandle + " in unloadNanoApp");
Arthur Ishiguro2fc5a4b2017-12-11 15:15:44 -0800391 return -1;
Peng Xu9ff7d222016-02-11 13:02:05 -0800392 }
393
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700394 int contextHubId = info.getContexthubId();
395 long nanoAppId = info.getAppId();
396 IContextHubTransactionCallback onCompleteCallback =
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800397 createUnloadTransactionCallback(contextHubId);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700398 ContextHubServiceTransaction transaction = mTransactionManager.createUnloadTransaction(
399 contextHubId, nanoAppId, onCompleteCallback);
Peng Xu9ff7d222016-02-11 13:02:05 -0800400
Arthur Ishiguroe60f91a2017-11-30 09:48:00 -0800401 mTransactionManager.addTransaction(transaction);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700402 return 0;
destradaa8bad3fe2016-03-15 12:33:40 -0700403 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800404
405 @Override
Arthur Ishiguro2fc5a4b2017-12-11 15:15:44 -0800406 public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) throws RemoteException {
destradaa8bad3fe2016-03-15 12:33:40 -0700407 checkPermissions();
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800408
Arthur Ishiguro2fc5a4b2017-12-11 15:15:44 -0800409 return mNanoAppStateManager.getNanoAppInstanceInfo(nanoAppHandle);
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800410 }
411
412 @Override
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800413 public int[] findNanoAppOnHub(
414 int contextHubHandle, NanoAppFilter filter) throws RemoteException {
destradaa8bad3fe2016-03-15 12:33:40 -0700415 checkPermissions();
Peng Xu9ff7d222016-02-11 13:02:05 -0800416
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800417 ArrayList<Integer> foundInstances = new ArrayList<>();
418 for (NanoAppInstanceInfo info : mNanoAppStateManager.getNanoAppInstanceInfoCollection()) {
Ashutosh Joshi6239cc62016-04-04 16:19:29 -0700419 if (filter.testMatch(info)) {
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800420 foundInstances.add(info.getHandle());
Peng Xu9ff7d222016-02-11 13:02:05 -0800421 }
422 }
423
424 int[] retArray = new int[foundInstances.size()];
425 for (int i = 0; i < foundInstances.size(); i++) {
426 retArray[i] = foundInstances.get(i).intValue();
427 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800428 return retArray;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800429 }
430
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700431 /**
432 * Performs a query at the specified hub.
433 *
434 * This method should only be invoked internally by the service, either to update the service
435 * cache or as a result of an explicit query requested by a client through the sendMessage API.
436 *
437 * @param contextHubId the ID of the hub to do the query
438 * @return the result of the query
Arthur Ishiguroe60f91a2017-11-30 09:48:00 -0800439 *
440 * @throws IllegalStateException if the transaction queue is full
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700441 */
442 private int queryNanoAppsInternal(int contextHubId) {
443 if (mContextHubProxy == null) {
444 return Result.UNKNOWN_FAILURE;
445 }
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700446
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700447 IContextHubTransactionCallback onCompleteCallback =
448 createQueryTransactionCallback(contextHubId);
449 ContextHubServiceTransaction transaction = mTransactionManager.createQueryTransaction(
450 contextHubId, onCompleteCallback);
451
Arthur Ishiguroe60f91a2017-11-30 09:48:00 -0800452 mTransactionManager.addTransaction(transaction);
453 return Result.OK;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700454 }
455
456 @Override
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800457 public int sendMessage(int contextHubHandle, int nanoAppHandle, ContextHubMessage msg)
458 throws RemoteException {
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700459 checkPermissions();
460 if (mContextHubProxy == null) {
461 return -1;
462 }
463 if (msg == null) {
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800464 Log.e(TAG, "ContextHubMessage cannot be null in sendMessage");
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700465 return -1;
466 }
467 if (msg.getData() == null) {
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800468 Log.e(TAG, "ContextHubMessage message body cannot be null in sendMessage");
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800469 return -1;
470 }
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800471 if (!isValidContextHubId(contextHubHandle)) {
472 Log.e(TAG, "Invalid Context Hub handle " + contextHubHandle + " in sendMessage");
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600473 return -1;
474 }
475
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800476 boolean success = false;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700477 if (nanoAppHandle == OS_APP_INSTANCE) {
478 if (msg.getMsgType() == MSG_QUERY_NANO_APPS) {
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800479 success = (queryNanoAppsInternal(contextHubHandle) == Result.OK);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700480 } else {
481 Log.e(TAG, "Invalid OS message params of type " + msg.getMsgType());
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700482 }
483 } else {
484 NanoAppInstanceInfo info = getNanoAppInstanceInfo(nanoAppHandle);
485 if (info != null) {
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800486 NanoAppMessage message = NanoAppMessage.createMessageToNanoApp(
487 info.getAppId(), msg.getMsgType(), msg.getData());
Peng Xu9ff7d222016-02-11 13:02:05 -0800488
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800489 IContextHubClient client = mDefaultClientMap.get(contextHubHandle);
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800490 success = (client.sendMessageToNanoApp(message) ==
Arthur Ishiguro6100aa72017-12-20 09:35:00 -0800491 ContextHubTransaction.RESULT_SUCCESS);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700492 } else {
Arthur Ishiguro2fc5a4b2017-12-11 15:15:44 -0800493 Log.e(TAG, "Failed to send nanoapp message - nanoapp with handle "
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700494 + nanoAppHandle + " does not exist.");
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700495 }
496 }
497
Arthur Ishiguroebb0e862017-11-17 14:55:32 -0800498 return success ? 0 : -1;
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700499 }
500
501 /**
502 * Handles a unicast or broadcast message from a nanoapp.
503 *
504 * @param contextHubId the ID of the hub the message came from
505 * @param message the message contents
506 */
507 private void handleClientMessageCallback(int contextHubId, ContextHubMsg message) {
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800508 mClientManager.onMessageFromNanoApp(contextHubId, message);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700509 }
510
511 /**
512 * A helper function to handle a load response from the Context Hub for the old API.
513 *
514 * TODO(b/69270990): Remove this once the old APIs are obsolete.
515 */
516 private void handleLoadResponseOldApi(
517 int contextHubId, int result, NanoAppBinary nanoAppBinary) {
518 if (nanoAppBinary == null) {
519 Log.e(TAG, "Nanoapp binary field was null for a load transaction");
520 return;
521 }
522
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700523 byte[] data = new byte[5];
524 data[0] = (byte) result;
Arthur Ishiguro2fc5a4b2017-12-11 15:15:44 -0800525 int nanoAppHandle = mNanoAppStateManager.getNanoAppHandle(
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800526 contextHubId, nanoAppBinary.getNanoAppId());
Arthur Ishiguro2fc5a4b2017-12-11 15:15:44 -0800527 ByteBuffer.wrap(data, 1, 4).order(ByteOrder.nativeOrder()).putInt(nanoAppHandle);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700528
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800529 onMessageReceiptOldApi(MSG_LOAD_NANO_APP, contextHubId, OS_APP_INSTANCE, data);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700530 }
531
532 /**
533 * A helper function to handle an unload response from the Context Hub for the old API.
534 *
535 * TODO(b/69270990): Remove this once the old APIs are obsolete.
536 */
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800537 private void handleUnloadResponseOldApi(int contextHubId, int result) {
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700538 byte[] data = new byte[1];
539 data[0] = (byte) result;
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800540 onMessageReceiptOldApi(MSG_UNLOAD_NANO_APP, contextHubId, OS_APP_INSTANCE, data);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700541 }
542
543 /**
544 * Handles a transaction response from a Context Hub.
545 *
546 * @param contextHubId the ID of the hub the response came from
547 * @param transactionId the ID of the transaction
548 * @param result the result of the transaction reported by the hub
549 */
550 private void handleTransactionResultCallback(int contextHubId, int transactionId, int result) {
551 mTransactionManager.onTransactionResponse(transactionId, result);
552 }
553
554 /**
555 * Handles an asynchronous event from a Context Hub.
556 *
557 * @param contextHubId the ID of the hub the response came from
558 * @param eventType the type of the event as defined in Context Hub HAL AsyncEventType
559 */
560 private void handleHubEventCallback(int contextHubId, int eventType) {
561 if (eventType == AsyncEventType.RESTARTED) {
562 mTransactionManager.onHubReset();
563 queryNanoAppsInternal(contextHubId);
564
Arthur Ishiguro6d47c542017-11-17 15:49:07 -0800565 mClientManager.onHubReset(contextHubId);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700566 } else {
567 Log.i(TAG, "Received unknown hub event (hub ID = " + contextHubId + ", type = "
568 + eventType + ")");
569 }
570 }
571
572 /**
573 * Handles an asynchronous abort event of a nanoapp.
574 *
575 * @param contextHubId the ID of the hub that the nanoapp aborted in
576 * @param nanoAppId the ID of the aborted nanoapp
577 * @param abortCode the nanoapp-specific abort code
578 */
579 private void handleAppAbortCallback(int contextHubId, long nanoAppId, int abortCode) {
Arthur Ishiguro02ff50b2017-12-18 10:02:35 -0800580 mClientManager.onNanoAppAborted(contextHubId, nanoAppId, abortCode);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700581 }
582
583 /**
584 * Handles a query response from a Context Hub.
585 *
586 * @param contextHubId the ID of the hub of the response
587 * @param nanoAppInfoList the list of loaded nanoapps
588 */
589 private void handleQueryAppsCallback(int contextHubId, List<HubAppInfo> nanoAppInfoList) {
590 List<NanoAppState> nanoAppStateList =
591 ContextHubServiceUtil.createNanoAppStateList(nanoAppInfoList);
592
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800593 mNanoAppStateManager.updateCache(contextHubId, nanoAppInfoList);
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700594 mTransactionManager.onQueryResponse(nanoAppStateList);
595 }
596
597 /**
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800598 * @param contextHubId the hub ID to validate
599 * @return {@code true} if the ID represents that of an available hub, {@code false} otherwise
600 */
601 private boolean isValidContextHubId(int contextHubId) {
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800602 return mContextHubIdToInfoMap.containsKey(contextHubId);
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800603 }
604
605 /**
606 * Creates and registers a client at the service for the specified Context Hub.
607 *
608 * @param clientCallback the client interface to register with the service
609 * @param contextHubId the ID of the hub this client is attached to
610 * @return the generated client interface, null if registration was unsuccessful
611 *
612 * @throws IllegalArgumentException if contextHubId is not a valid ID
613 * @throws IllegalStateException if max number of clients have already registered
614 * @throws NullPointerException if clientCallback is null
615 */
616 @Override
617 public IContextHubClient createClient(
618 IContextHubClientCallback clientCallback, int contextHubId) throws RemoteException {
619 checkPermissions();
620 if (!isValidContextHubId(contextHubId)) {
621 throw new IllegalArgumentException("Invalid context hub ID " + contextHubId);
622 }
623 if (clientCallback == null) {
624 throw new NullPointerException("Cannot register client with null callback");
625 }
626
Arthur Ishiguro622ebcb2018-10-17 14:02:27 -0700627 ContextHubInfo contextHubInfo = mContextHubIdToInfoMap.get(contextHubId);
628 return mClientManager.registerClient(clientCallback, contextHubInfo);
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800629 }
630
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800631 /**
632 * Loads a nanoapp binary at the specified Context hub.
633 *
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800634 * @param contextHubId the ID of the hub to load the binary
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800635 * @param transactionCallback the client-facing transaction callback interface
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800636 * @param nanoAppBinary the binary to load
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800637 *
Arthur Ishiguroe60f91a2017-11-30 09:48:00 -0800638 * @throws IllegalStateException if the transaction queue is full
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800639 */
640 @Override
641 public void loadNanoAppOnHub(
642 int contextHubId, IContextHubTransactionCallback transactionCallback,
643 NanoAppBinary nanoAppBinary) throws RemoteException {
644 checkPermissions();
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800645 if (!checkHalProxyAndContextHubId(
646 contextHubId, transactionCallback, ContextHubTransaction.TYPE_LOAD_NANOAPP)) {
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800647 return;
648 }
649 if (nanoAppBinary == null) {
650 Log.e(TAG, "NanoAppBinary cannot be null in loadNanoAppOnHub");
651 transactionCallback.onTransactionComplete(
Arthur Ishiguro6100aa72017-12-20 09:35:00 -0800652 ContextHubTransaction.RESULT_FAILED_BAD_PARAMS);
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800653 return;
654 }
655
656 ContextHubServiceTransaction transaction = mTransactionManager.createLoadTransaction(
657 contextHubId, nanoAppBinary, transactionCallback);
Arthur Ishiguroe60f91a2017-11-30 09:48:00 -0800658 mTransactionManager.addTransaction(transaction);
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800659 }
660
661 /**
662 * Unloads a nanoapp from the specified Context Hub.
663 *
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800664 * @param contextHubId the ID of the hub to unload the nanoapp
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800665 * @param transactionCallback the client-facing transaction callback interface
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800666 * @param nanoAppId the ID of the nanoapp to unload
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800667 *
Arthur Ishiguroe60f91a2017-11-30 09:48:00 -0800668 * @throws IllegalStateException if the transaction queue is full
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800669 */
670 @Override
671 public void unloadNanoAppFromHub(
672 int contextHubId, IContextHubTransactionCallback transactionCallback, long nanoAppId)
673 throws RemoteException {
674 checkPermissions();
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800675 if (!checkHalProxyAndContextHubId(
676 contextHubId, transactionCallback, ContextHubTransaction.TYPE_UNLOAD_NANOAPP)) {
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800677 return;
678 }
679
680 ContextHubServiceTransaction transaction = mTransactionManager.createUnloadTransaction(
681 contextHubId, nanoAppId, transactionCallback);
Arthur Ishiguroe60f91a2017-11-30 09:48:00 -0800682 mTransactionManager.addTransaction(transaction);
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800683 }
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800684
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800685 /**
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800686 * Enables a nanoapp at the specified Context Hub.
687 *
688 * @param contextHubId the ID of the hub to enable the nanoapp
689 * @param transactionCallback the client-facing transaction callback interface
690 * @param nanoAppId the ID of the nanoapp to enable
691 *
692 * @throws IllegalStateException if the transaction queue is full
693 */
694 @Override
695 public void enableNanoApp(
696 int contextHubId, IContextHubTransactionCallback transactionCallback, long nanoAppId)
697 throws RemoteException {
698 checkPermissions();
699 if (!checkHalProxyAndContextHubId(
700 contextHubId, transactionCallback, ContextHubTransaction.TYPE_ENABLE_NANOAPP)) {
701 return;
702 }
703
704 ContextHubServiceTransaction transaction = mTransactionManager.createEnableTransaction(
705 contextHubId, nanoAppId, transactionCallback);
706 mTransactionManager.addTransaction(transaction);
707 }
708
709 /**
Arthur Ishiguro54e1a892017-12-12 15:09:31 -0800710 * Disables a nanoapp at the specified Context Hub.
711 *
712 * @param contextHubId the ID of the hub to disable the nanoapp
713 * @param transactionCallback the client-facing transaction callback interface
714 * @param nanoAppId the ID of the nanoapp to disable
715 *
716 * @throws IllegalStateException if the transaction queue is full
717 */
718 @Override
719 public void disableNanoApp(
720 int contextHubId, IContextHubTransactionCallback transactionCallback, long nanoAppId)
721 throws RemoteException {
722 checkPermissions();
723 if (!checkHalProxyAndContextHubId(
724 contextHubId, transactionCallback, ContextHubTransaction.TYPE_DISABLE_NANOAPP)) {
725 return;
726 }
727
728 ContextHubServiceTransaction transaction = mTransactionManager.createDisableTransaction(
729 contextHubId, nanoAppId, transactionCallback);
730 mTransactionManager.addTransaction(transaction);
731 }
732
733 /**
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800734 * Queries for a list of nanoapps from the specified Context hub.
735 *
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800736 * @param contextHubId the ID of the hub to query
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800737 * @param transactionCallback the client-facing transaction callback interface
738 *
Arthur Ishiguroe60f91a2017-11-30 09:48:00 -0800739 * @throws IllegalStateException if the transaction queue is full
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800740 */
741 @Override
742 public void queryNanoApps(int contextHubId, IContextHubTransactionCallback transactionCallback)
743 throws RemoteException {
744 checkPermissions();
745 if (!checkHalProxyAndContextHubId(
746 contextHubId, transactionCallback, ContextHubTransaction.TYPE_QUERY_NANOAPPS)) {
747 return;
748 }
749
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800750 ContextHubServiceTransaction transaction = mTransactionManager.createQueryTransaction(
751 contextHubId, transactionCallback);
Arthur Ishiguroe60f91a2017-11-30 09:48:00 -0800752 mTransactionManager.addTransaction(transaction);
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800753 }
754
Ashutosh Joshi6239cc62016-04-04 16:19:29 -0700755 @Override
756 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600757 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Ashutosh Joshi6239cc62016-04-04 16:19:29 -0700758
759 pw.println("Dumping ContextHub Service");
760
761 pw.println("");
762 // dump ContextHubInfo
763 pw.println("=================== CONTEXT HUBS ====================");
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800764 for (ContextHubInfo hubInfo : mContextHubIdToInfoMap.values()) {
765 pw.println(hubInfo);
Ashutosh Joshi6239cc62016-04-04 16:19:29 -0700766 }
767 pw.println("");
768 pw.println("=================== NANOAPPS ====================");
769 // Dump nanoAppHash
Arthur Ishigurofb9e4c72017-11-21 15:33:21 -0800770 for (NanoAppInstanceInfo info : mNanoAppStateManager.getNanoAppInstanceInfoCollection()) {
771 pw.println(info);
Ashutosh Joshi6239cc62016-04-04 16:19:29 -0700772 }
773
774 // dump eventLog
775 }
776
destradaa8bad3fe2016-03-15 12:33:40 -0700777 private void checkPermissions() {
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800778 ContextHubServiceUtil.checkPermissions(mContext);
destradaa8bad3fe2016-03-15 12:33:40 -0700779 }
Ashutosh Joshi2c697fb2016-04-01 20:48:13 +0000780
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800781 private int onMessageReceiptOldApi(
782 int msgType, int contextHubHandle, int appInstance, byte[] data) {
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700783 if (data == null) {
784 return -1;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700785 }
Ashutosh Joshi1d941812017-03-09 15:21:24 -0800786
Arthur Ishiguro7a23a962017-11-01 10:52:28 -0700787 int msgVersion = 0;
destradaa78cebca2016-04-14 18:40:14 -0700788 int callbacksCount = mCallbacksList.beginBroadcast();
Arthur Ishigurob4f59872018-07-31 16:38:08 -0700789 if (DEBUG_LOG_ENABLED) {
790 Log.v(TAG, "Sending message " + msgType + " version " + msgVersion + " from hubHandle "
791 + contextHubHandle + ", appInstance " + appInstance + ", callBackCount "
792 + callbacksCount);
793 }
Ashutosh Joshi1d941812017-03-09 15:21:24 -0800794
destradaa78cebca2016-04-14 18:40:14 -0700795 if (callbacksCount < 1) {
Arthur Ishigurob4f59872018-07-31 16:38:08 -0700796 if (DEBUG_LOG_ENABLED) {
797 Log.v(TAG, "No message callbacks registered.");
798 }
destradaa78cebca2016-04-14 18:40:14 -0700799 return 0;
800 }
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700801
Ashutosh Joshi1d941812017-03-09 15:21:24 -0800802 ContextHubMessage msg = new ContextHubMessage(msgType, msgVersion, data);
destradaa78cebca2016-04-14 18:40:14 -0700803 for (int i = 0; i < callbacksCount; ++i) {
804 IContextHubCallback callback = mCallbacksList.getBroadcastItem(i);
805 try {
Arthur Ishiguroab7113d2017-12-15 14:32:51 -0800806 callback.onMessageReceipt(contextHubHandle, appInstance, msg);
destradaa78cebca2016-04-14 18:40:14 -0700807 } catch (RemoteException e) {
808 Log.i(TAG, "Exception (" + e + ") calling remote callback (" + callback + ").");
809 continue;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700810 }
811 }
destradaa78cebca2016-04-14 18:40:14 -0700812 mCallbacksList.finishBroadcast();
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700813 return 0;
814 }
815
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800816 /**
817 * Validates the HAL proxy state and context hub ID to see if we can start the transaction.
818 *
819 * @param contextHubId the ID of the hub to start the transaction
820 * @param callback the client transaction callback interface
821 * @param transactionType the type of the transaction
822 *
823 * @return {@code true} if mContextHubProxy and contextHubId is valid, {@code false} otherwise
824 */
825 private boolean checkHalProxyAndContextHubId(
826 int contextHubId, IContextHubTransactionCallback callback,
827 @ContextHubTransaction.Type int transactionType) {
828 if (mContextHubProxy == null) {
829 try {
830 callback.onTransactionComplete(
Arthur Ishiguro6100aa72017-12-20 09:35:00 -0800831 ContextHubTransaction.RESULT_FAILED_HAL_UNAVAILABLE);
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800832 } catch (RemoteException e) {
833 Log.e(TAG, "RemoteException while calling onTransactionComplete", e);
834 }
835 return false;
836 }
837 if (!isValidContextHubId(contextHubId)) {
838 Log.e(TAG, "Cannot start "
839 + ContextHubTransaction.typeToString(transactionType, false /* upperCase */)
840 + " transaction for invalid hub ID " + contextHubId);
841 try {
Arthur Ishiguro6100aa72017-12-20 09:35:00 -0800842 callback.onTransactionComplete(ContextHubTransaction.RESULT_FAILED_BAD_PARAMS);
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800843 } catch (RemoteException e) {
844 Log.e(TAG, "RemoteException while calling onTransactionComplete", e);
845 }
846 return false;
847 }
848
849 return true;
850 }
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700851}