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 */ 16package android.hardware.location; 17 18import android.annotation.SystemApi; 19import android.content.Context; 20import android.os.Handler; 21import android.os.IBinder; 22import android.os.Looper; 23import android.os.RemoteException; 24import android.os.ServiceManager; 25import 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 36public 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 { 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 367 private IContextHubService getBinder() throws RemoteException { 368 if (mContextHubService == null) { 369 throw new RemoteException("Service not connected."); 370 } 371 return mContextHubService; 372 } 373} 374