diff options
author | destradaa <destradaa@google.com> | 2013-07-12 15:43:36 -0700 |
---|---|---|
committer | destradaa <destradaa@google.com> | 2013-08-08 15:27:38 -0700 |
commit | 1af4b0280af406cfc7eb46810f6b76e57b983e11 (patch) | |
tree | 1f7f8d5a86c8dcd42cb24474e93b58bb0775071e /services/java/com/android/server/location | |
parent | 8ffe17ae32e72e5d872a36d5048bf912d28e766f (diff) | |
download | frameworks_base-1af4b0280af406cfc7eb46810f6b76e57b983e11.zip frameworks_base-1af4b0280af406cfc7eb46810f6b76e57b983e11.tar.gz frameworks_base-1af4b0280af406cfc7eb46810f6b76e57b983e11.tar.bz2 |
Add FlpHal layer to support Location Batching.
Change-Id: Ia3a57d869dfb3f067a1b95fa66d54f311ddcfdc3
Diffstat (limited to 'services/java/com/android/server/location')
3 files changed, 579 insertions, 0 deletions
diff --git a/services/java/com/android/server/location/FlpHardwareProvider.java b/services/java/com/android/server/location/FlpHardwareProvider.java new file mode 100644 index 0000000..469f7ce --- /dev/null +++ b/services/java/com/android/server/location/FlpHardwareProvider.java @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.location; + +import android.hardware.location.GeofenceHardwareImpl; +import android.hardware.location.IFusedLocationHardware; +import android.hardware.location.IFusedLocationHardwareSink; +import android.location.IFusedGeofenceHardware; +import android.location.FusedBatchOptions; +import android.location.Geofence; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; + +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.RemoteException; +import android.os.SystemClock; +import android.util.Log; +import android.util.Slog; + +/** + * This class is an interop layer for JVM types and the JNI code that interacts + * with the FLP HAL implementation. + * + * {@hide} + */ +public class FlpHardwareProvider { + private GeofenceHardwareImpl mGeofenceHardwareSink = null; + private IFusedLocationHardwareSink mLocationSink = null; + + private static FlpHardwareProvider sSingletonInstance = null; + + private final static String TAG = "FlpHardwareProvider"; + private final Context mContext; + + public static FlpHardwareProvider getInstance(Context context) { + if (sSingletonInstance == null) { + sSingletonInstance = new FlpHardwareProvider(context); + } + + return sSingletonInstance; + } + + private FlpHardwareProvider(Context context) { + mContext = context; + + // register for listening for passive provider data + Handler handler = new Handler(); + LocationManager manager = (LocationManager) mContext.getSystemService( + Context.LOCATION_SERVICE); + manager.requestLocationUpdates( + LocationManager.PASSIVE_PROVIDER, + 0 /* minTime */, + 0 /* minDistance */, + new NetworkLocationListener(), + handler.getLooper()); + } + + public static boolean isSupported() { + return nativeIsSupported(); + } + + /** + * Private callback functions used by FLP HAL. + */ + // FlpCallbacks members + private void onLocationReport(Location[] locations) { + for (Location location : locations) { + location.setProvider(LocationManager.FUSED_PROVIDER); + // set the elapsed time-stamp just as GPS provider does + location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()); + } + + try { + if (mLocationSink != null) { + mLocationSink.onLocationAvailable(locations); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException calling onLocationAvailable"); + } + } + + // FlpDiagnosticCallbacks members + private void onDataReport(String data) { + try { + if (mLocationSink != null) { + mLocationSink.onDiagnosticDataAvailable(data); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException calling onDiagnosticDataAvailable"); + } + } + + // FlpGeofenceCallbacks members + private void onGeofenceTransition( + int geofenceId, + Location location, + int transition, + long timestamp, + int sourcesUsed + ) { + // TODO: [GeofenceIntegration] change GeofenceHardwareImpl to accept a location object + } + + private void onGeofenceMonitorStatus(int status, int source, Location location) { + // TODO: [GeofenceIntegration] + } + + private void onGeofenceAdd(int geofenceId, int result) { + // TODO: [GeofenceIntegration] map between GPS and FLP results to pass a consistent status + } + + private void onGeofenceRemove(int geofenceId, int result) { + // TODO: [GeofenceIntegration] map between GPS and FLP results to pass a consistent status + } + + private void onGeofencePause(int geofenceId, int result) { + // TODO; [GeofenceIntegration] map between GPS and FLP results + } + + private void onGeofenceResume(int geofenceId, int result) { + // TODO: [GeofenceIntegration] map between GPS and FLP results + } + + /** + * Private native methods accessing FLP HAL. + */ + static { nativeClassInit(); } + + // Core members + private static native void nativeClassInit(); + private static native boolean nativeIsSupported(); + + // FlpLocationInterface members + private native void nativeInit(); + private native int nativeGetBatchSize(); + private native void nativeStartBatching(int requestId, FusedBatchOptions options); + private native void nativeUpdateBatchingOptions(int requestId, FusedBatchOptions optionsObject); + private native void nativeStopBatching(int id); + private native void nativeRequestBatchedLocation(int lastNLocations); + private native void nativeInjectLocation(Location location); + // TODO [Fix] sort out the lifetime of the instance + private native void nativeCleanup(); + + // FlpDiagnosticsInterface members + private native boolean nativeIsDiagnosticSupported(); + private native void nativeInjectDiagnosticData(String data); + + // FlpDeviceContextInterface members + private native boolean nativeIsDeviceContextSupported(); + private native void nativeInjectDeviceContext(int deviceEnabledContext); + + // FlpGeofencingInterface members + private native boolean nativeIsGeofencingSupported(); + private native void nativeAddGeofences(int[] geofenceIdsArray, Geofence[] geofencesArray); + private native void nativePauseGeofence(int geofenceId); + private native void nativeResumeGeofence(int geofenceId, int monitorTransitions); + private native void nativeModifyGeofenceOption( + int geofenceId, + int lastTransition, + int monitorTransitions, + int notificationResponsiveness, + int unknownTimer, + int sourcesToUse); + private native void nativeRemoveGeofences(int[] geofenceIdsArray); + + /** + * Interface implementations for services built on top of this functionality. + */ + public static final String LOCATION = "Location"; + public static final String GEOFENCING = "Geofencing"; + + public IFusedLocationHardware getLocationHardware() { + nativeInit(); + return mLocationHardware; + } + + public IFusedGeofenceHardware getGeofenceHardware() { + nativeInit(); + return mGeofenceHardwareService; + } + + private final IFusedLocationHardware mLocationHardware = new IFusedLocationHardware.Stub() { + @Override + public void registerSink(IFusedLocationHardwareSink eventSink) { + // only one sink is allowed at the moment + if (mLocationSink != null) { + throw new RuntimeException("IFusedLocationHardware does not support multiple sinks"); + } + + mLocationSink = eventSink; + } + + @Override + public void unregisterSink(IFusedLocationHardwareSink eventSink) { + // don't throw if the sink is not registered, simply make it a no-op + if (mLocationSink == eventSink) { + mLocationSink = null; + } + } + + @Override + public int getSupportedBatchSize() { + return nativeGetBatchSize(); + } + + @Override + public void startBatching(int requestId, FusedBatchOptions options) { + nativeStartBatching(requestId, options); + } + + @Override + public void stopBatching(int requestId) { + nativeStopBatching(requestId); + } + + @Override + public void updateBatchingOptions(int requestId, FusedBatchOptions options) { + nativeUpdateBatchingOptions(requestId, options); + } + + @Override + public void requestBatchOfLocations(int batchSizeRequested) { + nativeRequestBatchedLocation(batchSizeRequested); + } + + @Override + public boolean supportsDiagnosticDataInjection() { + return nativeIsDiagnosticSupported(); + } + + @Override + public void injectDiagnosticData(String data) { + nativeInjectDiagnosticData(data); + } + + @Override + public boolean supportsDeviceContextInjection() { + return nativeIsDeviceContextSupported(); + } + + @Override + public void injectDeviceContext(int deviceEnabledContext) { + nativeInjectDeviceContext(deviceEnabledContext); + } + }; + + private final IFusedGeofenceHardware mGeofenceHardwareService = + new IFusedGeofenceHardware.Stub() { + @Override + public boolean isSupported() { + return nativeIsGeofencingSupported(); + } + + @Override + public void addGeofences(int[] geofenceIdsArray, Geofence[] geofencesArray) { + nativeAddGeofences(geofenceIdsArray, geofencesArray); + } + + @Override + public void removeGeofences(int[] geofenceIds) { + nativeRemoveGeofences(geofenceIds); + } + + @Override + public void pauseMonitoringGeofence(int geofenceId) { + nativePauseGeofence(geofenceId); + } + + @Override + public void resumeMonitoringGeofence(int geofenceId, int monitorTransitions) { + nativeResumeGeofence(geofenceId, monitorTransitions); + } + + @Override + public void modifyGeofenceOptions(int geofenceId, + int lastTransition, + int monitorTransitions, + int notificationResponsiveness, + int unknownTimer + ) { + // TODO: [GeofenceIntegration] set sourcesToUse to the right value + // TODO: expose sourcesToUse externally when needed + nativeModifyGeofenceOption( + geofenceId, + lastTransition, + monitorTransitions, + notificationResponsiveness, + unknownTimer, + /* sourcesToUse */ 0xFFFF); + } + }; + + /** + * Internal classes and functions used by the provider. + */ + private final class NetworkLocationListener implements LocationListener { + @Override + public void onLocationChanged(Location location) { + if ( + !LocationManager.NETWORK_PROVIDER.equals(location.getProvider()) || + !location.hasAccuracy() + ) { + return; + } + + nativeInjectLocation(location); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { } + + @Override + public void onProviderEnabled(String provider) { } + + @Override + public void onProviderDisabled(String provider) { } + } + + private GeofenceHardwareImpl getGeofenceHardwareSink() { + if (mGeofenceHardwareSink == null) { + // TODO: [GeofenceIntegration] we need to register ourselves with GeofenceHardwareImpl + mGeofenceHardwareSink = GeofenceHardwareImpl.getInstance(mContext); + } + + return mGeofenceHardwareSink; + } +}
\ No newline at end of file diff --git a/services/java/com/android/server/location/FusedLocationHardwareSecure.java b/services/java/com/android/server/location/FusedLocationHardwareSecure.java new file mode 100644 index 0000000..389bd24 --- /dev/null +++ b/services/java/com/android/server/location/FusedLocationHardwareSecure.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.location; + +import android.content.Context; +import android.hardware.location.IFusedLocationHardware; +import android.hardware.location.IFusedLocationHardwareSink; +import android.location.FusedBatchOptions; +import android.os.RemoteException; + +/** + * FusedLocationHardware decorator that adds permission checking. + * @hide + */ +public class FusedLocationHardwareSecure extends IFusedLocationHardware.Stub { + private final IFusedLocationHardware mLocationHardware; + private final Context mContext; + private final String mPermissionId; + + public FusedLocationHardwareSecure( + IFusedLocationHardware locationHardware, + Context context, + String permissionId) { + mLocationHardware = locationHardware; + mContext = context; + mPermissionId = permissionId; + } + + private void checkPermissions() { + mContext.enforceCallingPermission( + mPermissionId, + String.format( + "Permission '%s' not granted to access FusedLocationHardware", + mPermissionId)); + } + + @Override + public void registerSink(IFusedLocationHardwareSink eventSink) throws RemoteException { + checkPermissions(); + mLocationHardware.registerSink(eventSink); + } + + @Override + public void unregisterSink(IFusedLocationHardwareSink eventSink) throws RemoteException { + checkPermissions(); + mLocationHardware.unregisterSink(eventSink); + } + + @Override + public int getSupportedBatchSize() throws RemoteException { + checkPermissions(); + return mLocationHardware.getSupportedBatchSize(); + } + + @Override + public void startBatching(int id, FusedBatchOptions batchOptions) throws RemoteException { + checkPermissions(); + mLocationHardware.startBatching(id, batchOptions); + } + + @Override + public void stopBatching(int id) throws RemoteException { + checkPermissions(); + mLocationHardware.stopBatching(id); + } + + @Override + public void updateBatchingOptions( + int id, + FusedBatchOptions batchoOptions + ) throws RemoteException { + checkPermissions(); + mLocationHardware.updateBatchingOptions(id, batchoOptions); + } + + @Override + public void requestBatchOfLocations(int batchSizeRequested) throws RemoteException { + checkPermissions(); + mLocationHardware.requestBatchOfLocations(batchSizeRequested); + } + + @Override + public boolean supportsDiagnosticDataInjection() throws RemoteException { + checkPermissions(); + return mLocationHardware.supportsDiagnosticDataInjection(); + } + + @Override + public void injectDiagnosticData(String data) throws RemoteException { + checkPermissions(); + mLocationHardware.injectDiagnosticData(data); + } + + @Override + public boolean supportsDeviceContextInjection() throws RemoteException { + checkPermissions(); + return mLocationHardware.supportsDeviceContextInjection(); + } + + @Override + public void injectDeviceContext(int deviceEnabledContext) throws RemoteException { + checkPermissions(); + mLocationHardware.injectDeviceContext(deviceEnabledContext); + } +} diff --git a/services/java/com/android/server/location/FusedProxy.java b/services/java/com/android/server/location/FusedProxy.java new file mode 100644 index 0000000..8278b96 --- /dev/null +++ b/services/java/com/android/server/location/FusedProxy.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (The "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.location; + +import com.android.server.ServiceWatcher; + +import android.Manifest; +import android.content.Context; +import android.hardware.location.IFusedLocationHardware; +import android.location.IFusedProvider; +import android.os.Handler; +import android.os.RemoteException; +import android.util.Log; + +/** + * Proxy that helps bind GCore FusedProvider implementations to the Fused Hardware instances. + * + * @hide + */ +public final class FusedProxy { + private final String TAG = "FusedProxy"; + + private ServiceWatcher mServiceWatcher; + + private FusedLocationHardwareSecure mLocationHardware; + + /** + * Constructor of the class. + * This is private as the class follows a factory pattern for construction. + * + * @param context The context needed for construction. + * @param handler The handler needed for construction. + * @param locationHardware The instance of the Fused location hardware assigned to the proxy. + */ + private FusedProxy(Context context, Handler handler, IFusedLocationHardware locationHardware) { + mLocationHardware = new FusedLocationHardwareSecure( + locationHardware, + context, + Manifest.permission.LOCATION_HARDWARE); + Runnable newServiceWork = new Runnable() { + @Override + public void run() { + bindProvider(mLocationHardware); + } + }; + + // prepare the connection to the provider + mServiceWatcher = new ServiceWatcher( + context, + TAG, + "com.android.location.service.FusedProvider", + com.android.internal.R.bool.config_enableFusedLocationOverlay, + com.android.internal.R.string.config_fusedLocationProviderPackageName, + com.android.internal.R.array.config_locationProviderPackageNames, + newServiceWork, + handler); + } + + /** + * Creates an instance of the proxy and binds it to the appropriate FusedProvider. + * + * @param context The context needed for construction. + * @param handler The handler needed for construction. + * @param locationHardware The instance of the Fused location hardware assigned to the proxy. + * + * @return An instance of the proxy if it could be bound, null otherwise. + */ + public static FusedProxy createAndBind( + Context context, + Handler handler, + IFusedLocationHardware locationHardware + ) { + FusedProxy fusedProxy = new FusedProxy(context, handler, locationHardware); + + // try to bind the Fused provider + if (!fusedProxy.mServiceWatcher.start()) { + return null; + } + + return fusedProxy; + } + + /** + * Helper function to bind the FusedLocationHardware to the appropriate FusedProvider instance. + * + * @param locationHardware The FusedLocationHardware instance to use for the binding operation. + */ + private void bindProvider(IFusedLocationHardware locationHardware) { + IFusedProvider provider = IFusedProvider.Stub.asInterface(mServiceWatcher.getBinder()); + + if (provider == null) { + Log.e(TAG, "No instance of FusedProvider found on FusedLocationHardware connected."); + return; + } + + try { + provider.onFusedLocationHardwareChange(locationHardware); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } +} |