blob: 0c4573b3d7a27c779b6b9f31c7983d5b07e0ad79 [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
18import android.annotation.SystemApi;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080019import android.content.Context;
Peng Xu9ff7d222016-02-11 13:02:05 -080020import android.os.Handler;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080021import android.os.IBinder;
Peng Xu9ff7d222016-02-11 13:02:05 -080022import android.os.Looper;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080023import android.os.RemoteException;
Peng Xu9ff7d222016-02-11 13:02:05 -080024import android.os.ServiceManager;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080025import android.util.Log;
26
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080027/**
destradaa8bad3fe2016-03-15 12:33:40 -070028 * A class that exposes the Context hubs on a device to applications.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080029 *
destradaa8bad3fe2016-03-15 12:33:40 -070030 * Please note that this class is not expected to be used by unbundled applications. Also, calling
31 * applications are expected to have LOCATION_HARDWARE permissions to use this class.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080032 *
33 * @hide
34 */
35@SystemApi
36public final class ContextHubManager {
37
38 private static final String TAG = "ContextHubManager";
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080039
Peng Xu9ff7d222016-02-11 13:02:05 -080040 private final Looper mMainLooper;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080041 private IContextHubService mContextHubService;
Greg Kaiser6ba60e62016-03-18 10:08:39 -070042 private Callback mCallback;
Peng Xu9ff7d222016-02-11 13:02:05 -080043 private Handler mCallbackHandler;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080044
45 /**
destradaa78cebca2016-04-14 18:40:14 -070046 * @deprecated Use {@code mCallback} instead.
47 */
48 @Deprecated
49 private ICallback mLocalCallback;
50
51 /**
destradaa8bad3fe2016-03-15 12:33:40 -070052 * An interface to receive asynchronous communication from the context hub.
Peng Xu9ff7d222016-02-11 13:02:05 -080053 */
Greg Kaiser6ba60e62016-03-18 10:08:39 -070054 public abstract static class Callback {
55 protected Callback() {}
destradaa8bad3fe2016-03-15 12:33:40 -070056
Peng Xu9ff7d222016-02-11 13:02:05 -080057 /**
destradaa8bad3fe2016-03-15 12:33:40 -070058 * Callback function called on message receipt from context hub.
Peng Xu9ff7d222016-02-11 13:02:05 -080059 *
destradaa8bad3fe2016-03-15 12:33:40 -070060 * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070061 * @param nanoAppHandle Handle (unique identifier) for app instance that sent the message.
destradaa8bad3fe2016-03-15 12:33:40 -070062 * @param message The context hub message.
Peng Xu9ff7d222016-02-11 13:02:05 -080063 *
64 * @see ContextHubMessage
65 */
destradaa8bad3fe2016-03-15 12:33:40 -070066 public abstract void onMessageReceipt(
67 int hubHandle,
68 int nanoAppHandle,
69 ContextHubMessage message);
Peng Xu9ff7d222016-02-11 13:02:05 -080070 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080071
72 /**
destradaa78cebca2016-04-14 18:40:14 -070073 * @deprecated Use {@link Callback} instead.
74 * @hide
75 */
76 @Deprecated
77 public interface ICallback {
78 /**
79 * Callback function called on message receipt from context hub.
80 *
81 * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
82 * @param nanoAppHandle Handle (unique identifier) for app instance that sent the message.
83 * @param message The context hub message.
84 *
85 * @see ContextHubMessage
86 */
87 void onMessageReceipt(int hubHandle, int nanoAppHandle, ContextHubMessage message);
88 }
89
90 /**
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080091 * Get a handle to all the context hubs in the system
92 * @return array of context hub handles
93 */
Peng Xu9ff7d222016-02-11 13:02:05 -080094 public int[] getContextHubHandles() {
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -080095 int[] retVal = null;
Peng Xu9ff7d222016-02-11 13:02:05 -080096 try {
97 retVal = getBinder().getContextHubHandles();
98 } catch (RemoteException e) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070099 Log.w(TAG, "Could not fetch context hub handles : " + e);
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800100 }
101 return retVal;
102 }
103
104 /**
105 * Get more information about a specific hub.
106 *
destradaa8bad3fe2016-03-15 12:33:40 -0700107 * @param hubHandle Handle (system-wide unique identifier) of a context hub.
108 * @return ContextHubInfo Information about the requested context hub.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800109 *
110 * @see ContextHubInfo
111 */
destradaa8bad3fe2016-03-15 12:33:40 -0700112 public ContextHubInfo getContextHubInfo(int hubHandle) {
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800113 ContextHubInfo retVal = null;
Peng Xu9ff7d222016-02-11 13:02:05 -0800114 try {
destradaa8bad3fe2016-03-15 12:33:40 -0700115 retVal = getBinder().getContextHubInfo(hubHandle);
Peng Xu9ff7d222016-02-11 13:02:05 -0800116 } catch (RemoteException e) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700117 Log.w(TAG, "Could not fetch context hub info :" + e);
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800118 }
119
Peng Xu9ff7d222016-02-11 13:02:05 -0800120 return retVal;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800121 }
122
123 /**
destradaa8bad3fe2016-03-15 12:33:40 -0700124 * Load a nano app on a specified context hub.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800125 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700126 * Note that loading is asynchronous. When we return from this method,
127 * the nano app (probably) hasn't loaded yet. Assuming a return of 0
128 * from this method, then the final success/failure for the load, along
129 * with the "handle" for the nanoapp, is all delivered in a byte
130 * string via a call to Callback.onMessageReceipt.
131 *
132 * TODO(b/30784270): Provide a better success/failure and "handle" delivery.
133 *
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800134 * @param hubHandle handle of context hub to load the app on.
135 * @param app the nanoApp to load on the hub
136 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700137 * @return 0 if the command for loading was sent to the context hub;
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800138 * -1 otherwise
139 *
140 * @see NanoApp
141 */
142 public int loadNanoApp(int hubHandle, NanoApp app) {
143 int retVal = -1;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700144
Peng Xu9ff7d222016-02-11 13:02:05 -0800145 if (app == null) {
146 return retVal;
147 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800148
Peng Xu9ff7d222016-02-11 13:02:05 -0800149 try {
150 retVal = getBinder().loadNanoApp(hubHandle, app);
151 } catch (RemoteException e) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700152 Log.w(TAG, "Could not load nanoApp :" + e);
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800153 }
154
155 return retVal;
156 }
157
158 /**
159 * Unload a specified nanoApp
160 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700161 * Note that unloading is asynchronous. When we return from this method,
162 * the nano app (probably) hasn't unloaded yet. Assuming a return of 0
163 * from this method, then the final success/failure for the unload is
164 * delivered in a byte string via a call to Callback.onMessageReceipt.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800165 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700166 * TODO(b/30784270): Provide a better success/failure delivery.
167 *
168 * @param nanoAppHandle handle of the nanoApp to unload
169 *
170 * @return 0 if the command for unloading was sent to the context hub;
171 * -1 otherwise
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800172 */
destradaa8bad3fe2016-03-15 12:33:40 -0700173 public int unloadNanoApp(int nanoAppHandle) {
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800174 int retVal = -1;
175
Peng Xu9ff7d222016-02-11 13:02:05 -0800176 try {
destradaa8bad3fe2016-03-15 12:33:40 -0700177 retVal = getBinder().unloadNanoApp(nanoAppHandle);
Peng Xu9ff7d222016-02-11 13:02:05 -0800178 } catch (RemoteException e) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700179 Log.w(TAG, "Could not fetch unload nanoApp :" + e);
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800180 }
181
182 return retVal;
183 }
184
185 /**
186 * get information about the nano app instance
187 *
Greg Kaiser3be73d32016-08-18 10:13:52 -0700188 * NOTE: The returned NanoAppInstanceInfo does _not_ contain correct
189 * information for several fields, specifically:
190 * - getName()
191 * - getPublisher()
192 * - getNeededExecMemBytes()
193 * - getNeededReadMemBytes()
194 * - getNeededWriteMemBytes()
195 *
196 * For example, say you call loadNanoApp() with a NanoApp that has
197 * getName() returning "My Name". Later, if you call getNanoAppInstanceInfo
198 * for that nanoapp, the returned NanoAppInstanceInfo's getName()
199 * method will claim "Preloaded app, unknown", even though you would
200 * have expected "My Name". For now, as the user, you'll need to
201 * separately track the above fields if they are of interest to you.
202 *
203 * TODO(b/30943489): Have the returned NanoAppInstanceInfo contain the
204 * correct information.
205 *
destradaa8bad3fe2016-03-15 12:33:40 -0700206 * @param nanoAppHandle handle of the nanoAppInstance
207 * @return NanoAppInstanceInfo Information about the nano app instance.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800208 *
209 * @see NanoAppInstanceInfo
210 */
destradaa8bad3fe2016-03-15 12:33:40 -0700211 public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800212 NanoAppInstanceInfo retVal = null;
213
Peng Xu9ff7d222016-02-11 13:02:05 -0800214 try {
destradaa8bad3fe2016-03-15 12:33:40 -0700215 retVal = getBinder().getNanoAppInstanceInfo(nanoAppHandle);
Peng Xu9ff7d222016-02-11 13:02:05 -0800216 } catch (RemoteException e) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700217 Log.w(TAG, "Could not fetch nanoApp info :" + e);
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800218 }
219
220 return retVal;
221 }
222
223 /**
224 * Find a specified nano app on the system
225 *
226 * @param hubHandle handle of hub to search for nano app
227 * @param filter filter specifying the search criteria for app
228 *
229 * @see NanoAppFilter
230 *
destradaa8bad3fe2016-03-15 12:33:40 -0700231 * @return int[] Array of handles to any found nano apps
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800232 */
destradaa8bad3fe2016-03-15 12:33:40 -0700233 public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
234 int[] retVal = null;
Peng Xu9ff7d222016-02-11 13:02:05 -0800235 try {
destradaa8bad3fe2016-03-15 12:33:40 -0700236 retVal = getBinder().findNanoAppOnHub(hubHandle, filter);
Peng Xu9ff7d222016-02-11 13:02:05 -0800237 } catch (RemoteException e) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700238 Log.w(TAG, "Could not query nanoApp instance :" + e);
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800239 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800240 return retVal;
241 }
242
243 /**
destradaa8bad3fe2016-03-15 12:33:40 -0700244 * Send a message to a specific nano app instance on a context hub.
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800245 *
Greg Kaiserfac5be22016-08-17 15:33:10 -0700246 * Note that the return value of this method only speaks of success
247 * up to the point of sending this to the Context Hub. It is not
248 * an assurance that the Context Hub successfully sent this message
249 * on to the nanoapp. If assurance is desired, a protocol should be
250 * established between your code and the nanoapp, with the nanoapp
251 * sending a confirmation message (which will be reported via
252 * Callback.onMessageReceipt).
253 *
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800254 * @param hubHandle handle of the hub to send the message to
255 * @param nanoAppHandle handle of the nano app to send to
destradaa8bad3fe2016-03-15 12:33:40 -0700256 * @param message Message to be sent
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800257 *
258 * @see ContextHubMessage
259 *
260 * @return int 0 on success, -1 otherwise
261 */
Peng Xu9ff7d222016-02-11 13:02:05 -0800262 public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) {
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800263 int retVal = -1;
264
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700265 if (message == null || message.getData() == null) {
266 Log.w(TAG, "null ptr");
267 return retVal;
268 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800269 try {
270 retVal = getBinder().sendMessage(hubHandle, nanoAppHandle, message);
271 } catch (RemoteException e) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700272 Log.w(TAG, "Could not send message :" + e.toString());
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800273 }
274
275 return retVal;
276 }
277
Peng Xu9ff7d222016-02-11 13:02:05 -0800278 /**
279 * Set a callback to receive messages from the context hub
280 *
Peng Xu9ff7d222016-02-11 13:02:05 -0800281 * @param callback Callback object
282 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700283 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800284 *
285 * @return int 0 on success, -1 otherwise
286 */
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700287 public int registerCallback(Callback callback) {
288 return registerCallback(callback, null);
Peng Xu9ff7d222016-02-11 13:02:05 -0800289 }
290
291 /**
destradaa78cebca2016-04-14 18:40:14 -0700292 * @deprecated Use {@link #registerCallback(Callback)} instead.
293 * @hide
294 */
295 @Deprecated
296 public int registerCallback(ICallback callback) {
297 if (mLocalCallback != null) {
298 Log.w(TAG, "Max number of local callbacks reached!");
299 return -1;
300 }
301 mLocalCallback = callback;
302 return 0;
303 }
304
305 /**
Peng Xu9ff7d222016-02-11 13:02:05 -0800306 * Set a callback to receive messages from the context hub
307 *
Peng Xu9ff7d222016-02-11 13:02:05 -0800308 * @param callback Callback object
destradaa8bad3fe2016-03-15 12:33:40 -0700309 * @param handler Handler object
Peng Xu9ff7d222016-02-11 13:02:05 -0800310 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700311 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800312 *
313 * @return int 0 on success, -1 otherwise
314 */
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700315 public int registerCallback(Callback callback, Handler handler) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800316 synchronized(this) {
317 if (mCallback != null) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700318 Log.w(TAG, "Max number of callbacks reached!");
Peng Xu9ff7d222016-02-11 13:02:05 -0800319 return -1;
320 }
321 mCallback = callback;
322 mCallbackHandler = handler;
323 }
324 return 0;
325 }
326
327 /**
destradaa8bad3fe2016-03-15 12:33:40 -0700328 * Unregister a callback for receive messages from the context hub.
Peng Xu9ff7d222016-02-11 13:02:05 -0800329 *
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700330 * @see Callback
Peng Xu9ff7d222016-02-11 13:02:05 -0800331 *
332 * @param callback method to deregister
333 *
334 * @return int 0 on success, -1 otherwise
335 */
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700336 public int unregisterCallback(Callback callback) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800337 synchronized(this) {
338 if (callback != mCallback) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700339 Log.w(TAG, "Cannot recognize callback!");
Peng Xu9ff7d222016-02-11 13:02:05 -0800340 return -1;
341 }
342
343 mCallback = null;
344 mCallbackHandler = null;
345 }
346 return 0;
347 }
348
destradaa78cebca2016-04-14 18:40:14 -0700349 /**
350 * @deprecated Use {@link #unregisterCallback(Callback)} instead.
351 * @hide
352 */
353 public synchronized int unregisterCallback(ICallback callback) {
354 if (callback != mLocalCallback) {
355 Log.w(TAG, "Cannot recognize local callback!");
356 return -1;
357 }
358 mLocalCallback = null;
359 return 0;
360 }
361
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800362 private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
363 @Override
Peng Xu9ff7d222016-02-11 13:02:05 -0800364 public void onMessageReceipt(final int hubId, final int nanoAppId,
destradaa8bad3fe2016-03-15 12:33:40 -0700365 final ContextHubMessage message) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800366 if (mCallback != null) {
367 synchronized(this) {
Greg Kaiser6ba60e62016-03-18 10:08:39 -0700368 final Callback callback = mCallback;
Peng Xu9ff7d222016-02-11 13:02:05 -0800369 Handler handler = mCallbackHandler == null ?
370 new Handler(mMainLooper) : mCallbackHandler;
371 handler.post(new Runnable() {
372 @Override
373 public void run() {
374 callback.onMessageReceipt(hubId, nanoAppId, message);
375 }
376 });
377 }
destradaa78cebca2016-04-14 18:40:14 -0700378 } else if (mLocalCallback != null) {
379 // we always ensure that mCallback takes precedence, because mLocalCallback is only
380 // for internal compatibility
381 synchronized (this) {
382 mLocalCallback.onMessageReceipt(hubId, nanoAppId, message);
383 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800384 } else {
385 Log.d(TAG, "Context hub manager client callback is NULL");
386 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800387 }
388 };
389
Peng Xu9ff7d222016-02-11 13:02:05 -0800390 /** @hide */
391 public ContextHubManager(Context context, Looper mainLooper) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800392 mMainLooper = mainLooper;
393
Ashutosh Joshi835da282016-12-27 09:32:49 -0800394 IBinder b = ServiceManager.getService(Context.CONTEXTHUB_SERVICE);
Peng Xu9ff7d222016-02-11 13:02:05 -0800395 if (b != null) {
396 mContextHubService = IContextHubService.Stub.asInterface(b);
397
398 try {
399 getBinder().registerCallback(mClientCallback);
400 } catch (RemoteException e) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700401 Log.w(TAG, "Could not register callback:" + e);
Peng Xu9ff7d222016-02-11 13:02:05 -0800402 }
403
404 } else {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700405 Log.w(TAG, "failed to getService");
Peng Xu9ff7d222016-02-11 13:02:05 -0800406 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800407 }
408
Peng Xu9ff7d222016-02-11 13:02:05 -0800409 private IContextHubService getBinder() throws RemoteException {
410 if (mContextHubService == null) {
411 throw new RemoteException("Service not connected.");
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800412 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800413 return mContextHubService;
414 }
Ashutosh Joshi1d1ac542016-01-18 17:19:27 -0800415}