blob: b31c7bcdb31e58aa61b8af0f8cef897ec9e1f784 [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 Ishiguro6c37fd02017-10-26 15:36:22 -0700274 /*
275 * 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
300 /*
301 * 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) {
345 throw new UnsupportedOperationException("TODO: Implement this");
346 }
347
348 /**
349 * Unloads a nanoapp at the specified Context Hub.
350 *
351 * @param hubInfo the hub to unload the nanoapp from
352 * @param nanoAppId the app to unload
353 *
354 * @return the ContextHubTransaction of the request
355 *
356 * @hide
357 */
358 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
359 public ContextHubTransaction<Void> unloadNanoApp(ContextHubInfo hubInfo, long nanoAppId) {
360 throw new UnsupportedOperationException("TODO: Implement this");
361 }
362
363 /**
364 * Enables a nanoapp at the specified Context Hub.
365 *
366 * @param hubInfo the hub to enable the nanoapp on
367 * @param nanoAppId the app to enable
368 *
369 * @return the ContextHubTransaction of the request
370 *
371 * @hide
372 */
373 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
374 public ContextHubTransaction<Void> enableNanoApp(ContextHubInfo hubInfo, long nanoAppId) {
375 throw new UnsupportedOperationException("TODO: Implement this");
376 }
377
378 /**
379 * Disables a nanoapp at the specified Context Hub.
380 *
381 * @param hubInfo the hub to disable the nanoapp on
382 * @param nanoAppId the app to disable
383 *
384 * @return the ContextHubTransaction of the request
385 *
386 * @hide
387 */
388 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
389 public ContextHubTransaction<Void> disableNanoApp(ContextHubInfo hubInfo, long nanoAppId) {
390 throw new UnsupportedOperationException("TODO: Implement this");
391 }
392
393 /**
394 * Requests a query for nanoapps loaded at the specified Context Hub.
395 *
396 * @param hubInfo the hub to query a list of nanoapps from
397 *
398 * @return the ContextHubTransaction of the request
399 *
400 * @hide
401 */
402 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
403 public ContextHubTransaction<List<NanoAppState>> queryNanoApps(ContextHubInfo hubInfo) {
404 throw new UnsupportedOperationException("TODO: Implement this");
405 }
406
407 /**
Peng Xu9ff7d222016-02-11 13:02:05 -0800408 * Set a callback to receive messages from the context hub
409 *
Peng Xu9ff7d222016-02-11 13:02:05 -0800410 * @param callback Callback object
411 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700412 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800413 *
414 * @return int 0 on success, -1 otherwise
415 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600416 @SuppressLint("Doclava125")
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700417 public int registerCallback(Callback callback) {
418 return registerCallback(callback, null);
Peng Xu9ff7d222016-02-11 13:02:05 -0800419 }
420
421 /**
destradaa78cebca2016-04-14 18:40:14 -0700422 * @deprecated Use {@link #registerCallback(Callback)} instead.
423 * @hide
424 */
425 @Deprecated
426 public int registerCallback(ICallback callback) {
427 if (mLocalCallback != null) {
428 Log.w(TAG, "Max number of local callbacks reached!");
429 return -1;
430 }
431 mLocalCallback = callback;
432 return 0;
433 }
434
435 /**
Peng Xu9ff7d222016-02-11 13:02:05 -0800436 * Set a callback to receive messages from the context hub
437 *
Peng Xu9ff7d222016-02-11 13:02:05 -0800438 * @param callback Callback object
destradaa8bad3fe2016-03-15 12:33:40 -0700439 * @param handler Handler object
Peng Xu9ff7d222016-02-11 13:02:05 -0800440 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700441 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800442 *
443 * @return int 0 on success, -1 otherwise
444 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600445 @SuppressLint("Doclava125")
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700446 public int registerCallback(Callback callback, Handler handler) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800447 synchronized(this) {
448 if (mCallback != null) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700449 Log.w(TAG, "Max number of callbacks reached!");
Peng Xu9ff7d222016-02-11 13:02:05 -0800450 return -1;
451 }
452 mCallback = callback;
453 mCallbackHandler = handler;
454 }
455 return 0;
456 }
457
458 /**
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800459 * Creates an interface to the ContextHubClient to send down to the service.
460 *
461 * @param callback the callback to invoke at the client process
462 * @param handler the handler to post callbacks for this client
463 *
464 * @return the callback interface
465 */
466 private IContextHubClientCallback createClientCallback(
467 ContextHubClientCallback callback, Handler handler) {
468 return new IContextHubClientCallback.Stub() {
469 @Override
470 public void onMessageFromNanoApp(NanoAppMessage message) {
471 handler.post(() -> callback.onMessageFromNanoApp(message));
472 }
473
474 @Override
475 public void onHubReset() {
476 handler.post(() -> callback.onHubReset());
477 }
478
479 @Override
480 public void onNanoAppAborted(long nanoAppId, int abortCode) {
481 handler.post(() -> callback.onNanoAppAborted(nanoAppId, abortCode));
482 }
483
484 @Override
485 public void onNanoAppLoaded(long nanoAppId) {
486 handler.post(() -> callback.onNanoAppLoaded(nanoAppId));
487 }
488
489 @Override
490 public void onNanoAppUnloaded(long nanoAppId) {
491 handler.post(() -> callback.onNanoAppUnloaded(nanoAppId));
492 }
493
494 @Override
495 public void onNanoAppEnabled(long nanoAppId) {
496 handler.post(() -> callback.onNanoAppEnabled(nanoAppId));
497 }
498
499 @Override
500 public void onNanoAppDisabled(long nanoAppId) {
501 handler.post(() -> callback.onNanoAppDisabled(nanoAppId));
502 }
503 };
504 }
505
506 /**
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700507 * Creates and registers a client and its callback with the Context Hub Service.
508 *
509 * A client is registered with the Context Hub Service for a specified Context Hub. When the
510 * registration succeeds, the client can send messages to nanoapps through the returned
511 * {@link ContextHubClient} object, and receive notifications through the provided callback.
512 *
513 * @param callback the notification callback to register
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800514 * @param hubInfo the hub to attach this client to
515 * @param handler the handler to invoke the callback, if null uses the main thread's Looper
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700516 * @return the registered client object
517 *
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800518 * @throws IllegalArgumentException if hubInfo does not represent a valid hub
519 * @throws IllegalStateException if there were too many registered clients at the service
520 * @throws NullPointerException if callback or hubInfo is null
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700521 *
522 * @hide
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800523 * @see ContextHubClientCallback
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700524 */
525 public ContextHubClient createClient(
526 ContextHubClientCallback callback, ContextHubInfo hubInfo, @Nullable Handler handler) {
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800527 if (callback == null) {
528 throw new NullPointerException("Callback cannot be null");
529 }
530 if (hubInfo == null) {
531 throw new NullPointerException("Hub info cannot be null");
532 }
533
534 Handler realHandler = (handler == null) ? new Handler(mMainLooper) : handler;
535 IContextHubClientCallback clientInterface = createClientCallback(callback, realHandler);
536
537 IContextHubClient client;
538 try {
539 client = mService.createClient(clientInterface, hubInfo.getId());
540 } catch (RemoteException e) {
541 throw e.rethrowFromSystemServer();
542 }
543
544 return new ContextHubClient(client, clientInterface, hubInfo);
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700545 }
546
547 /**
destradaa8bad3fe2016-03-15 12:33:40 -0700548 * Unregister a callback for receive messages from the context hub.
Peng Xu9ff7d222016-02-11 13:02:05 -0800549 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700550 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800551 *
552 * @param callback method to deregister
553 *
554 * @return int 0 on success, -1 otherwise
555 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600556 @SuppressLint("Doclava125")
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700557 public int unregisterCallback(Callback callback) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800558 synchronized(this) {
559 if (callback != mCallback) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700560 Log.w(TAG, "Cannot recognize callback!");
Peng Xu9ff7d222016-02-11 13:02:05 -0800561 return -1;
562 }
563
564 mCallback = null;
565 mCallbackHandler = null;
566 }
567 return 0;
568 }
569
destradaa78cebca2016-04-14 18:40:14 -0700570 /**
571 * @deprecated Use {@link #unregisterCallback(Callback)} instead.
572 * @hide
573 */
Aurimas Liutikas514c5ef2016-05-24 15:22:55 -0700574 @Deprecated
destradaa78cebca2016-04-14 18:40:14 -0700575 public synchronized int unregisterCallback(ICallback callback) {
576 if (callback != mLocalCallback) {
577 Log.w(TAG, "Cannot recognize local callback!");
578 return -1;
579 }
580 mLocalCallback = null;
581 return 0;
582 }
583
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600584 private final IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800585 @Override
Peng Xu9ff7d222016-02-11 13:02:05 -0800586 public void onMessageReceipt(final int hubId, final int nanoAppId,
destradaa8bad3fe2016-03-15 12:33:40 -0700587 final ContextHubMessage message) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800588 if (mCallback != null) {
589 synchronized(this) {
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700590 final Callback callback = mCallback;
Peng Xu9ff7d222016-02-11 13:02:05 -0800591 Handler handler = mCallbackHandler == null ?
592 new Handler(mMainLooper) : mCallbackHandler;
593 handler.post(new Runnable() {
594 @Override
595 public void run() {
596 callback.onMessageReceipt(hubId, nanoAppId, message);
597 }
598 });
599 }
destradaa78cebca2016-04-14 18:40:14 -0700600 } else if (mLocalCallback != null) {
601 // we always ensure that mCallback takes precedence, because mLocalCallback is only
602 // for internal compatibility
603 synchronized (this) {
604 mLocalCallback.onMessageReceipt(hubId, nanoAppId, message);
605 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800606 } else {
607 Log.d(TAG, "Context hub manager client callback is NULL");
608 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800609 }
610 };
611
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600612 /** @throws ServiceNotFoundException
613 * @hide */
614 public ContextHubManager(Context context, Looper mainLooper) throws ServiceNotFoundException {
Peng Xu9ff7d222016-02-11 13:02:05 -0800615 mMainLooper = mainLooper;
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600616 mService = IContextHubService.Stub.asInterface(
Ashutosh Joshi420e45e2016-12-20 16:34:41 -0800617 ServiceManager.getServiceOrThrow(Context.CONTEXTHUB_SERVICE));
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600618 try {
619 mService.registerCallback(mClientCallback);
620 } catch (RemoteException e) {
621 Log.w(TAG, "Could not register callback:" + e);
Peng Xu9ff7d222016-02-11 13:02:05 -0800622 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800623 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800624}