am 1b90bdf2: am f910d320: Merge "Address Robin\'s code review comments in initial FlpHal submission." into klp-dev
* commit '1b90bdf2fe6de9fa51be47a81d6d220e26291e02': Address Robin's code review comments in initial FlpHal submission.
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
*
|
||||
* 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 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
|
||||
* limitations under the License.
|
||||
*/
|
||||
@@ -21,20 +21,26 @@ import android.hardware.location.IFusedLocationHardwareSink;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class that exposes IFusedLocationHardware functionality to unbundled services.
|
||||
* Namely this is used by GmsCore Fused Location Provider.
|
||||
*/
|
||||
public final class FusedLocationHardware {
|
||||
private final String TAG = "FusedLocationHardware";
|
||||
|
||||
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() {
|
||||
@Override
|
||||
@@ -48,6 +54,9 @@ public final class FusedLocationHardware {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public FusedLocationHardware(IFusedLocationHardware locationHardware) {
|
||||
mLocationHardware = locationHardware;
|
||||
}
|
||||
@@ -55,19 +64,24 @@ public final class FusedLocationHardware {
|
||||
/*
|
||||
* Methods to provide a Facade for IFusedLocationHardware
|
||||
*/
|
||||
public void registerSink(FusedLocationHardwareSink sink) {
|
||||
if(sink == null) {
|
||||
return;
|
||||
public void registerSink(FusedLocationHardwareSink sink, Looper looper) {
|
||||
if(sink == null || looper == null) {
|
||||
throw new IllegalArgumentException("Parameter sink and looper cannot be null.");
|
||||
}
|
||||
|
||||
boolean registerSink = false;
|
||||
boolean registerSink;
|
||||
synchronized (mSinkList) {
|
||||
// register only on first insertion
|
||||
registerSink = mSinkList.size() == 0;
|
||||
// guarantee uniqueness
|
||||
if(!mSinkList.contains(sink)) {
|
||||
mSinkList.add(sink);
|
||||
if(mSinkList.containsKey(sink)) {
|
||||
return;
|
||||
}
|
||||
|
||||
HashMap<FusedLocationHardwareSink, DispatcherHandler> newSinkList =
|
||||
new HashMap<FusedLocationHardwareSink, DispatcherHandler>(mSinkList);
|
||||
newSinkList.put(sink, new DispatcherHandler(looper));
|
||||
mSinkList = newSinkList;
|
||||
}
|
||||
|
||||
if(registerSink) {
|
||||
@@ -81,14 +95,23 @@ public final class FusedLocationHardware {
|
||||
|
||||
public void unregisterSink(FusedLocationHardwareSink sink) {
|
||||
if(sink == null) {
|
||||
return;
|
||||
throw new IllegalArgumentException("Parameter sink cannot be null.");
|
||||
}
|
||||
|
||||
boolean unregisterSink = false;
|
||||
boolean unregisterSink;
|
||||
synchronized(mSinkList) {
|
||||
mSinkList.remove(sink);
|
||||
// unregister after the last sink
|
||||
unregisterSink = mSinkList.size() == 0;
|
||||
if(!mSinkList.containsKey(sink)) {
|
||||
//done
|
||||
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) {
|
||||
@@ -176,27 +199,82 @@ public final class FusedLocationHardware {
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper methods
|
||||
* Helper methods and classes
|
||||
*/
|
||||
private void dispatchLocations(Location[] locations) {
|
||||
ArrayList<FusedLocationHardwareSink> sinks = null;
|
||||
synchronized (mSinkList) {
|
||||
sinks = new ArrayList<FusedLocationHardwareSink>(mSinkList);
|
||||
private class DispatcherHandler extends Handler {
|
||||
public static final int DISPATCH_LOCATION = 1;
|
||||
public static final int DISPATCH_DIAGNOSTIC_DATA = 2;
|
||||
|
||||
public DispatcherHandler(Looper looper) {
|
||||
super(looper, null /*callback*/ , true /*async*/);
|
||||
}
|
||||
|
||||
for(FusedLocationHardwareSink sink : sinks) {
|
||||
sink.onLocationAvailable(locations);
|
||||
@Override
|
||||
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) {
|
||||
ArrayList<FusedLocationHardwareSink> sinks = null;
|
||||
HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
|
||||
synchronized(mSinkList) {
|
||||
sinks = new ArrayList<FusedLocationHardwareSink>(mSinkList);
|
||||
sinks = mSinkList;
|
||||
}
|
||||
|
||||
for(FusedLocationHardwareSink sink : sinks) {
|
||||
sink.onDiagnosticDataAvailable(data);
|
||||
for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
|
||||
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.
|
||||
* This is mainly used by GmsCore Fused Provider.
|
||||
*/
|
||||
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
|
||||
* API stable. See README.txt in the root of this package for more information.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public abstract class FusedProvider {
|
||||
private IFusedProvider.Stub mProvider = new IFusedProvider.Stub() {
|
||||
|
||||
@@ -437,7 +437,10 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
FusedProxy fusedProxy = FusedProxy.createAndBind(
|
||||
mContext,
|
||||
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) {
|
||||
Slog.e(TAG, "No FusedProvider found.");
|
||||
|
||||
@@ -28,11 +28,10 @@ import android.location.LocationManager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
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
|
||||
@@ -48,6 +47,7 @@ public class FlpHardwareProvider {
|
||||
|
||||
private final static String TAG = "FlpHardwareProvider";
|
||||
private final Context mContext;
|
||||
private final Object mLocationSinkLock = new Object();
|
||||
|
||||
public static FlpHardwareProvider getInstance(Context context) {
|
||||
if (sSingletonInstance == null) {
|
||||
@@ -61,7 +61,6 @@ public class FlpHardwareProvider {
|
||||
mContext = context;
|
||||
|
||||
// register for listening for passive provider data
|
||||
Handler handler = new Handler();
|
||||
LocationManager manager = (LocationManager) mContext.getSystemService(
|
||||
Context.LOCATION_SERVICE);
|
||||
manager.requestLocationUpdates(
|
||||
@@ -69,7 +68,7 @@ public class FlpHardwareProvider {
|
||||
0 /* minTime */,
|
||||
0 /* minDistance */,
|
||||
new NetworkLocationListener(),
|
||||
handler.getLooper());
|
||||
Looper.myLooper());
|
||||
}
|
||||
|
||||
public static boolean isSupported() {
|
||||
@@ -87,9 +86,13 @@ public class FlpHardwareProvider {
|
||||
location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
|
||||
}
|
||||
|
||||
IFusedLocationHardwareSink sink;
|
||||
synchronized (mLocationSinkLock) {
|
||||
sink = mLocationSink;
|
||||
}
|
||||
try {
|
||||
if (mLocationSink != null) {
|
||||
mLocationSink.onLocationAvailable(locations);
|
||||
if (sink != null) {
|
||||
sink.onLocationAvailable(locations);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoteException calling onLocationAvailable");
|
||||
@@ -98,9 +101,13 @@ public class FlpHardwareProvider {
|
||||
|
||||
// FlpDiagnosticCallbacks members
|
||||
private void onDataReport(String data) {
|
||||
IFusedLocationHardwareSink sink;
|
||||
synchronized (mLocationSinkLock) {
|
||||
sink = mLocationSink;
|
||||
}
|
||||
try {
|
||||
if (mLocationSink != null) {
|
||||
mLocationSink.onDiagnosticDataAvailable(data);
|
||||
sink.onDiagnosticDataAvailable(data);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoteException calling onDiagnosticDataAvailable");
|
||||
@@ -199,19 +206,24 @@ public class FlpHardwareProvider {
|
||||
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");
|
||||
}
|
||||
synchronized (mLocationSinkLock) {
|
||||
// only one sink is allowed at the moment
|
||||
if (mLocationSink != null) {
|
||||
throw new RuntimeException(
|
||||
"IFusedLocationHardware does not support multiple sinks");
|
||||
}
|
||||
|
||||
mLocationSink = eventSink;
|
||||
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;
|
||||
synchronized (mLocationSinkLock) {
|
||||
// don't throw if the sink is not registered, simply make it a no-op
|
||||
if (mLocationSink == eventSink) {
|
||||
mLocationSink = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,8 @@ import android.util.Log;
|
||||
*/
|
||||
public final class FusedProxy {
|
||||
private final String TAG = "FusedProxy";
|
||||
|
||||
private ServiceWatcher mServiceWatcher;
|
||||
|
||||
private FusedLocationHardwareSecure mLocationHardware;
|
||||
private final ServiceWatcher mServiceWatcher;
|
||||
private final FusedLocationHardwareSecure mLocationHardware;
|
||||
|
||||
/**
|
||||
* Constructor of the class.
|
||||
@@ -46,7 +44,13 @@ public final class FusedProxy {
|
||||
* @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) {
|
||||
private FusedProxy(
|
||||
Context context,
|
||||
Handler handler,
|
||||
IFusedLocationHardware locationHardware,
|
||||
int overlaySwitchResId,
|
||||
int defaultServicePackageNameResId,
|
||||
int initialPackageNameResId) {
|
||||
mLocationHardware = new FusedLocationHardwareSecure(
|
||||
locationHardware,
|
||||
context,
|
||||
@@ -63,9 +67,9 @@ public final class FusedProxy {
|
||||
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,
|
||||
overlaySwitchResId,
|
||||
defaultServicePackageNameResId,
|
||||
initialPackageNameResId,
|
||||
newServiceWork,
|
||||
handler);
|
||||
}
|
||||
@@ -82,9 +86,17 @@ public final class FusedProxy {
|
||||
public static FusedProxy createAndBind(
|
||||
Context context,
|
||||
Handler handler,
|
||||
IFusedLocationHardware locationHardware
|
||||
) {
|
||||
FusedProxy fusedProxy = new FusedProxy(context, handler, locationHardware);
|
||||
IFusedLocationHardware locationHardware,
|
||||
int overlaySwitchResId,
|
||||
int defaultServicePackageNameResId,
|
||||
int initialPackageNameResId) {
|
||||
FusedProxy fusedProxy = new FusedProxy(
|
||||
context,
|
||||
handler,
|
||||
locationHardware,
|
||||
overlaySwitchResId,
|
||||
defaultServicePackageNameResId,
|
||||
initialPackageNameResId);
|
||||
|
||||
// try to bind the Fused provider
|
||||
if (!fusedProxy.mServiceWatcher.start()) {
|
||||
|
||||
Reference in New Issue
Block a user