blob: 8a0d2e6c981d4dd0a1bc6bb4a31bf29c46fb1308 [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 */
16package android.hardware.location;
17
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -070018import android.annotation.Nullable;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060019import android.annotation.RequiresPermission;
20import android.annotation.SuppressLint;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080021import android.annotation.SystemApi;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060022import android.annotation.SystemService;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080023import android.content.Context;
Peng Xu9ff7d222016-02-11 13:02:05 -080024import android.os.Handler;
Peng Xu9ff7d222016-02-11 13:02:05 -080025import android.os.Looper;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080026import android.os.RemoteException;
Peng Xu9ff7d222016-02-11 13:02:05 -080027import android.os.ServiceManager;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060028import android.os.ServiceManager.ServiceNotFoundException;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080029import android.util.Log;
30
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -070031import java.util.List;
32
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080033/**
destradaa8bad3fe2016-03-15 12:33:40 -070034 * A class that exposes the Context hubs on a device to applications.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080035 *
destradaa8bad3fe2016-03-15 12:33:40 -070036 * Please note that this class is not expected to be used by unbundled applications. Also, calling
37 * applications are expected to have LOCATION_HARDWARE permissions to use this class.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080038 *
39 * @hide
40 */
41@SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060042@SystemService(Context.CONTEXTHUB_SERVICE)
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080043public final class ContextHubManager {
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080044 private static final String TAG = "ContextHubManager";
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080045
Peng Xu9ff7d222016-02-11 13:02:05 -080046 private final Looper mMainLooper;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060047 private final IContextHubService mService;
Greg Kaiser6ba60e62016-03-18 10:08:39 -070048 private Callback mCallback;
Peng Xu9ff7d222016-02-11 13:02:05 -080049 private Handler mCallbackHandler;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080050
51 /**
destradaa78cebca2016-04-14 18:40:14 -070052 * @deprecated Use {@code mCallback} instead.
53 */
54 @Deprecated
55 private ICallback mLocalCallback;
56
57 /**
destradaa8bad3fe2016-03-15 12:33:40 -070058 * An interface to receive asynchronous communication from the context hub.
Peng Xu9ff7d222016-02-11 13:02:05 -080059 */
Greg Kaiser6ba60e62016-03-18 10:08:39 -070060 public abstract static class Callback {
61 protected Callback() {}
destradaa8bad3fe2016-03-15 12:33:40 -070062
Peng Xu9ff7d222016-02-11 13:02:05 -080063 /**
destradaa8bad3fe2016-03-15 12:33:40 -070064 * Callback function called on message receipt from context hub.
Peng Xu9ff7d222016-02-11 13:02:05 -080065 *
destradaa8bad3fe2016-03-15 12:33:40 -070066 * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070067 * @param nanoAppHandle Handle (unique identifier) for app instance that sent the message.
destradaa8bad3fe2016-03-15 12:33:40 -070068 * @param message The context hub message.
Peng Xu9ff7d222016-02-11 13:02:05 -080069 *
70 * @see ContextHubMessage
71 */
destradaa8bad3fe2016-03-15 12:33:40 -070072 public abstract void onMessageReceipt(
73 int hubHandle,
74 int nanoAppHandle,
75 ContextHubMessage message);
Peng Xu9ff7d222016-02-11 13:02:05 -080076 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080077
78 /**
destradaa78cebca2016-04-14 18:40:14 -070079 * @deprecated Use {@link Callback} instead.
80 * @hide
81 */
82 @Deprecated
83 public interface ICallback {
84 /**
85 * Callback function called on message receipt from context hub.
86 *
87 * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
88 * @param nanoAppHandle Handle (unique identifier) for app instance that sent the message.
89 * @param message The context hub message.
90 *
91 * @see ContextHubMessage
92 */
93 void onMessageReceipt(int hubHandle, int nanoAppHandle, ContextHubMessage message);
94 }
95
96 /**
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080097 * Get a handle to all the context hubs in the system
98 * @return array of context hub handles
99 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600100 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Peng Xu9ff7d222016-02-11 13:02:05 -0800101 public int[] getContextHubHandles() {
Peng Xu9ff7d222016-02-11 13:02:05 -0800102 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600103 return mService.getContextHubHandles();
Peng Xu9ff7d222016-02-11 13:02:05 -0800104 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600105 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800106 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800107 }
108
109 /**
110 * Get more information about a specific hub.
111 *
destradaa8bad3fe2016-03-15 12:33:40 -0700112 * @param hubHandle Handle (system-wide unique identifier) of a context hub.
113 * @return ContextHubInfo Information about the requested context hub.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800114 *
115 * @see ContextHubInfo
116 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600117 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
destradaa8bad3fe2016-03-15 12:33:40 -0700118 public ContextHubInfo getContextHubInfo(int hubHandle) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800119 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600120 return mService.getContextHubInfo(hubHandle);
Peng Xu9ff7d222016-02-11 13:02:05 -0800121 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600122 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800123 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800124 }
125
126 /**
destradaa8bad3fe2016-03-15 12:33:40 -0700127 * Load a nano app on a specified context hub.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800128 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700129 * Note that loading is asynchronous. When we return from this method,
130 * the nano app (probably) hasn't loaded yet. Assuming a return of 0
131 * from this method, then the final success/failure for the load, along
132 * with the "handle" for the nanoapp, is all delivered in a byte
133 * string via a call to Callback.onMessageReceipt.
134 *
135 * TODO(b/30784270): Provide a better success/failure and "handle" delivery.
136 *
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800137 * @param hubHandle handle of context hub to load the app on.
138 * @param app the nanoApp to load on the hub
139 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700140 * @return 0 if the command for loading was sent to the context hub;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800141 * -1 otherwise
142 *
143 * @see NanoApp
144 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600145 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800146 public int loadNanoApp(int hubHandle, NanoApp app) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800147 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600148 return mService.loadNanoApp(hubHandle, app);
Peng Xu9ff7d222016-02-11 13:02:05 -0800149 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600150 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800151 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800152 }
153
154 /**
155 * Unload a specified nanoApp
156 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700157 * Note that unloading is asynchronous. When we return from this method,
158 * the nano app (probably) hasn't unloaded yet. Assuming a return of 0
159 * from this method, then the final success/failure for the unload is
160 * delivered in a byte string via a call to Callback.onMessageReceipt.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800161 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700162 * TODO(b/30784270): Provide a better success/failure delivery.
163 *
164 * @param nanoAppHandle handle of the nanoApp to unload
165 *
166 * @return 0 if the command for unloading was sent to the context hub;
167 * -1 otherwise
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800168 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600169 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
destradaa8bad3fe2016-03-15 12:33:40 -0700170 public int unloadNanoApp(int nanoAppHandle) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800171 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600172 return mService.unloadNanoApp(nanoAppHandle);
Peng Xu9ff7d222016-02-11 13:02:05 -0800173 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600174 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800175 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800176 }
177
178 /**
179 * get information about the nano app instance
180 *
Greg Kaiser3be73d32016-08-18 10:13:52 -0700181 * NOTE: The returned NanoAppInstanceInfo does _not_ contain correct
182 * information for several fields, specifically:
183 * - getName()
184 * - getPublisher()
185 * - getNeededExecMemBytes()
186 * - getNeededReadMemBytes()
187 * - getNeededWriteMemBytes()
188 *
189 * For example, say you call loadNanoApp() with a NanoApp that has
190 * getName() returning "My Name". Later, if you call getNanoAppInstanceInfo
191 * for that nanoapp, the returned NanoAppInstanceInfo's getName()
192 * method will claim "Preloaded app, unknown", even though you would
193 * have expected "My Name". For now, as the user, you'll need to
194 * separately track the above fields if they are of interest to you.
195 *
196 * TODO(b/30943489): Have the returned NanoAppInstanceInfo contain the
197 * correct information.
198 *
destradaa8bad3fe2016-03-15 12:33:40 -0700199 * @param nanoAppHandle handle of the nanoAppInstance
200 * @return NanoAppInstanceInfo Information about the nano app instance.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800201 *
202 * @see NanoAppInstanceInfo
203 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600204 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
destradaa8bad3fe2016-03-15 12:33:40 -0700205 public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800206 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600207 return mService.getNanoAppInstanceInfo(nanoAppHandle);
Peng Xu9ff7d222016-02-11 13:02:05 -0800208 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600209 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800210 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800211 }
212
213 /**
214 * Find a specified nano app on the system
215 *
216 * @param hubHandle handle of hub to search for nano app
217 * @param filter filter specifying the search criteria for app
218 *
219 * @see NanoAppFilter
220 *
destradaa8bad3fe2016-03-15 12:33:40 -0700221 * @return int[] Array of handles to any found nano apps
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800222 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600223 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
destradaa8bad3fe2016-03-15 12:33:40 -0700224 public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800225 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600226 return mService.findNanoAppOnHub(hubHandle, filter);
Peng Xu9ff7d222016-02-11 13:02:05 -0800227 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600228 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800229 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800230 }
231
232 /**
destradaa8bad3fe2016-03-15 12:33:40 -0700233 * Send a message to a specific nano app instance on a context hub.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800234 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700235 * Note that the return value of this method only speaks of success
236 * up to the point of sending this to the Context Hub. It is not
237 * an assurance that the Context Hub successfully sent this message
238 * on to the nanoapp. If assurance is desired, a protocol should be
239 * established between your code and the nanoapp, with the nanoapp
240 * sending a confirmation message (which will be reported via
241 * Callback.onMessageReceipt).
242 *
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800243 * @param hubHandle handle of the hub to send the message to
244 * @param nanoAppHandle handle of the nano app to send to
destradaa8bad3fe2016-03-15 12:33:40 -0700245 * @param message Message to be sent
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800246 *
247 * @see ContextHubMessage
248 *
249 * @return int 0 on success, -1 otherwise
250 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600251 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Peng Xu9ff7d222016-02-11 13:02:05 -0800252 public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800253 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600254 return mService.sendMessage(hubHandle, nanoAppHandle, message);
Peng Xu9ff7d222016-02-11 13:02:05 -0800255 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600256 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800257 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800258 }
259
Peng Xu9ff7d222016-02-11 13:02:05 -0800260 /**
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700261 * Returns the list of context hubs in the system.
262 *
263 * @return the list of context hub informations
264 *
265 * @see ContextHubInfo
266 *
267 * @hide
268 */
269 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
270 public List<ContextHubInfo> getContextHubs() {
271 throw new UnsupportedOperationException("TODO: Implement this");
272 }
273
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800274 /**
Arthur Ishiguro6c37fd02017-10-26 15:36:22 -0700275 * Helper function to generate a stub for a non-query transaction callback.
276 *
277 * @param transaction the transaction to unblock when complete
278 *
279 * @return the callback
280 *
281 * @hide
282 */
283 private IContextHubTransactionCallback createTransactionCallback(
284 ContextHubTransaction<Void> transaction) {
285 return new IContextHubTransactionCallback.Stub() {
286 @Override
287 public void onQueryResponse(int result, List<NanoAppState> nanoappList) {
288 Log.e(TAG, "Received a query callback on a non-query request");
289 transaction.setResponse(new ContextHubTransaction.Response<Void>(
290 ContextHubTransaction.TRANSACTION_FAILED_SERVICE_INTERNAL_FAILURE, null));
291 }
292
293 @Override
294 public void onTransactionComplete(int result) {
295 transaction.setResponse(new ContextHubTransaction.Response<Void>(result, null));
296 }
297 };
298 }
299
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800300 /**
Arthur Ishiguro6c37fd02017-10-26 15:36:22 -0700301 * Helper function to generate a stub for a query transaction callback.
302 *
303 * @param transaction the transaction to unblock when complete
304 *
305 * @return the callback
306 *
307 * @hide
308 */
309 private IContextHubTransactionCallback createQueryCallback(
310 ContextHubTransaction<List<NanoAppState>> transaction) {
311 return new IContextHubTransactionCallback.Stub() {
312 @Override
313 public void onQueryResponse(int result, List<NanoAppState> nanoappList) {
314 transaction.setResponse(new ContextHubTransaction.Response<List<NanoAppState>>(
315 result, nanoappList));
316 }
317
318 @Override
319 public void onTransactionComplete(int result) {
320 Log.e(TAG, "Received a non-query callback on a query request");
321 transaction.setResponse(new ContextHubTransaction.Response<List<NanoAppState>>(
322 ContextHubTransaction.TRANSACTION_FAILED_SERVICE_INTERNAL_FAILURE, null));
323 }
324 };
325 }
326
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700327 /**
328 * Loads a nanoapp at the specified Context Hub.
329 *
330 * After the nanoapp binary is successfully loaded at the specified hub, the nanoapp will be in
331 * the enabled state.
332 *
333 * @param hubInfo the hub to load the nanoapp on
334 * @param appBinary The app binary to load
335 *
336 * @return the ContextHubTransaction of the request
337 *
338 * @see NanoAppBinary
339 *
340 * @hide
341 */
342 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
343 public ContextHubTransaction<Void> loadNanoApp(
344 ContextHubInfo hubInfo, NanoAppBinary appBinary) {
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800345 ContextHubTransaction<Void> transaction =
346 new ContextHubTransaction<>(ContextHubTransaction.TYPE_LOAD_NANOAPP);
347 IContextHubTransactionCallback callback = createTransactionCallback(transaction);
348
349 try {
350 mService.loadNanoAppOnHub(hubInfo.getId(), callback, appBinary);
351 } catch (RemoteException e) {
352 throw e.rethrowFromSystemServer();
353 }
354
355 return transaction;
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700356 }
357
358 /**
359 * Unloads a nanoapp at the specified Context Hub.
360 *
361 * @param hubInfo the hub to unload the nanoapp from
362 * @param nanoAppId the app to unload
363 *
364 * @return the ContextHubTransaction of the request
365 *
366 * @hide
367 */
368 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
369 public ContextHubTransaction<Void> unloadNanoApp(ContextHubInfo hubInfo, long nanoAppId) {
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800370 ContextHubTransaction<Void> transaction =
371 new ContextHubTransaction<>(ContextHubTransaction.TYPE_UNLOAD_NANOAPP);
372 IContextHubTransactionCallback callback = createTransactionCallback(transaction);
373
374 try {
375 mService.unloadNanoAppFromHub(hubInfo.getId(), callback, nanoAppId);
376 } catch (RemoteException e) {
377 throw e.rethrowFromSystemServer();
378 }
379
380 return transaction;
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700381 }
382
383 /**
384 * Enables a nanoapp at the specified Context Hub.
385 *
386 * @param hubInfo the hub to enable the nanoapp on
387 * @param nanoAppId the app to enable
388 *
389 * @return the ContextHubTransaction of the request
390 *
391 * @hide
392 */
393 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
394 public ContextHubTransaction<Void> enableNanoApp(ContextHubInfo hubInfo, long nanoAppId) {
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800395 ContextHubTransaction<Void> transaction =
396 new ContextHubTransaction<>(ContextHubTransaction.TYPE_ENABLE_NANOAPP);
397 IContextHubTransactionCallback callback = createTransactionCallback(transaction);
398
399 try {
400 mService.enableNanoApp(hubInfo.getId(), callback, nanoAppId);
401 } catch (RemoteException e) {
402 throw e.rethrowFromSystemServer();
403 }
404
405 return transaction;
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700406 }
407
408 /**
409 * Disables a nanoapp at the specified Context Hub.
410 *
411 * @param hubInfo the hub to disable the nanoapp on
412 * @param nanoAppId the app to disable
413 *
414 * @return the ContextHubTransaction of the request
415 *
416 * @hide
417 */
418 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
419 public ContextHubTransaction<Void> disableNanoApp(ContextHubInfo hubInfo, long nanoAppId) {
420 throw new UnsupportedOperationException("TODO: Implement this");
421 }
422
423 /**
424 * Requests a query for nanoapps loaded at the specified Context Hub.
425 *
426 * @param hubInfo the hub to query a list of nanoapps from
427 *
428 * @return the ContextHubTransaction of the request
429 *
430 * @hide
431 */
432 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
433 public ContextHubTransaction<List<NanoAppState>> queryNanoApps(ContextHubInfo hubInfo) {
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800434 ContextHubTransaction<List<NanoAppState>> transaction =
435 new ContextHubTransaction<>(ContextHubTransaction.TYPE_QUERY_NANOAPPS);
436 IContextHubTransactionCallback callback = createQueryCallback(transaction);
437
438 try {
439 mService.queryNanoApps(hubInfo.getId(), callback);
440 } catch (RemoteException e) {
441 throw e.rethrowFromSystemServer();
442 }
443
444 return transaction;
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700445 }
446
447 /**
Peng Xu9ff7d222016-02-11 13:02:05 -0800448 * Set a callback to receive messages from the context hub
449 *
Peng Xu9ff7d222016-02-11 13:02:05 -0800450 * @param callback Callback object
451 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700452 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800453 *
454 * @return int 0 on success, -1 otherwise
455 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600456 @SuppressLint("Doclava125")
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700457 public int registerCallback(Callback callback) {
458 return registerCallback(callback, null);
Peng Xu9ff7d222016-02-11 13:02:05 -0800459 }
460
461 /**
destradaa78cebca2016-04-14 18:40:14 -0700462 * @deprecated Use {@link #registerCallback(Callback)} instead.
463 * @hide
464 */
465 @Deprecated
466 public int registerCallback(ICallback callback) {
467 if (mLocalCallback != null) {
468 Log.w(TAG, "Max number of local callbacks reached!");
469 return -1;
470 }
471 mLocalCallback = callback;
472 return 0;
473 }
474
475 /**
Peng Xu9ff7d222016-02-11 13:02:05 -0800476 * Set a callback to receive messages from the context hub
477 *
Peng Xu9ff7d222016-02-11 13:02:05 -0800478 * @param callback Callback object
destradaa8bad3fe2016-03-15 12:33:40 -0700479 * @param handler Handler object
Peng Xu9ff7d222016-02-11 13:02:05 -0800480 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700481 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800482 *
483 * @return int 0 on success, -1 otherwise
484 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600485 @SuppressLint("Doclava125")
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700486 public int registerCallback(Callback callback, Handler handler) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800487 synchronized(this) {
488 if (mCallback != null) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700489 Log.w(TAG, "Max number of callbacks reached!");
Peng Xu9ff7d222016-02-11 13:02:05 -0800490 return -1;
491 }
492 mCallback = callback;
493 mCallbackHandler = handler;
494 }
495 return 0;
496 }
497
498 /**
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800499 * Creates an interface to the ContextHubClient to send down to the service.
500 *
501 * @param callback the callback to invoke at the client process
502 * @param handler the handler to post callbacks for this client
503 *
504 * @return the callback interface
505 */
506 private IContextHubClientCallback createClientCallback(
507 ContextHubClientCallback callback, Handler handler) {
508 return new IContextHubClientCallback.Stub() {
509 @Override
510 public void onMessageFromNanoApp(NanoAppMessage message) {
511 handler.post(() -> callback.onMessageFromNanoApp(message));
512 }
513
514 @Override
515 public void onHubReset() {
516 handler.post(() -> callback.onHubReset());
517 }
518
519 @Override
520 public void onNanoAppAborted(long nanoAppId, int abortCode) {
521 handler.post(() -> callback.onNanoAppAborted(nanoAppId, abortCode));
522 }
523
524 @Override
525 public void onNanoAppLoaded(long nanoAppId) {
526 handler.post(() -> callback.onNanoAppLoaded(nanoAppId));
527 }
528
529 @Override
530 public void onNanoAppUnloaded(long nanoAppId) {
531 handler.post(() -> callback.onNanoAppUnloaded(nanoAppId));
532 }
533
534 @Override
535 public void onNanoAppEnabled(long nanoAppId) {
536 handler.post(() -> callback.onNanoAppEnabled(nanoAppId));
537 }
538
539 @Override
540 public void onNanoAppDisabled(long nanoAppId) {
541 handler.post(() -> callback.onNanoAppDisabled(nanoAppId));
542 }
543 };
544 }
545
546 /**
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700547 * Creates and registers a client and its callback with the Context Hub Service.
548 *
549 * A client is registered with the Context Hub Service for a specified Context Hub. When the
550 * registration succeeds, the client can send messages to nanoapps through the returned
551 * {@link ContextHubClient} object, and receive notifications through the provided callback.
552 *
553 * @param callback the notification callback to register
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800554 * @param hubInfo the hub to attach this client to
555 * @param handler the handler to invoke the callback, if null uses the main thread's Looper
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700556 * @return the registered client object
557 *
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800558 * @throws IllegalArgumentException if hubInfo does not represent a valid hub
559 * @throws IllegalStateException if there were too many registered clients at the service
560 * @throws NullPointerException if callback or hubInfo is null
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700561 *
562 * @hide
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800563 * @see ContextHubClientCallback
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700564 */
565 public ContextHubClient createClient(
566 ContextHubClientCallback callback, ContextHubInfo hubInfo, @Nullable Handler handler) {
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800567 if (callback == null) {
568 throw new NullPointerException("Callback cannot be null");
569 }
570 if (hubInfo == null) {
571 throw new NullPointerException("Hub info cannot be null");
572 }
573
574 Handler realHandler = (handler == null) ? new Handler(mMainLooper) : handler;
575 IContextHubClientCallback clientInterface = createClientCallback(callback, realHandler);
576
577 IContextHubClient client;
578 try {
579 client = mService.createClient(clientInterface, hubInfo.getId());
580 } catch (RemoteException e) {
581 throw e.rethrowFromSystemServer();
582 }
583
584 return new ContextHubClient(client, clientInterface, hubInfo);
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700585 }
586
587 /**
destradaa8bad3fe2016-03-15 12:33:40 -0700588 * Unregister a callback for receive messages from the context hub.
Peng Xu9ff7d222016-02-11 13:02:05 -0800589 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700590 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800591 *
592 * @param callback method to deregister
593 *
594 * @return int 0 on success, -1 otherwise
595 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600596 @SuppressLint("Doclava125")
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700597 public int unregisterCallback(Callback callback) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800598 synchronized(this) {
599 if (callback != mCallback) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700600 Log.w(TAG, "Cannot recognize callback!");
Peng Xu9ff7d222016-02-11 13:02:05 -0800601 return -1;
602 }
603
604 mCallback = null;
605 mCallbackHandler = null;
606 }
607 return 0;
608 }
609
destradaa78cebca2016-04-14 18:40:14 -0700610 /**
611 * @deprecated Use {@link #unregisterCallback(Callback)} instead.
612 * @hide
613 */
Aurimas Liutikas514c5ef2016-05-24 15:22:55 -0700614 @Deprecated
destradaa78cebca2016-04-14 18:40:14 -0700615 public synchronized int unregisterCallback(ICallback callback) {
616 if (callback != mLocalCallback) {
617 Log.w(TAG, "Cannot recognize local callback!");
618 return -1;
619 }
620 mLocalCallback = null;
621 return 0;
622 }
623
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600624 private final IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800625 @Override
Peng Xu9ff7d222016-02-11 13:02:05 -0800626 public void onMessageReceipt(final int hubId, final int nanoAppId,
destradaa8bad3fe2016-03-15 12:33:40 -0700627 final ContextHubMessage message) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800628 if (mCallback != null) {
629 synchronized(this) {
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700630 final Callback callback = mCallback;
Peng Xu9ff7d222016-02-11 13:02:05 -0800631 Handler handler = mCallbackHandler == null ?
632 new Handler(mMainLooper) : mCallbackHandler;
633 handler.post(new Runnable() {
634 @Override
635 public void run() {
636 callback.onMessageReceipt(hubId, nanoAppId, message);
637 }
638 });
639 }
destradaa78cebca2016-04-14 18:40:14 -0700640 } else if (mLocalCallback != null) {
641 // we always ensure that mCallback takes precedence, because mLocalCallback is only
642 // for internal compatibility
643 synchronized (this) {
644 mLocalCallback.onMessageReceipt(hubId, nanoAppId, message);
645 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800646 } else {
647 Log.d(TAG, "Context hub manager client callback is NULL");
648 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800649 }
650 };
651
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600652 /** @throws ServiceNotFoundException
653 * @hide */
654 public ContextHubManager(Context context, Looper mainLooper) throws ServiceNotFoundException {
Peng Xu9ff7d222016-02-11 13:02:05 -0800655 mMainLooper = mainLooper;
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600656 mService = IContextHubService.Stub.asInterface(
Ashutosh Joshi420e45e2016-12-20 16:34:41 -0800657 ServiceManager.getServiceOrThrow(Context.CONTEXTHUB_SERVICE));
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600658 try {
659 mService.registerCallback(mClientCallback);
660 } catch (RemoteException e) {
661 Log.w(TAG, "Could not register callback:" + e);
Peng Xu9ff7d222016-02-11 13:02:05 -0800662 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800663 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800664}