Merge "Address Robin's code review comments in initial FlpHal submission." into klp-dev
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIOS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
@@ -21,20 +21,26 @@ import android.hardware.location.IFusedLocationHardwareSink;
|
|||||||
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.Message;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that exposes IFusedLocationHardware functionality to unbundled services.
|
* Class that exposes IFusedLocationHardware functionality to unbundled services.
|
||||||
* Namely this is used by GmsCore Fused Location Provider.
|
|
||||||
*/
|
*/
|
||||||
public final class FusedLocationHardware {
|
public final class FusedLocationHardware {
|
||||||
private final String TAG = "FusedLocationHardware";
|
private final String TAG = "FusedLocationHardware";
|
||||||
|
|
||||||
private IFusedLocationHardware mLocationHardware;
|
private IFusedLocationHardware mLocationHardware;
|
||||||
ArrayList<FusedLocationHardwareSink> mSinkList = new ArrayList<FusedLocationHardwareSink>();
|
|
||||||
|
// the list uses a copy-on-write pattern to update its contents
|
||||||
|
HashMap<FusedLocationHardwareSink, DispatcherHandler> mSinkList =
|
||||||
|
new HashMap<FusedLocationHardwareSink, DispatcherHandler>();
|
||||||
|
|
||||||
private IFusedLocationHardwareSink mInternalSink = new IFusedLocationHardwareSink.Stub() {
|
private IFusedLocationHardwareSink mInternalSink = new IFusedLocationHardwareSink.Stub() {
|
||||||
@Override
|
@Override
|
||||||
@@ -48,6 +54,9 @@ public final class FusedLocationHardware {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
public FusedLocationHardware(IFusedLocationHardware locationHardware) {
|
public FusedLocationHardware(IFusedLocationHardware locationHardware) {
|
||||||
mLocationHardware = locationHardware;
|
mLocationHardware = locationHardware;
|
||||||
}
|
}
|
||||||
@@ -55,19 +64,24 @@ public final class FusedLocationHardware {
|
|||||||
/*
|
/*
|
||||||
* Methods to provide a Facade for IFusedLocationHardware
|
* Methods to provide a Facade for IFusedLocationHardware
|
||||||
*/
|
*/
|
||||||
public void registerSink(FusedLocationHardwareSink sink) {
|
public void registerSink(FusedLocationHardwareSink sink, Looper looper) {
|
||||||
if(sink == null) {
|
if(sink == null || looper == null) {
|
||||||
return;
|
throw new IllegalArgumentException("Parameter sink and looper cannot be null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean registerSink = false;
|
boolean registerSink;
|
||||||
synchronized (mSinkList) {
|
synchronized (mSinkList) {
|
||||||
// register only on first insertion
|
// register only on first insertion
|
||||||
registerSink = mSinkList.size() == 0;
|
registerSink = mSinkList.size() == 0;
|
||||||
// guarantee uniqueness
|
// guarantee uniqueness
|
||||||
if(!mSinkList.contains(sink)) {
|
if(mSinkList.containsKey(sink)) {
|
||||||
mSinkList.add(sink);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HashMap<FusedLocationHardwareSink, DispatcherHandler> newSinkList =
|
||||||
|
new HashMap<FusedLocationHardwareSink, DispatcherHandler>(mSinkList);
|
||||||
|
newSinkList.put(sink, new DispatcherHandler(looper));
|
||||||
|
mSinkList = newSinkList;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(registerSink) {
|
if(registerSink) {
|
||||||
@@ -81,14 +95,23 @@ public final class FusedLocationHardware {
|
|||||||
|
|
||||||
public void unregisterSink(FusedLocationHardwareSink sink) {
|
public void unregisterSink(FusedLocationHardwareSink sink) {
|
||||||
if(sink == null) {
|
if(sink == null) {
|
||||||
return;
|
throw new IllegalArgumentException("Parameter sink cannot be null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean unregisterSink = false;
|
boolean unregisterSink;
|
||||||
synchronized(mSinkList) {
|
synchronized(mSinkList) {
|
||||||
mSinkList.remove(sink);
|
if(!mSinkList.containsKey(sink)) {
|
||||||
// unregister after the last sink
|
//done
|
||||||
unregisterSink = mSinkList.size() == 0;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap<FusedLocationHardwareSink, DispatcherHandler> newSinkList =
|
||||||
|
new HashMap<FusedLocationHardwareSink, DispatcherHandler>(mSinkList);
|
||||||
|
newSinkList.remove(sink);
|
||||||
|
//unregister after the last sink
|
||||||
|
unregisterSink = newSinkList.size() == 0;
|
||||||
|
|
||||||
|
mSinkList = newSinkList;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(unregisterSink) {
|
if(unregisterSink) {
|
||||||
@@ -176,27 +199,82 @@ public final class FusedLocationHardware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper methods
|
* Helper methods and classes
|
||||||
*/
|
*/
|
||||||
private void dispatchLocations(Location[] locations) {
|
private class DispatcherHandler extends Handler {
|
||||||
ArrayList<FusedLocationHardwareSink> sinks = null;
|
public static final int DISPATCH_LOCATION = 1;
|
||||||
synchronized (mSinkList) {
|
public static final int DISPATCH_DIAGNOSTIC_DATA = 2;
|
||||||
sinks = new ArrayList<FusedLocationHardwareSink>(mSinkList);
|
|
||||||
|
public DispatcherHandler(Looper looper) {
|
||||||
|
super(looper, null /*callback*/ , true /*async*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(FusedLocationHardwareSink sink : sinks) {
|
@Override
|
||||||
sink.onLocationAvailable(locations);
|
public void handleMessage(Message message) {
|
||||||
|
MessageCommand command = (MessageCommand) message.obj;
|
||||||
|
switch(message.what) {
|
||||||
|
case DISPATCH_LOCATION:
|
||||||
|
command.dispatchLocation();
|
||||||
|
break;
|
||||||
|
case DISPATCH_DIAGNOSTIC_DATA:
|
||||||
|
command.dispatchDiagnosticData();
|
||||||
|
default:
|
||||||
|
Log.e(TAG, "Invalid dispatch message");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MessageCommand {
|
||||||
|
private final FusedLocationHardwareSink mSink;
|
||||||
|
private final Location[] mLocations;
|
||||||
|
private final String mData;
|
||||||
|
|
||||||
|
public MessageCommand(
|
||||||
|
FusedLocationHardwareSink sink,
|
||||||
|
Location[] locations,
|
||||||
|
String data) {
|
||||||
|
mSink = sink;
|
||||||
|
mLocations = locations;
|
||||||
|
mData = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispatchLocation() {
|
||||||
|
mSink.onLocationAvailable(mLocations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispatchDiagnosticData() {
|
||||||
|
mSink.onDiagnosticDataAvailable(mData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dispatchLocations(Location[] locations) {
|
||||||
|
HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
|
||||||
|
synchronized (mSinkList) {
|
||||||
|
sinks = mSinkList;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
|
||||||
|
Message message = Message.obtain(
|
||||||
|
entry.getValue(),
|
||||||
|
DispatcherHandler.DISPATCH_LOCATION,
|
||||||
|
new MessageCommand(entry.getKey(), locations, null /*data*/));
|
||||||
|
message.sendToTarget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dispatchDiagnosticData(String data) {
|
private void dispatchDiagnosticData(String data) {
|
||||||
ArrayList<FusedLocationHardwareSink> sinks = null;
|
HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
|
||||||
synchronized(mSinkList) {
|
synchronized(mSinkList) {
|
||||||
sinks = new ArrayList<FusedLocationHardwareSink>(mSinkList);
|
sinks = mSinkList;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(FusedLocationHardwareSink sink : sinks) {
|
for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
|
||||||
sink.onDiagnosticDataAvailable(data);
|
Message message = Message.obtain(
|
||||||
|
entry.getValue(),
|
||||||
|
DispatcherHandler.DISPATCH_DIAGNOSTIC_DATA,
|
||||||
|
new MessageCommand(entry.getKey(), null /*locations*/, data));
|
||||||
|
message.sendToTarget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import android.location.Location;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for sinks to interact with FusedLocationHardware.
|
* Base class for sinks to interact with FusedLocationHardware.
|
||||||
* This is mainly used by GmsCore Fused Provider.
|
|
||||||
*/
|
*/
|
||||||
public abstract class FusedLocationHardwareSink {
|
public abstract class FusedLocationHardwareSink {
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ import android.os.IBinder;
|
|||||||
*
|
*
|
||||||
* <p>IMPORTANT: This class is effectively a public API for unbundled applications, and must remain
|
* <p>IMPORTANT: This class is effectively a public API for unbundled applications, and must remain
|
||||||
* API stable. See README.txt in the root of this package for more information.
|
* API stable. See README.txt in the root of this package for more information.
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public abstract class FusedProvider {
|
public abstract class FusedProvider {
|
||||||
private IFusedProvider.Stub mProvider = new IFusedProvider.Stub() {
|
private IFusedProvider.Stub mProvider = new IFusedProvider.Stub() {
|
||||||
|
|||||||
@@ -437,7 +437,10 @@ public class LocationManagerService extends ILocationManager.Stub {
|
|||||||
FusedProxy fusedProxy = FusedProxy.createAndBind(
|
FusedProxy fusedProxy = FusedProxy.createAndBind(
|
||||||
mContext,
|
mContext,
|
||||||
mLocationHandler,
|
mLocationHandler,
|
||||||
flpHardwareProvider.getLocationHardware());
|
flpHardwareProvider.getLocationHardware(),
|
||||||
|
com.android.internal.R.bool.config_enableFusedLocationOverlay,
|
||||||
|
com.android.internal.R.string.config_fusedLocationProviderPackageName,
|
||||||
|
com.android.internal.R.array.config_locationProviderPackageNames);
|
||||||
|
|
||||||
if(fusedProxy == null) {
|
if(fusedProxy == null) {
|
||||||
Slog.e(TAG, "No FusedProvider found.");
|
Slog.e(TAG, "No FusedProvider found.");
|
||||||
|
|||||||
@@ -28,11 +28,10 @@ import android.location.LocationManager;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Looper;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Slog;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is an interop layer for JVM types and the JNI code that interacts
|
* This class is an interop layer for JVM types and the JNI code that interacts
|
||||||
@@ -48,6 +47,7 @@ public class FlpHardwareProvider {
|
|||||||
|
|
||||||
private final static String TAG = "FlpHardwareProvider";
|
private final static String TAG = "FlpHardwareProvider";
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
private final Object mLocationSinkLock = new Object();
|
||||||
|
|
||||||
public static FlpHardwareProvider getInstance(Context context) {
|
public static FlpHardwareProvider getInstance(Context context) {
|
||||||
if (sSingletonInstance == null) {
|
if (sSingletonInstance == null) {
|
||||||
@@ -61,7 +61,6 @@ public class FlpHardwareProvider {
|
|||||||
mContext = context;
|
mContext = context;
|
||||||
|
|
||||||
// register for listening for passive provider data
|
// register for listening for passive provider data
|
||||||
Handler handler = new Handler();
|
|
||||||
LocationManager manager = (LocationManager) mContext.getSystemService(
|
LocationManager manager = (LocationManager) mContext.getSystemService(
|
||||||
Context.LOCATION_SERVICE);
|
Context.LOCATION_SERVICE);
|
||||||
manager.requestLocationUpdates(
|
manager.requestLocationUpdates(
|
||||||
@@ -69,7 +68,7 @@ public class FlpHardwareProvider {
|
|||||||
0 /* minTime */,
|
0 /* minTime */,
|
||||||
0 /* minDistance */,
|
0 /* minDistance */,
|
||||||
new NetworkLocationListener(),
|
new NetworkLocationListener(),
|
||||||
handler.getLooper());
|
Looper.myLooper());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSupported() {
|
public static boolean isSupported() {
|
||||||
@@ -87,9 +86,13 @@ public class FlpHardwareProvider {
|
|||||||
location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
|
location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IFusedLocationHardwareSink sink;
|
||||||
|
synchronized (mLocationSinkLock) {
|
||||||
|
sink = mLocationSink;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (mLocationSink != null) {
|
if (sink != null) {
|
||||||
mLocationSink.onLocationAvailable(locations);
|
sink.onLocationAvailable(locations);
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "RemoteException calling onLocationAvailable");
|
Log.e(TAG, "RemoteException calling onLocationAvailable");
|
||||||
@@ -98,9 +101,13 @@ public class FlpHardwareProvider {
|
|||||||
|
|
||||||
// FlpDiagnosticCallbacks members
|
// FlpDiagnosticCallbacks members
|
||||||
private void onDataReport(String data) {
|
private void onDataReport(String data) {
|
||||||
|
IFusedLocationHardwareSink sink;
|
||||||
|
synchronized (mLocationSinkLock) {
|
||||||
|
sink = mLocationSink;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (mLocationSink != null) {
|
if (mLocationSink != null) {
|
||||||
mLocationSink.onDiagnosticDataAvailable(data);
|
sink.onDiagnosticDataAvailable(data);
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "RemoteException calling onDiagnosticDataAvailable");
|
Log.e(TAG, "RemoteException calling onDiagnosticDataAvailable");
|
||||||
@@ -199,19 +206,24 @@ public class FlpHardwareProvider {
|
|||||||
private final IFusedLocationHardware mLocationHardware = new IFusedLocationHardware.Stub() {
|
private final IFusedLocationHardware mLocationHardware = new IFusedLocationHardware.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void registerSink(IFusedLocationHardwareSink eventSink) {
|
public void registerSink(IFusedLocationHardwareSink eventSink) {
|
||||||
// only one sink is allowed at the moment
|
synchronized (mLocationSinkLock) {
|
||||||
if (mLocationSink != null) {
|
// only one sink is allowed at the moment
|
||||||
throw new RuntimeException("IFusedLocationHardware does not support multiple sinks");
|
if (mLocationSink != null) {
|
||||||
}
|
throw new RuntimeException(
|
||||||
|
"IFusedLocationHardware does not support multiple sinks");
|
||||||
|
}
|
||||||
|
|
||||||
mLocationSink = eventSink;
|
mLocationSink = eventSink;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterSink(IFusedLocationHardwareSink eventSink) {
|
public void unregisterSink(IFusedLocationHardwareSink eventSink) {
|
||||||
// don't throw if the sink is not registered, simply make it a no-op
|
synchronized (mLocationSinkLock) {
|
||||||
if (mLocationSink == eventSink) {
|
// don't throw if the sink is not registered, simply make it a no-op
|
||||||
mLocationSink = null;
|
if (mLocationSink == eventSink) {
|
||||||
|
mLocationSink = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,10 +33,8 @@ import android.util.Log;
|
|||||||
*/
|
*/
|
||||||
public final class FusedProxy {
|
public final class FusedProxy {
|
||||||
private final String TAG = "FusedProxy";
|
private final String TAG = "FusedProxy";
|
||||||
|
private final ServiceWatcher mServiceWatcher;
|
||||||
private ServiceWatcher mServiceWatcher;
|
private final FusedLocationHardwareSecure mLocationHardware;
|
||||||
|
|
||||||
private FusedLocationHardwareSecure mLocationHardware;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor of the class.
|
* Constructor of the class.
|
||||||
@@ -46,7 +44,13 @@ public final class FusedProxy {
|
|||||||
* @param handler The handler needed for construction.
|
* @param handler The handler needed for construction.
|
||||||
* @param locationHardware The instance of the Fused location hardware assigned to the proxy.
|
* @param locationHardware The instance of the Fused location hardware assigned to the proxy.
|
||||||
*/
|
*/
|
||||||
private FusedProxy(Context context, Handler handler, IFusedLocationHardware locationHardware) {
|
private FusedProxy(
|
||||||
|
Context context,
|
||||||
|
Handler handler,
|
||||||
|
IFusedLocationHardware locationHardware,
|
||||||
|
int overlaySwitchResId,
|
||||||
|
int defaultServicePackageNameResId,
|
||||||
|
int initialPackageNameResId) {
|
||||||
mLocationHardware = new FusedLocationHardwareSecure(
|
mLocationHardware = new FusedLocationHardwareSecure(
|
||||||
locationHardware,
|
locationHardware,
|
||||||
context,
|
context,
|
||||||
@@ -63,9 +67,9 @@ public final class FusedProxy {
|
|||||||
context,
|
context,
|
||||||
TAG,
|
TAG,
|
||||||
"com.android.location.service.FusedProvider",
|
"com.android.location.service.FusedProvider",
|
||||||
com.android.internal.R.bool.config_enableFusedLocationOverlay,
|
overlaySwitchResId,
|
||||||
com.android.internal.R.string.config_fusedLocationProviderPackageName,
|
defaultServicePackageNameResId,
|
||||||
com.android.internal.R.array.config_locationProviderPackageNames,
|
initialPackageNameResId,
|
||||||
newServiceWork,
|
newServiceWork,
|
||||||
handler);
|
handler);
|
||||||
}
|
}
|
||||||
@@ -82,9 +86,17 @@ public final class FusedProxy {
|
|||||||
public static FusedProxy createAndBind(
|
public static FusedProxy createAndBind(
|
||||||
Context context,
|
Context context,
|
||||||
Handler handler,
|
Handler handler,
|
||||||
IFusedLocationHardware locationHardware
|
IFusedLocationHardware locationHardware,
|
||||||
) {
|
int overlaySwitchResId,
|
||||||
FusedProxy fusedProxy = new FusedProxy(context, handler, locationHardware);
|
int defaultServicePackageNameResId,
|
||||||
|
int initialPackageNameResId) {
|
||||||
|
FusedProxy fusedProxy = new FusedProxy(
|
||||||
|
context,
|
||||||
|
handler,
|
||||||
|
locationHardware,
|
||||||
|
overlaySwitchResId,
|
||||||
|
defaultServicePackageNameResId,
|
||||||
|
initialPackageNameResId);
|
||||||
|
|
||||||
// try to bind the Fused provider
|
// try to bind the Fused provider
|
||||||
if (!fusedProxy.mServiceWatcher.start()) {
|
if (!fusedProxy.mServiceWatcher.start()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user