Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64be0c61 authored by destradaa's avatar destradaa
Browse files

Address Robin's code review comments in initial FlpHal submission.

Change-Id: I50889599fdc5938a19b8bff4f11e64f44bcebdbf
parent f6c7a5fd
Loading
Loading
Loading
Loading
+102 −24
Original line number Original line Diff line number Diff line
@@ -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)) {
                //done
                return;
            }

            HashMap<FusedLocationHardwareSink, DispatcherHandler> newSinkList =
                    new HashMap<FusedLocationHardwareSink, DispatcherHandler>(mSinkList);
            newSinkList.remove(sink);
            //unregister after the last sink
            //unregister after the last sink
            unregisterSink = mSinkList.size() == 0;
            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 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*/);
        }

        @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) {
    private void dispatchLocations(Location[] locations) {
        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.onLocationAvailable(locations);
            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();
        }
        }
    }
    }
}
}
+0 −1
Original line number Original line Diff line number Diff line
@@ -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 {
    /*
    /*
+0 −2
Original line number Original line Diff line number Diff line
@@ -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() {
+4 −1
Original line number Original line Diff line number Diff line
@@ -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.");
+27 −15
Original line number Original line Diff line number Diff line
@@ -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,21 +206,26 @@ 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) {
            synchronized (mLocationSinkLock) {
                // only one sink is allowed at the moment
                // only one sink is allowed at the moment
                if (mLocationSink != null) {
                if (mLocationSink != null) {
                throw new RuntimeException("IFusedLocationHardware does not support multiple sinks");
                    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) {
            synchronized (mLocationSinkLock) {
                // don't throw if the sink is not registered, simply make it a no-op
                // don't throw if the sink is not registered, simply make it a no-op
                if (mLocationSink == eventSink) {
                if (mLocationSink == eventSink) {
                    mLocationSink = null;
                    mLocationSink = null;
                }
                }
            }
            }
        }


        @Override
        @Override
        public int getSupportedBatchSize() {
        public int getSupportedBatchSize() {
Loading