blob: be1efdea0260af5c65c5f139564cccd19bf62be5 [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 Ishiguroe35a6de2017-12-20 15:30:51 -080018import android.annotation.CallbackExecutor;
19import android.annotation.NonNull;
Arthur Ishiguroac7b9592018-01-02 09:46:42 -080020import android.annotation.Nullable;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060021import android.annotation.RequiresPermission;
22import android.annotation.SuppressLint;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080023import android.annotation.SystemApi;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060024import android.annotation.SystemService;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080025import android.content.Context;
Peng Xu9ff7d222016-02-11 13:02:05 -080026import android.os.Handler;
Arthur Ishiguro9b9c9d82017-12-20 16:11:53 -080027import android.os.HandlerExecutor;
Peng Xu9ff7d222016-02-11 13:02:05 -080028import android.os.Looper;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080029import android.os.RemoteException;
Peng Xu9ff7d222016-02-11 13:02:05 -080030import android.os.ServiceManager;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060031import android.os.ServiceManager.ServiceNotFoundException;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080032import android.util.Log;
33
Arthur Ishiguroac7b9592018-01-02 09:46:42 -080034import com.android.internal.util.Preconditions;
35
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -070036import java.util.List;
Arthur Ishiguroe35a6de2017-12-20 15:30:51 -080037import java.util.concurrent.Executor;
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -070038
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080039/**
destradaa8bad3fe2016-03-15 12:33:40 -070040 * A class that exposes the Context hubs on a device to applications.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080041 *
destradaa8bad3fe2016-03-15 12:33:40 -070042 * Please note that this class is not expected to be used by unbundled applications. Also, calling
43 * applications are expected to have LOCATION_HARDWARE permissions to use this class.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080044 *
45 * @hide
46 */
47@SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060048@SystemService(Context.CONTEXTHUB_SERVICE)
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080049public final class ContextHubManager {
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080050 private static final String TAG = "ContextHubManager";
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080051
Peng Xu9ff7d222016-02-11 13:02:05 -080052 private final Looper mMainLooper;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060053 private final IContextHubService mService;
Greg Kaiser6ba60e62016-03-18 10:08:39 -070054 private Callback mCallback;
Peng Xu9ff7d222016-02-11 13:02:05 -080055 private Handler mCallbackHandler;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080056
57 /**
destradaa78cebca2016-04-14 18:40:14 -070058 * @deprecated Use {@code mCallback} instead.
59 */
60 @Deprecated
61 private ICallback mLocalCallback;
62
63 /**
destradaa8bad3fe2016-03-15 12:33:40 -070064 * An interface to receive asynchronous communication from the context hub.
Arthur Ishigurof2b6f012017-11-28 15:21:38 -080065 *
66 * @deprecated Use the more refined {@link android.hardware.location.ContextHubClientCallback}
67 * instead for notification callbacks.
Peng Xu9ff7d222016-02-11 13:02:05 -080068 */
Arthur Ishigurof2b6f012017-11-28 15:21:38 -080069 @Deprecated
Greg Kaiser6ba60e62016-03-18 10:08:39 -070070 public abstract static class Callback {
71 protected Callback() {}
destradaa8bad3fe2016-03-15 12:33:40 -070072
Peng Xu9ff7d222016-02-11 13:02:05 -080073 /**
destradaa8bad3fe2016-03-15 12:33:40 -070074 * Callback function called on message receipt from context hub.
Peng Xu9ff7d222016-02-11 13:02:05 -080075 *
destradaa8bad3fe2016-03-15 12:33:40 -070076 * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070077 * @param nanoAppHandle Handle (unique identifier) for app instance that sent the message.
destradaa8bad3fe2016-03-15 12:33:40 -070078 * @param message The context hub message.
Peng Xu9ff7d222016-02-11 13:02:05 -080079 *
80 * @see ContextHubMessage
81 */
destradaa8bad3fe2016-03-15 12:33:40 -070082 public abstract void onMessageReceipt(
83 int hubHandle,
84 int nanoAppHandle,
Arthur Ishiguroac7b9592018-01-02 09:46:42 -080085 @NonNull ContextHubMessage message);
Peng Xu9ff7d222016-02-11 13:02:05 -080086 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080087
88 /**
destradaa78cebca2016-04-14 18:40:14 -070089 * @deprecated Use {@link Callback} instead.
90 * @hide
91 */
92 @Deprecated
93 public interface ICallback {
94 /**
95 * Callback function called on message receipt from context hub.
96 *
97 * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
98 * @param nanoAppHandle Handle (unique identifier) for app instance that sent the message.
99 * @param message The context hub message.
100 *
101 * @see ContextHubMessage
102 */
103 void onMessageReceipt(int hubHandle, int nanoAppHandle, ContextHubMessage message);
104 }
105
106 /**
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800107 * Get a handle to all the context hubs in the system
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800108 *
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800109 * @return array of context hub handles
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800110 *
111 * @deprecated Use {@link #getContextHubs()} instead. The use of handles are deprecated in the
112 * new APIs.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800113 */
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800114 @Deprecated
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600115 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Peng Xu9ff7d222016-02-11 13:02:05 -0800116 public int[] getContextHubHandles() {
Peng Xu9ff7d222016-02-11 13:02:05 -0800117 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600118 return mService.getContextHubHandles();
Peng Xu9ff7d222016-02-11 13:02:05 -0800119 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600120 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800121 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800122 }
123
124 /**
125 * Get more information about a specific hub.
126 *
destradaa8bad3fe2016-03-15 12:33:40 -0700127 * @param hubHandle Handle (system-wide unique identifier) of a context hub.
128 * @return ContextHubInfo Information about the requested context hub.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800129 *
130 * @see ContextHubInfo
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800131 *
132 * @deprecated Use {@link #getContextHubs()} instead. The use of handles are deprecated in the
133 * new APIs.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800134 */
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800135 @Deprecated
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600136 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
destradaa8bad3fe2016-03-15 12:33:40 -0700137 public ContextHubInfo getContextHubInfo(int hubHandle) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800138 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600139 return mService.getContextHubInfo(hubHandle);
Peng Xu9ff7d222016-02-11 13:02:05 -0800140 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600141 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800142 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800143 }
144
145 /**
destradaa8bad3fe2016-03-15 12:33:40 -0700146 * Load a nano app on a specified context hub.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800147 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700148 * Note that loading is asynchronous. When we return from this method,
149 * the nano app (probably) hasn't loaded yet. Assuming a return of 0
150 * from this method, then the final success/failure for the load, along
151 * with the "handle" for the nanoapp, is all delivered in a byte
152 * string via a call to Callback.onMessageReceipt.
153 *
154 * TODO(b/30784270): Provide a better success/failure and "handle" delivery.
155 *
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800156 * @param hubHandle handle of context hub to load the app on.
157 * @param app the nanoApp to load on the hub
158 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700159 * @return 0 if the command for loading was sent to the context hub;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800160 * -1 otherwise
161 *
162 * @see NanoApp
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800163 *
164 * @deprecated Use {@link #loadNanoApp(ContextHubInfo, NanoAppBinary)} instead.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800165 */
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800166 @Deprecated
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600167 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800168 public int loadNanoApp(int hubHandle, @NonNull NanoApp app) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800169 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600170 return mService.loadNanoApp(hubHandle, app);
Peng Xu9ff7d222016-02-11 13:02:05 -0800171 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600172 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800173 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800174 }
175
176 /**
177 * Unload a specified nanoApp
178 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700179 * Note that unloading is asynchronous. When we return from this method,
180 * the nano app (probably) hasn't unloaded yet. Assuming a return of 0
181 * from this method, then the final success/failure for the unload is
182 * delivered in a byte string via a call to Callback.onMessageReceipt.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800183 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700184 * TODO(b/30784270): Provide a better success/failure delivery.
185 *
186 * @param nanoAppHandle handle of the nanoApp to unload
187 *
188 * @return 0 if the command for unloading was sent to the context hub;
189 * -1 otherwise
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800190 *
191 * @deprecated Use {@link #unloadNanoApp(ContextHubInfo, long)} instead.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800192 */
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800193 @Deprecated
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600194 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
destradaa8bad3fe2016-03-15 12:33:40 -0700195 public int unloadNanoApp(int nanoAppHandle) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800196 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600197 return mService.unloadNanoApp(nanoAppHandle);
Peng Xu9ff7d222016-02-11 13:02:05 -0800198 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600199 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800200 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800201 }
202
203 /**
204 * get information about the nano app instance
205 *
Greg Kaiser3be73d32016-08-18 10:13:52 -0700206 * NOTE: The returned NanoAppInstanceInfo does _not_ contain correct
207 * information for several fields, specifically:
208 * - getName()
209 * - getPublisher()
210 * - getNeededExecMemBytes()
211 * - getNeededReadMemBytes()
212 * - getNeededWriteMemBytes()
213 *
214 * For example, say you call loadNanoApp() with a NanoApp that has
215 * getName() returning "My Name". Later, if you call getNanoAppInstanceInfo
216 * for that nanoapp, the returned NanoAppInstanceInfo's getName()
217 * method will claim "Preloaded app, unknown", even though you would
218 * have expected "My Name". For now, as the user, you'll need to
219 * separately track the above fields if they are of interest to you.
220 *
221 * TODO(b/30943489): Have the returned NanoAppInstanceInfo contain the
222 * correct information.
223 *
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800224 * @param nanoAppHandle handle of the nanoapp instance
225 * @return NanoAppInstanceInfo the NanoAppInstanceInfo of the nanoapp, or null if the nanoapp
226 * does not exist
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800227 *
228 * @see NanoAppInstanceInfo
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800229 *
230 * @deprecated Use {@link #queryNanoApps(ContextHubInfo)} instead to explicitly query the hub
231 * for loaded nanoapps.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800232 */
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800233 @Deprecated
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600234 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800235 @Nullable public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800236 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600237 return mService.getNanoAppInstanceInfo(nanoAppHandle);
Peng Xu9ff7d222016-02-11 13:02:05 -0800238 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600239 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800240 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800241 }
242
243 /**
244 * Find a specified nano app on the system
245 *
246 * @param hubHandle handle of hub to search for nano app
247 * @param filter filter specifying the search criteria for app
248 *
249 * @see NanoAppFilter
250 *
destradaa8bad3fe2016-03-15 12:33:40 -0700251 * @return int[] Array of handles to any found nano apps
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800252 *
253 * @deprecated Use {@link #queryNanoApps(ContextHubInfo)} instead to explicitly query the hub
254 * for loaded nanoapps.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800255 */
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800256 @Deprecated
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600257 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800258 @NonNull public int[] findNanoAppOnHub(int hubHandle, @NonNull NanoAppFilter filter) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800259 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600260 return mService.findNanoAppOnHub(hubHandle, filter);
Peng Xu9ff7d222016-02-11 13:02:05 -0800261 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600262 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800263 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800264 }
265
266 /**
destradaa8bad3fe2016-03-15 12:33:40 -0700267 * Send a message to a specific nano app instance on a context hub.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800268 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700269 * Note that the return value of this method only speaks of success
270 * up to the point of sending this to the Context Hub. It is not
271 * an assurance that the Context Hub successfully sent this message
272 * on to the nanoapp. If assurance is desired, a protocol should be
273 * established between your code and the nanoapp, with the nanoapp
274 * sending a confirmation message (which will be reported via
275 * Callback.onMessageReceipt).
276 *
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800277 * @param hubHandle handle of the hub to send the message to
278 * @param nanoAppHandle handle of the nano app to send to
destradaa8bad3fe2016-03-15 12:33:40 -0700279 * @param message Message to be sent
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800280 *
281 * @see ContextHubMessage
282 *
283 * @return int 0 on success, -1 otherwise
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800284 *
285 * @deprecated Use {@link android.hardware.location.ContextHubClient#sendMessageToNanoApp(
286 * NanoAppMessage)} instead, after creating a
287 * {@link android.hardware.location.ContextHubClient} with
288 * {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)}
289 * or {@link #createClient(ContextHubInfo, ContextHubClientCallback)}.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800290 */
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800291 @Deprecated
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600292 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800293 public int sendMessage(int hubHandle, int nanoAppHandle, @NonNull ContextHubMessage message) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800294 try {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600295 return mService.sendMessage(hubHandle, nanoAppHandle, message);
Peng Xu9ff7d222016-02-11 13:02:05 -0800296 } catch (RemoteException e) {
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600297 throw e.rethrowFromSystemServer();
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800298 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800299 }
300
Peng Xu9ff7d222016-02-11 13:02:05 -0800301 /**
Arthur Ishigurofdbbd462017-11-27 16:33:36 -0800302 * Returns the list of ContextHubInfo objects describing the available Context Hubs.
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700303 *
Arthur Ishigurofdbbd462017-11-27 16:33:36 -0800304 * @return the list of ContextHubInfo objects
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700305 *
306 * @see ContextHubInfo
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700307 */
308 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800309 @NonNull public List<ContextHubInfo> getContextHubs() {
Arthur Ishigurofdbbd462017-11-27 16:33:36 -0800310 try {
311 return mService.getContextHubs();
312 } catch (RemoteException e) {
313 throw e.rethrowFromSystemServer();
314 }
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700315 }
316
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800317 /**
Arthur Ishiguro6c37fd02017-10-26 15:36:22 -0700318 * Helper function to generate a stub for a non-query transaction callback.
319 *
320 * @param transaction the transaction to unblock when complete
321 *
322 * @return the callback
323 *
324 * @hide
325 */
326 private IContextHubTransactionCallback createTransactionCallback(
327 ContextHubTransaction<Void> transaction) {
328 return new IContextHubTransactionCallback.Stub() {
329 @Override
330 public void onQueryResponse(int result, List<NanoAppState> nanoappList) {
331 Log.e(TAG, "Received a query callback on a non-query request");
332 transaction.setResponse(new ContextHubTransaction.Response<Void>(
Arthur Ishiguro6100aa72017-12-20 09:35:00 -0800333 ContextHubTransaction.RESULT_FAILED_SERVICE_INTERNAL_FAILURE, null));
Arthur Ishiguro6c37fd02017-10-26 15:36:22 -0700334 }
335
336 @Override
337 public void onTransactionComplete(int result) {
338 transaction.setResponse(new ContextHubTransaction.Response<Void>(result, null));
339 }
340 };
341 }
342
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800343 /**
Arthur Ishiguro6c37fd02017-10-26 15:36:22 -0700344 * Helper function to generate a stub for a query transaction callback.
345 *
346 * @param transaction the transaction to unblock when complete
347 *
348 * @return the callback
349 *
350 * @hide
351 */
352 private IContextHubTransactionCallback createQueryCallback(
353 ContextHubTransaction<List<NanoAppState>> transaction) {
354 return new IContextHubTransactionCallback.Stub() {
355 @Override
356 public void onQueryResponse(int result, List<NanoAppState> nanoappList) {
357 transaction.setResponse(new ContextHubTransaction.Response<List<NanoAppState>>(
358 result, nanoappList));
359 }
360
361 @Override
362 public void onTransactionComplete(int result) {
363 Log.e(TAG, "Received a non-query callback on a query request");
364 transaction.setResponse(new ContextHubTransaction.Response<List<NanoAppState>>(
Arthur Ishiguro6100aa72017-12-20 09:35:00 -0800365 ContextHubTransaction.RESULT_FAILED_SERVICE_INTERNAL_FAILURE, null));
Arthur Ishiguro6c37fd02017-10-26 15:36:22 -0700366 }
367 };
368 }
369
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700370 /**
371 * Loads a nanoapp at the specified Context Hub.
372 *
373 * After the nanoapp binary is successfully loaded at the specified hub, the nanoapp will be in
374 * the enabled state.
375 *
376 * @param hubInfo the hub to load the nanoapp on
377 * @param appBinary The app binary to load
378 *
379 * @return the ContextHubTransaction of the request
380 *
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800381 * @throws NullPointerException if hubInfo or NanoAppBinary is null
382 *
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700383 * @see NanoAppBinary
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700384 */
385 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800386 @NonNull public ContextHubTransaction<Void> loadNanoApp(
387 @NonNull ContextHubInfo hubInfo, @NonNull NanoAppBinary appBinary) {
388 Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
389 Preconditions.checkNotNull(appBinary, "NanoAppBinary cannot be null");
390
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800391 ContextHubTransaction<Void> transaction =
392 new ContextHubTransaction<>(ContextHubTransaction.TYPE_LOAD_NANOAPP);
393 IContextHubTransactionCallback callback = createTransactionCallback(transaction);
394
395 try {
396 mService.loadNanoAppOnHub(hubInfo.getId(), callback, appBinary);
397 } catch (RemoteException e) {
398 throw e.rethrowFromSystemServer();
399 }
400
401 return transaction;
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700402 }
403
404 /**
405 * Unloads a nanoapp at the specified Context Hub.
406 *
407 * @param hubInfo the hub to unload the nanoapp from
408 * @param nanoAppId the app to unload
409 *
410 * @return the ContextHubTransaction of the request
411 *
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800412 * @throws NullPointerException if hubInfo is null
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700413 */
414 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800415 @NonNull public ContextHubTransaction<Void> unloadNanoApp(
416 @NonNull ContextHubInfo hubInfo, long nanoAppId) {
417 Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
418
Arthur Ishiguroe1ade432017-11-27 10:45:33 -0800419 ContextHubTransaction<Void> transaction =
420 new ContextHubTransaction<>(ContextHubTransaction.TYPE_UNLOAD_NANOAPP);
421 IContextHubTransactionCallback callback = createTransactionCallback(transaction);
422
423 try {
424 mService.unloadNanoAppFromHub(hubInfo.getId(), callback, nanoAppId);
425 } catch (RemoteException e) {
426 throw e.rethrowFromSystemServer();
427 }
428
429 return transaction;
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700430 }
431
432 /**
433 * Enables a nanoapp at the specified Context Hub.
434 *
435 * @param hubInfo the hub to enable the nanoapp on
436 * @param nanoAppId the app to enable
437 *
438 * @return the ContextHubTransaction of the request
439 *
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800440 * @throws NullPointerException if hubInfo is null
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700441 */
442 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800443 @NonNull public ContextHubTransaction<Void> enableNanoApp(
444 @NonNull ContextHubInfo hubInfo, long nanoAppId) {
445 Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
446
Arthur Ishiguro0ed545c2017-12-12 15:01:32 -0800447 ContextHubTransaction<Void> transaction =
448 new ContextHubTransaction<>(ContextHubTransaction.TYPE_ENABLE_NANOAPP);
449 IContextHubTransactionCallback callback = createTransactionCallback(transaction);
450
451 try {
452 mService.enableNanoApp(hubInfo.getId(), callback, nanoAppId);
453 } catch (RemoteException e) {
454 throw e.rethrowFromSystemServer();
455 }
456
457 return transaction;
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700458 }
459
460 /**
461 * Disables a nanoapp at the specified Context Hub.
462 *
463 * @param hubInfo the hub to disable the nanoapp on
464 * @param nanoAppId the app to disable
465 *
466 * @return the ContextHubTransaction of the request
467 *
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800468 * @throws NullPointerException if hubInfo is null
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700469 */
470 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800471 @NonNull public ContextHubTransaction<Void> disableNanoApp(
472 @NonNull ContextHubInfo hubInfo, long nanoAppId) {
473 Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
474
Arthur Ishiguro54e1a892017-12-12 15:09:31 -0800475 ContextHubTransaction<Void> transaction =
476 new ContextHubTransaction<>(ContextHubTransaction.TYPE_DISABLE_NANOAPP);
477 IContextHubTransactionCallback callback = createTransactionCallback(transaction);
478
479 try {
480 mService.disableNanoApp(hubInfo.getId(), callback, nanoAppId);
481 } catch (RemoteException e) {
482 throw e.rethrowFromSystemServer();
483 }
484
485 return transaction;
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700486 }
487
488 /**
489 * Requests a query for nanoapps loaded at the specified Context Hub.
490 *
491 * @param hubInfo the hub to query a list of nanoapps from
492 *
493 * @return the ContextHubTransaction of the request
494 *
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800495 * @throws NullPointerException if hubInfo is null
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700496 */
497 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800498 @NonNull public ContextHubTransaction<List<NanoAppState>> queryNanoApps(
499 @NonNull ContextHubInfo hubInfo) {
500 Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
501
Arthur Ishiguro4493e142017-11-27 16:26:34 -0800502 ContextHubTransaction<List<NanoAppState>> transaction =
503 new ContextHubTransaction<>(ContextHubTransaction.TYPE_QUERY_NANOAPPS);
504 IContextHubTransactionCallback callback = createQueryCallback(transaction);
505
506 try {
507 mService.queryNanoApps(hubInfo.getId(), callback);
508 } catch (RemoteException e) {
509 throw e.rethrowFromSystemServer();
510 }
511
512 return transaction;
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700513 }
514
515 /**
Peng Xu9ff7d222016-02-11 13:02:05 -0800516 * Set a callback to receive messages from the context hub
517 *
Peng Xu9ff7d222016-02-11 13:02:05 -0800518 * @param callback Callback object
519 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700520 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800521 *
522 * @return int 0 on success, -1 otherwise
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800523 *
524 * @deprecated Use {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)}
525 * or {@link #createClient(ContextHubInfo, ContextHubClientCallback)} instead to
526 * register a {@link android.hardware.location.ContextHubClientCallback}.
Peng Xu9ff7d222016-02-11 13:02:05 -0800527 */
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800528 @Deprecated
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600529 @SuppressLint("Doclava125")
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800530 public int registerCallback(@NonNull Callback callback) {
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700531 return registerCallback(callback, null);
Peng Xu9ff7d222016-02-11 13:02:05 -0800532 }
533
534 /**
destradaa78cebca2016-04-14 18:40:14 -0700535 * @deprecated Use {@link #registerCallback(Callback)} instead.
536 * @hide
537 */
538 @Deprecated
539 public int registerCallback(ICallback callback) {
540 if (mLocalCallback != null) {
541 Log.w(TAG, "Max number of local callbacks reached!");
542 return -1;
543 }
544 mLocalCallback = callback;
545 return 0;
546 }
547
548 /**
Peng Xu9ff7d222016-02-11 13:02:05 -0800549 * Set a callback to receive messages from the context hub
550 *
Peng Xu9ff7d222016-02-11 13:02:05 -0800551 * @param callback Callback object
destradaa8bad3fe2016-03-15 12:33:40 -0700552 * @param handler Handler object
Peng Xu9ff7d222016-02-11 13:02:05 -0800553 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700554 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800555 *
556 * @return int 0 on success, -1 otherwise
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800557 *
558 * @deprecated Use {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)}
559 * or {@link #createClient(ContextHubInfo, ContextHubClientCallback)} instead to
560 * register a {@link android.hardware.location.ContextHubClientCallback}.
Peng Xu9ff7d222016-02-11 13:02:05 -0800561 */
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800562 @Deprecated
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600563 @SuppressLint("Doclava125")
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700564 public int registerCallback(Callback callback, Handler handler) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800565 synchronized(this) {
566 if (mCallback != null) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700567 Log.w(TAG, "Max number of callbacks reached!");
Peng Xu9ff7d222016-02-11 13:02:05 -0800568 return -1;
569 }
570 mCallback = callback;
571 mCallbackHandler = handler;
572 }
573 return 0;
574 }
575
576 /**
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800577 * Creates an interface to the ContextHubClient to send down to the service.
578 *
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800579 * @param client the ContextHubClient object associated with this callback
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800580 * @param callback the callback to invoke at the client process
Arthur Ishiguroe35a6de2017-12-20 15:30:51 -0800581 * @param executor the executor to invoke callbacks for this client
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800582 *
583 * @return the callback interface
584 */
585 private IContextHubClientCallback createClientCallback(
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800586 ContextHubClient client, ContextHubClientCallback callback, Executor executor) {
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800587 return new IContextHubClientCallback.Stub() {
588 @Override
589 public void onMessageFromNanoApp(NanoAppMessage message) {
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800590 executor.execute(() -> callback.onMessageFromNanoApp(client, message));
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800591 }
592
593 @Override
594 public void onHubReset() {
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800595 executor.execute(() -> callback.onHubReset(client));
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800596 }
597
598 @Override
599 public void onNanoAppAborted(long nanoAppId, int abortCode) {
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800600 executor.execute(() -> callback.onNanoAppAborted(client, nanoAppId, abortCode));
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800601 }
602
603 @Override
604 public void onNanoAppLoaded(long nanoAppId) {
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800605 executor.execute(() -> callback.onNanoAppLoaded(client, nanoAppId));
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800606 }
607
608 @Override
609 public void onNanoAppUnloaded(long nanoAppId) {
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800610 executor.execute(() -> callback.onNanoAppUnloaded(client, nanoAppId));
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800611 }
612
613 @Override
614 public void onNanoAppEnabled(long nanoAppId) {
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800615 executor.execute(() -> callback.onNanoAppEnabled(client, nanoAppId));
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800616 }
617
618 @Override
619 public void onNanoAppDisabled(long nanoAppId) {
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800620 executor.execute(() -> callback.onNanoAppDisabled(client, nanoAppId));
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800621 }
622 };
623 }
624
625 /**
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700626 * Creates and registers a client and its callback with the Context Hub Service.
627 *
628 * A client is registered with the Context Hub Service for a specified Context Hub. When the
629 * registration succeeds, the client can send messages to nanoapps through the returned
630 * {@link ContextHubClient} object, and receive notifications through the provided callback.
631 *
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800632 * @param hubInfo the hub to attach this client to
Arthur Ishiguroe35a6de2017-12-20 15:30:51 -0800633 * @param callback the notification callback to register
634 * @param executor the executor to invoke the callback
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700635 * @return the registered client object
636 *
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800637 * @throws IllegalArgumentException if hubInfo does not represent a valid hub
638 * @throws IllegalStateException if there were too many registered clients at the service
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800639 * @throws NullPointerException if callback, hubInfo, or executor is null
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700640 *
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800641 * @see ContextHubClientCallback
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700642 */
Arthur Ishiguroe35a6de2017-12-20 15:30:51 -0800643 @NonNull public ContextHubClient createClient(
644 @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback,
645 @NonNull @CallbackExecutor Executor executor) {
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800646 Preconditions.checkNotNull(callback, "Callback cannot be null");
647 Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
648 Preconditions.checkNotNull(executor, "Executor cannot be null");
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800649
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800650 ContextHubClient client = new ContextHubClient(hubInfo);
651 IContextHubClientCallback clientInterface = createClientCallback(
652 client, callback, executor);
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800653
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800654 IContextHubClient clientProxy;
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800655 try {
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800656 clientProxy = mService.createClient(clientInterface, hubInfo.getId());
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800657 } catch (RemoteException e) {
658 throw e.rethrowFromSystemServer();
659 }
660
Arthur Ishiguro78493a12018-01-02 10:44:21 -0800661 client.setClientProxy(clientProxy);
662 return client;
Arthur Ishigurob9ae7bd2017-10-09 12:47:52 -0700663 }
664
665 /**
Arthur Ishiguro9b9c9d82017-12-20 16:11:53 -0800666 * Equivalent to {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)}
667 * with the executor using the main thread's Looper.
668 *
669 * @param hubInfo the hub to attach this client to
670 * @param callback the notification callback to register
671 * @return the registered client object
672 *
673 * @throws IllegalArgumentException if hubInfo does not represent a valid hub
674 * @throws IllegalStateException if there were too many registered clients at the service
675 * @throws NullPointerException if callback or hubInfo is null
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800676 *
Arthur Ishiguro9b9c9d82017-12-20 16:11:53 -0800677 * @see ContextHubClientCallback
678 */
679 @NonNull public ContextHubClient createClient(
680 @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback) {
681 return createClient(hubInfo, callback, new HandlerExecutor(Handler.getMain()));
682 }
683
684 /**
destradaa8bad3fe2016-03-15 12:33:40 -0700685 * Unregister a callback for receive messages from the context hub.
Peng Xu9ff7d222016-02-11 13:02:05 -0800686 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700687 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800688 *
689 * @param callback method to deregister
690 *
691 * @return int 0 on success, -1 otherwise
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800692 *
693 * @deprecated Use {@link android.hardware.location.ContextHubClient#close()} to unregister
694 * a {@link android.hardware.location.ContextHubClientCallback}.
Peng Xu9ff7d222016-02-11 13:02:05 -0800695 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600696 @SuppressLint("Doclava125")
Arthur Ishigurof2b6f012017-11-28 15:21:38 -0800697 @Deprecated
Arthur Ishiguroac7b9592018-01-02 09:46:42 -0800698 public int unregisterCallback(@NonNull Callback callback) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800699 synchronized(this) {
700 if (callback != mCallback) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700701 Log.w(TAG, "Cannot recognize callback!");
Peng Xu9ff7d222016-02-11 13:02:05 -0800702 return -1;
703 }
704
705 mCallback = null;
706 mCallbackHandler = null;
707 }
708 return 0;
709 }
710
destradaa78cebca2016-04-14 18:40:14 -0700711 /**
712 * @deprecated Use {@link #unregisterCallback(Callback)} instead.
713 * @hide
714 */
Aurimas Liutikas514c5ef2016-05-24 15:22:55 -0700715 @Deprecated
destradaa78cebca2016-04-14 18:40:14 -0700716 public synchronized int unregisterCallback(ICallback callback) {
717 if (callback != mLocalCallback) {
718 Log.w(TAG, "Cannot recognize local callback!");
719 return -1;
720 }
721 mLocalCallback = null;
722 return 0;
723 }
724
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600725 private final IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800726 @Override
Peng Xu9ff7d222016-02-11 13:02:05 -0800727 public void onMessageReceipt(final int hubId, final int nanoAppId,
destradaa8bad3fe2016-03-15 12:33:40 -0700728 final ContextHubMessage message) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800729 if (mCallback != null) {
730 synchronized(this) {
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700731 final Callback callback = mCallback;
Peng Xu9ff7d222016-02-11 13:02:05 -0800732 Handler handler = mCallbackHandler == null ?
733 new Handler(mMainLooper) : mCallbackHandler;
734 handler.post(new Runnable() {
735 @Override
736 public void run() {
737 callback.onMessageReceipt(hubId, nanoAppId, message);
738 }
739 });
740 }
destradaa78cebca2016-04-14 18:40:14 -0700741 } else if (mLocalCallback != null) {
742 // we always ensure that mCallback takes precedence, because mLocalCallback is only
743 // for internal compatibility
744 synchronized (this) {
745 mLocalCallback.onMessageReceipt(hubId, nanoAppId, message);
746 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800747 } else {
748 Log.d(TAG, "Context hub manager client callback is NULL");
749 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800750 }
751 };
752
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600753 /** @throws ServiceNotFoundException
754 * @hide */
755 public ContextHubManager(Context context, Looper mainLooper) throws ServiceNotFoundException {
Peng Xu9ff7d222016-02-11 13:02:05 -0800756 mMainLooper = mainLooper;
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600757 mService = IContextHubService.Stub.asInterface(
Ashutosh Joshi420e45e2016-12-20 16:34:41 -0800758 ServiceManager.getServiceOrThrow(Context.CONTEXTHUB_SERVICE));
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600759 try {
760 mService.registerCallback(mClientCallback);
761 } catch (RemoteException e) {
762 Log.w(TAG, "Could not register callback:" + e);
Peng Xu9ff7d222016-02-11 13:02:05 -0800763 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800764 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800765}