• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.hardware.location;
17 
18 import android.annotation.SystemApi;
19 import android.content.Context;
20 import android.os.Handler;
21 import android.os.IBinder;
22 import android.os.Looper;
23 import android.os.RemoteException;
24 import android.os.ServiceManager;
25 import android.util.Log;
26 
27 /**
28  * A class that exposes the Context hubs on a device to applications.
29  *
30  * 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.
32  *
33  * @hide
34  */
35 @SystemApi
36 public final class ContextHubManager {
37 
38     private static final String TAG = "ContextHubManager";
39 
40     private final Looper mMainLooper;
41     private IContextHubService mContextHubService;
42     private Callback mCallback;
43     private Handler mCallbackHandler;
44 
45     /**
46      * @deprecated Use {@code mCallback} instead.
47      */
48     @Deprecated
49     private ICallback mLocalCallback;
50 
51     /**
52      * An interface to receive asynchronous communication from the context hub.
53      */
54     public abstract static class Callback {
Callback()55         protected Callback() {}
56 
57         /**
58          * Callback function called on message receipt from context hub.
59          *
60          * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
61          * @param nanoAppHandle Handle (unique identifier) for app instance that sent the message.
62          * @param message The context hub message.
63          *
64          * @see ContextHubMessage
65          */
onMessageReceipt( int hubHandle, int nanoAppHandle, ContextHubMessage message)66         public abstract void onMessageReceipt(
67                 int hubHandle,
68                 int nanoAppHandle,
69                 ContextHubMessage message);
70     }
71 
72     /**
73      * @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          */
onMessageReceipt(int hubHandle, int nanoAppHandle, ContextHubMessage message)87         void onMessageReceipt(int hubHandle, int nanoAppHandle, ContextHubMessage message);
88     }
89 
90     /**
91      * Get a handle to all the context hubs in the system
92      * @return array of context hub handles
93      */
getContextHubHandles()94     public int[] getContextHubHandles() {
95         int[] retVal = null;
96         try {
97             retVal = getBinder().getContextHubHandles();
98         } catch (RemoteException e) {
99             Log.w(TAG, "Could not fetch context hub handles : " + e);
100         }
101         return retVal;
102     }
103 
104     /**
105      * Get more information about a specific hub.
106      *
107      * @param hubHandle Handle (system-wide unique identifier) of a context hub.
108      * @return ContextHubInfo Information about the requested context hub.
109      *
110      * @see ContextHubInfo
111      */
getContextHubInfo(int hubHandle)112     public ContextHubInfo getContextHubInfo(int hubHandle) {
113         ContextHubInfo retVal = null;
114         try {
115             retVal = getBinder().getContextHubInfo(hubHandle);
116         } catch (RemoteException e) {
117             Log.w(TAG, "Could not fetch context hub info :" + e);
118         }
119 
120         return retVal;
121     }
122 
123     /**
124      * Load a nano app on a specified context hub.
125      *
126      * @param hubHandle handle of context hub to load the app on.
127      * @param app the nanoApp to load on the hub
128      *
129      * @return int nanoAppInstance of the loaded nanoApp on success,
130      *         -1 otherwise
131      *
132      * @see NanoApp
133      */
loadNanoApp(int hubHandle, NanoApp app)134     public int loadNanoApp(int hubHandle, NanoApp app) {
135         int retVal = -1;
136 
137         if (app == null) {
138             return retVal;
139         }
140 
141         try {
142             retVal = getBinder().loadNanoApp(hubHandle, app);
143         } catch (RemoteException e) {
144             Log.w(TAG, "Could not load nanoApp :" + e);
145         }
146 
147         return retVal;
148     }
149 
150     /**
151      * Unload a specified nanoApp
152      *
153      * @param nanoAppHandle handle of the nanoApp to load
154      *
155      * @return int  0 on success, -1 otherwise
156      */
unloadNanoApp(int nanoAppHandle)157     public int unloadNanoApp(int nanoAppHandle) {
158         int retVal = -1;
159 
160         try {
161             retVal = getBinder().unloadNanoApp(nanoAppHandle);
162         } catch (RemoteException e) {
163             Log.w(TAG, "Could not fetch unload nanoApp :" + e);
164         }
165 
166         return retVal;
167     }
168 
169     /**
170      * get information about the nano app instance
171      *
172      * @param nanoAppHandle handle of the nanoAppInstance
173      * @return NanoAppInstanceInfo Information about the nano app instance.
174      *
175      * @see NanoAppInstanceInfo
176      */
getNanoAppInstanceInfo(int nanoAppHandle)177     public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
178         NanoAppInstanceInfo retVal = null;
179 
180         try {
181             retVal = getBinder().getNanoAppInstanceInfo(nanoAppHandle);
182         } catch (RemoteException e) {
183             Log.w(TAG, "Could not fetch nanoApp info :" + e);
184         }
185 
186         return retVal;
187     }
188 
189     /**
190      * Find a specified nano app on the system
191      *
192      * @param hubHandle handle of hub to search for nano app
193      * @param filter filter specifying the search criteria for app
194      *
195      * @see NanoAppFilter
196      *
197      * @return int[] Array of handles to any found nano apps
198      */
findNanoAppOnHub(int hubHandle, NanoAppFilter filter)199     public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
200         int[] retVal = null;
201         try {
202             retVal = getBinder().findNanoAppOnHub(hubHandle, filter);
203         } catch (RemoteException e) {
204             Log.w(TAG, "Could not query nanoApp instance :" + e);
205         }
206         return retVal;
207     }
208 
209     /**
210      * Send a message to a specific nano app instance on a context hub.
211      *
212      * @param hubHandle handle of the hub to send the message to
213      * @param nanoAppHandle  handle of the nano app to send to
214      * @param message Message to be sent
215      *
216      * @see ContextHubMessage
217      *
218      * @return int 0 on success, -1 otherwise
219      */
sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message)220     public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) {
221         int retVal = -1;
222 
223         if (message == null || message.getData() == null) {
224             Log.w(TAG, "null ptr");
225             return retVal;
226         }
227         try {
228             retVal = getBinder().sendMessage(hubHandle, nanoAppHandle, message);
229         } catch (RemoteException e) {
230             Log.w(TAG, "Could not send message :" + e.toString());
231         }
232 
233         return retVal;
234     }
235 
236     /**
237      * Set a callback to receive messages from the context hub
238      *
239      * @param callback Callback object
240      *
241      * @see Callback
242      *
243      * @return int 0 on success, -1 otherwise
244      */
registerCallback(Callback callback)245     public int registerCallback(Callback callback) {
246         return registerCallback(callback, null);
247     }
248 
249     /**
250      * @deprecated Use {@link #registerCallback(Callback)} instead.
251      * @hide
252      */
253     @Deprecated
registerCallback(ICallback callback)254     public int registerCallback(ICallback callback) {
255         if (mLocalCallback != null) {
256             Log.w(TAG, "Max number of local callbacks reached!");
257             return -1;
258         }
259         mLocalCallback = callback;
260         return 0;
261     }
262 
263     /**
264      * Set a callback to receive messages from the context hub
265      *
266      * @param callback Callback object
267      * @param handler Handler object
268      *
269      * @see Callback
270      *
271      * @return int 0 on success, -1 otherwise
272      */
registerCallback(Callback callback, Handler handler)273     public int registerCallback(Callback callback, Handler handler) {
274         synchronized(this) {
275             if (mCallback != null) {
276                 Log.w(TAG, "Max number of callbacks reached!");
277                 return -1;
278             }
279             mCallback = callback;
280             mCallbackHandler = handler;
281         }
282         return 0;
283     }
284 
285     /**
286      * Unregister a callback for receive messages from the context hub.
287      *
288      * @see Callback
289      *
290      * @param callback method to deregister
291      *
292      * @return int 0 on success, -1 otherwise
293      */
unregisterCallback(Callback callback)294     public int unregisterCallback(Callback callback) {
295       synchronized(this) {
296           if (callback != mCallback) {
297               Log.w(TAG, "Cannot recognize callback!");
298               return -1;
299           }
300 
301           mCallback = null;
302           mCallbackHandler = null;
303       }
304       return 0;
305     }
306 
307     /**
308      * @deprecated Use {@link #unregisterCallback(Callback)} instead.
309      * @hide
310      */
unregisterCallback(ICallback callback)311     public synchronized int unregisterCallback(ICallback callback) {
312         if (callback != mLocalCallback) {
313             Log.w(TAG, "Cannot recognize local callback!");
314             return -1;
315         }
316         mLocalCallback = null;
317         return 0;
318     }
319 
320     private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
321         @Override
322         public void onMessageReceipt(final int hubId, final int nanoAppId,
323                 final ContextHubMessage message) {
324             if (mCallback != null) {
325                 synchronized(this) {
326                     final Callback callback = mCallback;
327                     Handler handler = mCallbackHandler == null ?
328                             new Handler(mMainLooper) : mCallbackHandler;
329                     handler.post(new Runnable() {
330                         @Override
331                         public void run() {
332                             callback.onMessageReceipt(hubId, nanoAppId, message);
333                         }
334                     });
335                 }
336             } else if (mLocalCallback != null) {
337                 // we always ensure that mCallback takes precedence, because mLocalCallback is only
338                 // for internal compatibility
339                 synchronized (this) {
340                     mLocalCallback.onMessageReceipt(hubId, nanoAppId, message);
341                 }
342             } else {
343                 Log.d(TAG, "Context hub manager client callback is NULL");
344             }
345         }
346     };
347 
348     /** @hide */
ContextHubManager(Context context, Looper mainLooper)349     public ContextHubManager(Context context, Looper mainLooper) {
350         mMainLooper = mainLooper;
351 
352         IBinder b = ServiceManager.getService(ContextHubService.CONTEXTHUB_SERVICE);
353         if (b != null) {
354             mContextHubService = IContextHubService.Stub.asInterface(b);
355 
356             try {
357                 getBinder().registerCallback(mClientCallback);
358             } catch (RemoteException e) {
359                 Log.w(TAG, "Could not register callback:" + e);
360             }
361 
362         } else {
363             Log.w(TAG, "failed to getService");
364         }
365     }
366 
getBinder()367     private IContextHubService getBinder() throws RemoteException {
368         if (mContextHubService == null) {
369             throw new RemoteException("Service not connected.");
370         }
371         return mContextHubService;
372     }
373 }
374