/*
 * 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 android.hardware.location;

import android.content.Context;
import android.content.pm.PackageManager;
import android.location.IFusedGeofenceHardware;
import android.location.IGpsGeofenceHardware;
import android.location.Location;
import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * This class manages the geofences which are handled by hardware.
 *
 * @hide
 */
public final class GeofenceHardwareImpl {
    private static final String TAG = "GeofenceHardwareImpl";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final int FIRST_VERSION_WITH_CAPABILITIES = 2;

    private final Context mContext;
    private static GeofenceHardwareImpl sInstance;
    private PowerManager.WakeLock mWakeLock;
    private final SparseArray<IGeofenceHardwareCallback> mGeofences =
            new SparseArray<IGeofenceHardwareCallback>();
    private final ArrayList<IGeofenceHardwareMonitorCallback>[] mCallbacks =
            new ArrayList[GeofenceHardware.NUM_MONITORS];
    private final ArrayList<Reaper> mReapers = new ArrayList<Reaper>();

    private IFusedGeofenceHardware mFusedService;
    private IGpsGeofenceHardware mGpsService;
    private int mCapabilities;
    private int mVersion = 1;

    private int[] mSupportedMonitorTypes = new int[GeofenceHardware.NUM_MONITORS];

    // mGeofenceHandler message types
    private static final int GEOFENCE_TRANSITION_CALLBACK = 1;
    private static final int ADD_GEOFENCE_CALLBACK = 2;
    private static final int REMOVE_GEOFENCE_CALLBACK = 3;
    private static final int PAUSE_GEOFENCE_CALLBACK = 4;
    private static final int RESUME_GEOFENCE_CALLBACK = 5;
    private static final int GEOFENCE_CALLBACK_BINDER_DIED = 6;

    // mCallbacksHandler message types
    private static final int GEOFENCE_STATUS = 1;
    private static final int CALLBACK_ADD = 2;
    private static final int CALLBACK_REMOVE = 3;
    private static final int MONITOR_CALLBACK_BINDER_DIED = 4;

    // mReaperHandler message types
    private static final int REAPER_GEOFENCE_ADDED = 1;
    private static final int REAPER_MONITOR_CALLBACK_ADDED = 2;
    private static final int REAPER_REMOVED = 3;

    // The following constants need to match GpsLocationFlags enum in gps.h
    private static final int LOCATION_INVALID = 0;
    private static final int LOCATION_HAS_LAT_LONG = 1;
    private static final int LOCATION_HAS_ALTITUDE = 2;
    private static final int LOCATION_HAS_SPEED = 4;
    private static final int LOCATION_HAS_BEARING = 8;
    private static final int LOCATION_HAS_ACCURACY = 16;

    // Resolution level constants used for permission checks.
    // These constants must be in increasing order of finer resolution.
    private static final int RESOLUTION_LEVEL_NONE = 1;
    private static final int RESOLUTION_LEVEL_COARSE = 2;
    private static final int RESOLUTION_LEVEL_FINE = 3;

    // Capability constant corresponding to fused_location.h entry when geofencing supports GNNS.
    private static final int CAPABILITY_GNSS = 1;

    public synchronized static GeofenceHardwareImpl getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new GeofenceHardwareImpl(context);
        }
        return sInstance;
    }

    private GeofenceHardwareImpl(Context context) {
        mContext = context;
        // Init everything to unsupported.
        setMonitorAvailability(GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
                GeofenceHardware.MONITOR_UNSUPPORTED);
        setMonitorAvailability(
                GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
                GeofenceHardware.MONITOR_UNSUPPORTED);

    }

    private void acquireWakeLock() {
        if (mWakeLock == null) {
            PowerManager powerManager =
                    (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
            mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
        }
        mWakeLock.acquire();
    }

    private void releaseWakeLock() {
        if (mWakeLock.isHeld()) mWakeLock.release();
    }

    private void updateGpsHardwareAvailability() {
        //Check which monitors are available.
        boolean gpsSupported;
        try {
            gpsSupported = mGpsService.isHardwareGeofenceSupported();
        } catch (RemoteException e) {
            Log.e(TAG, "Remote Exception calling LocationManagerService");
            gpsSupported = false;
        }

        if (gpsSupported) {
            // Its assumed currently available at startup.
            // native layer will update later.
            setMonitorAvailability(GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
                    GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE);
        }
    }

    private void updateFusedHardwareAvailability() {
        boolean fusedSupported;
        try {
            final boolean hasGnnsCapabilities = (mVersion < FIRST_VERSION_WITH_CAPABILITIES)
                    || (mCapabilities & CAPABILITY_GNSS) != 0;
            fusedSupported = (mFusedService != null
                    ? mFusedService.isSupported() && hasGnnsCapabilities
                    : false);
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException calling LocationManagerService");
            fusedSupported = false;
        }

        if(fusedSupported) {
            setMonitorAvailability(
                    GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
                    GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE);
        }
    }

    public void setGpsHardwareGeofence(IGpsGeofenceHardware service) {
        if (mGpsService == null) {
            mGpsService = service;
            updateGpsHardwareAvailability();
        } else if (service == null) {
            mGpsService = null;
            Log.w(TAG, "GPS Geofence Hardware service seems to have crashed");
        } else {
            Log.e(TAG, "Error: GpsService being set again.");
        }
    }

    public void onCapabilities(int capabilities) {
        mCapabilities = capabilities;
        updateFusedHardwareAvailability();
    }

    public void setVersion(int version) {
        mVersion = version;
        updateFusedHardwareAvailability();
    }

    public void setFusedGeofenceHardware(IFusedGeofenceHardware service) {
        if(mFusedService == null) {
            mFusedService = service;
            updateFusedHardwareAvailability();
        } else if(service == null) {
            mFusedService = null;
            Log.w(TAG, "Fused Geofence Hardware service seems to have crashed");
        } else {
            Log.e(TAG, "Error: FusedService being set again");
        }
    }

    public int[] getMonitoringTypes() {
        boolean gpsSupported;
        boolean fusedSupported;
        synchronized (mSupportedMonitorTypes) {
            gpsSupported = mSupportedMonitorTypes[GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE]
                    != GeofenceHardware.MONITOR_UNSUPPORTED;
            fusedSupported = mSupportedMonitorTypes[GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE]
                    != GeofenceHardware.MONITOR_UNSUPPORTED;
        }

        if(gpsSupported) {
            if(fusedSupported) {
                return new int[] {
                        GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
                        GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE };
            } else {
                return new int[] { GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE };
            }
        } else if (fusedSupported) {
            return new int[] { GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE };
        } else {
            return new int[0];
        }
    }

    public int getStatusOfMonitoringType(int monitoringType) {
        synchronized (mSupportedMonitorTypes) {
            if (monitoringType >= mSupportedMonitorTypes.length || monitoringType < 0) {
                throw new IllegalArgumentException("Unknown monitoring type");
            }
            return mSupportedMonitorTypes[monitoringType];
        }
    }

    public int getCapabilitiesForMonitoringType(int monitoringType) {
        switch (mSupportedMonitorTypes[monitoringType]) {
            case GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE:
                switch (monitoringType) {
                    case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
                        return CAPABILITY_GNSS;
                    case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
                        if (mVersion >= FIRST_VERSION_WITH_CAPABILITIES) {
                            return mCapabilities;
                        }
                        // This was the implied capability on old FLP HAL versions that didn't
                        // have the capability callback.
                        return CAPABILITY_GNSS;
                }
                break;
        }
        return 0;
    }

    public boolean addCircularFence(
            int monitoringType,
            GeofenceHardwareRequestParcelable request,
            IGeofenceHardwareCallback callback) {
        int geofenceId = request.getId();

        // This API is not thread safe. Operations on the same geofence need to be serialized
        // by upper layers
        if (DEBUG) {
            String message = String.format(
                    "addCircularFence: monitoringType=%d, %s",
                    monitoringType,
                    request);
            Log.d(TAG, message);
        }
        boolean result;

        // The callback must be added before addCircularHardwareGeofence is called otherwise the
        // callback might not be called after the geofence is added in the geofence hardware.
        // This also means that the callback must be removed if the addCircularHardwareGeofence
        // operations is not called or fails.
        synchronized (mGeofences) {
            mGeofences.put(geofenceId, callback);
        }

        switch (monitoringType) {
            case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
                if (mGpsService == null) return false;
                try {
                    result = mGpsService.addCircularHardwareGeofence(
                            request.getId(),
                            request.getLatitude(),
                            request.getLongitude(),
                            request.getRadius(),
                            request.getLastTransition(),
                            request.getMonitorTransitions(),
                            request.getNotificationResponsiveness(),
                            request.getUnknownTimer());
                } catch (RemoteException e) {
                    Log.e(TAG, "AddGeofence: Remote Exception calling LocationManagerService");
                    result = false;
                }
                break;
            case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
                if(mFusedService == null) {
                    return false;
                }
                try {
                    mFusedService.addGeofences(
                            new GeofenceHardwareRequestParcelable[] { request });
                    result = true;
                } catch(RemoteException e) {
                    Log.e(TAG, "AddGeofence: RemoteException calling LocationManagerService");
                    result = false;
                }
                break;
            default:
                result = false;
        }
        if (result) {
            Message m = mReaperHandler.obtainMessage(REAPER_GEOFENCE_ADDED, callback);
            m.arg1 = monitoringType;
            mReaperHandler.sendMessage(m);
        } else {
            synchronized (mGeofences) {
                mGeofences.remove(geofenceId);
            }
        }

        if (DEBUG) Log.d(TAG, "addCircularFence: Result is: " + result);
        return result;
    }

    public boolean removeGeofence(int geofenceId, int monitoringType) {
        // This API is not thread safe. Operations on the same geofence need to be serialized
        // by upper layers
        if (DEBUG) Log.d(TAG, "Remove Geofence: GeofenceId: " + geofenceId);
        boolean result = false;

        synchronized (mGeofences) {
            if (mGeofences.get(geofenceId) == null) {
                throw new IllegalArgumentException("Geofence " + geofenceId + " not registered.");
            }
        }
        switch (monitoringType) {
            case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
                if (mGpsService == null) return false;
                try {
                    result = mGpsService.removeHardwareGeofence(geofenceId);
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoveGeofence: Remote Exception calling LocationManagerService");
                    result = false;
                }
                break;
            case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
                if(mFusedService == null) {
                    return false;
                }
                try {
                    mFusedService.removeGeofences(new int[] { geofenceId });
                    result = true;
                } catch(RemoteException e) {
                    Log.e(TAG, "RemoveGeofence: RemoteException calling LocationManagerService");
                    result = false;
                }
                break;
            default:
                result = false;
        }
        if (DEBUG) Log.d(TAG, "removeGeofence: Result is: " + result);
        return result;
    }

    public boolean pauseGeofence(int geofenceId, int monitoringType) {
        // This API is not thread safe. Operations on the same geofence need to be serialized
        // by upper layers
        if (DEBUG) Log.d(TAG, "Pause Geofence: GeofenceId: " + geofenceId);
        boolean result;
        synchronized (mGeofences) {
            if (mGeofences.get(geofenceId) == null) {
                throw new IllegalArgumentException("Geofence " + geofenceId + " not registered.");
            }
        }
        switch (monitoringType) {
            case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
                if (mGpsService == null) return false;
                try {
                    result = mGpsService.pauseHardwareGeofence(geofenceId);
                } catch (RemoteException e) {
                    Log.e(TAG, "PauseGeofence: Remote Exception calling LocationManagerService");
                    result = false;
                }
                break;
            case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
                if(mFusedService == null) {
                    return false;
                }
                try {
                    mFusedService.pauseMonitoringGeofence(geofenceId);
                    result = true;
                } catch(RemoteException e) {
                    Log.e(TAG, "PauseGeofence: RemoteException calling LocationManagerService");
                    result = false;
                }
                break;
            default:
                result = false;
        }
        if (DEBUG) Log.d(TAG, "pauseGeofence: Result is: " + result);
        return result;
    }


    public boolean resumeGeofence(int geofenceId,  int monitoringType, int monitorTransition) {
        // This API is not thread safe. Operations on the same geofence need to be serialized
        // by upper layers
        if (DEBUG) Log.d(TAG, "Resume Geofence: GeofenceId: " + geofenceId);
        boolean result;
        synchronized (mGeofences) {
            if (mGeofences.get(geofenceId) == null) {
                throw new IllegalArgumentException("Geofence " + geofenceId + " not registered.");
            }
        }
        switch (monitoringType) {
            case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
                if (mGpsService == null) return false;
                try {
                    result = mGpsService.resumeHardwareGeofence(geofenceId, monitorTransition);
                } catch (RemoteException e) {
                    Log.e(TAG, "ResumeGeofence: Remote Exception calling LocationManagerService");
                    result = false;
                }
                break;
            case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
                if(mFusedService == null) {
                    return false;
                }
                try {
                    mFusedService.resumeMonitoringGeofence(geofenceId, monitorTransition);
                    result = true;
                } catch(RemoteException e) {
                    Log.e(TAG, "ResumeGeofence: RemoteException calling LocationManagerService");
                    result = false;
                }
                break;
            default:
                result = false;
        }
        if (DEBUG) Log.d(TAG, "resumeGeofence: Result is: " + result);
        return result;
    }

    public boolean registerForMonitorStateChangeCallback(int monitoringType,
            IGeofenceHardwareMonitorCallback callback) {
        Message reaperMessage =
                mReaperHandler.obtainMessage(REAPER_MONITOR_CALLBACK_ADDED, callback);
        reaperMessage.arg1 = monitoringType;
        mReaperHandler.sendMessage(reaperMessage);

        Message m = mCallbacksHandler.obtainMessage(CALLBACK_ADD, callback);
        m.arg1 = monitoringType;
        mCallbacksHandler.sendMessage(m);
        return true;
    }

    public boolean unregisterForMonitorStateChangeCallback(int monitoringType,
            IGeofenceHardwareMonitorCallback callback) {
        Message m = mCallbacksHandler.obtainMessage(CALLBACK_REMOVE, callback);
        m.arg1 = monitoringType;
        mCallbacksHandler.sendMessage(m);
        return true;
    }

    /**
     * Used to report geofence transitions
     */
    public void reportGeofenceTransition(
            int geofenceId,
            Location location,
            int transition,
            long transitionTimestamp,
            int monitoringType,
            int sourcesUsed) {
        if(location == null) {
            Log.e(TAG, String.format("Invalid Geofence Transition: location=null"));
            return;
        }
        if(DEBUG) {
            Log.d(
                    TAG,
                    "GeofenceTransition| " + location + ", transition:" + transition +
                    ", transitionTimestamp:" + transitionTimestamp + ", monitoringType:" +
                    monitoringType + ", sourcesUsed:" + sourcesUsed);
        }

        GeofenceTransition geofenceTransition = new GeofenceTransition(
                geofenceId,
                transition,
                transitionTimestamp,
                location,
                monitoringType,
                sourcesUsed);
        acquireWakeLock();

        Message message = mGeofenceHandler.obtainMessage(
                GEOFENCE_TRANSITION_CALLBACK,
                geofenceTransition);
        message.sendToTarget();
    }

    /**
     * Used to report Monitor status changes.
     */
    public void reportGeofenceMonitorStatus(
            int monitoringType,
            int monitoringStatus,
            Location location,
            int source) {
        setMonitorAvailability(monitoringType, monitoringStatus);
        acquireWakeLock();
        GeofenceHardwareMonitorEvent event = new GeofenceHardwareMonitorEvent(
                monitoringType,
                monitoringStatus,
                source,
                location);
        Message message = mCallbacksHandler.obtainMessage(GEOFENCE_STATUS, event);
        message.sendToTarget();
    }

    /**
     * Internal generic status report function for Geofence operations.
     *
     * @param operation The operation to be reported as defined internally.
     * @param geofenceId The id of the geofence the operation is related to.
     * @param operationStatus The status of the operation as defined in GeofenceHardware class. This
     *                        status is independent of the statuses reported by different HALs.
     */
    private void reportGeofenceOperationStatus(int operation, int geofenceId, int operationStatus) {
        acquireWakeLock();
        Message message = mGeofenceHandler.obtainMessage(operation);
        message.arg1 = geofenceId;
        message.arg2 = operationStatus;
        message.sendToTarget();
    }

    /**
     * Used to report the status of a Geofence Add operation.
     */
    public void reportGeofenceAddStatus(int geofenceId, int status) {
        if(DEBUG) Log.d(TAG, "AddCallback| id:" + geofenceId + ", status:" + status);
        reportGeofenceOperationStatus(ADD_GEOFENCE_CALLBACK, geofenceId, status);
    }

    /**
     * Used to report the status of a Geofence Remove operation.
     */
    public void reportGeofenceRemoveStatus(int geofenceId, int status) {
        if(DEBUG) Log.d(TAG, "RemoveCallback| id:" + geofenceId + ", status:" + status);
        reportGeofenceOperationStatus(REMOVE_GEOFENCE_CALLBACK, geofenceId, status);
    }

    /**
     * Used to report the status of a Geofence Pause operation.
     */
    public void reportGeofencePauseStatus(int geofenceId, int status) {
        if(DEBUG) Log.d(TAG, "PauseCallbac| id:" + geofenceId + ", status" + status);
        reportGeofenceOperationStatus(PAUSE_GEOFENCE_CALLBACK, geofenceId, status);
    }

    /**
     * Used to report the status of a Geofence Resume operation.
     */
    public void reportGeofenceResumeStatus(int geofenceId, int status) {
        if(DEBUG) Log.d(TAG, "ResumeCallback| id:" + geofenceId + ", status:" + status);
        reportGeofenceOperationStatus(RESUME_GEOFENCE_CALLBACK, geofenceId, status);
    }

    // All operations on mGeofences
    private Handler mGeofenceHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int geofenceId;
            int status;
            IGeofenceHardwareCallback callback;
            switch (msg.what) {
                case ADD_GEOFENCE_CALLBACK:
                    geofenceId = msg.arg1;
                    synchronized (mGeofences) {
                        callback = mGeofences.get(geofenceId);
                    }

                    if (callback != null) {
                        try {
                            callback.onGeofenceAdd(geofenceId, msg.arg2);
                        } catch (RemoteException e) {Log.i(TAG, "Remote Exception:" + e);}
                    }
                    releaseWakeLock();
                    break;
                case REMOVE_GEOFENCE_CALLBACK:
                    geofenceId = msg.arg1;
                    synchronized (mGeofences) {
                        callback = mGeofences.get(geofenceId);
                    }

                    if (callback != null) {
                        try {
                            callback.onGeofenceRemove(geofenceId, msg.arg2);
                        } catch (RemoteException e) {}
                        IBinder callbackBinder = callback.asBinder();
                        boolean callbackInUse = false;
                        synchronized (mGeofences) {
                            mGeofences.remove(geofenceId);
                            // Check if the underlying binder is still useful for other geofences,
                            // if no, unlink the DeathRecipient to avoid memory leak.
                            for (int i = 0; i < mGeofences.size(); i++) {
                                 if (mGeofences.valueAt(i).asBinder() == callbackBinder) {
                                     callbackInUse = true;
                                     break;
                                 }
                            }
                        }

                        // Remove the reaper associated with this binder.
                        if (!callbackInUse) {
                            for (Iterator<Reaper> iterator = mReapers.iterator();
                                    iterator.hasNext();) {
                                Reaper reaper = iterator.next();
                                if (reaper.mCallback != null &&
                                        reaper.mCallback.asBinder() == callbackBinder) {
                                    iterator.remove();
                                    reaper.unlinkToDeath();
                                    if (DEBUG) Log.d(TAG, String.format("Removed reaper %s " +
                                          "because binder %s is no longer needed.",
                                          reaper, callbackBinder));
                                }
                            }
                        }
                    }
                    releaseWakeLock();
                    break;

                case PAUSE_GEOFENCE_CALLBACK:
                    geofenceId = msg.arg1;
                    synchronized (mGeofences) {
                        callback = mGeofences.get(geofenceId);
                    }

                    if (callback != null) {
                        try {
                            callback.onGeofencePause(geofenceId, msg.arg2);
                        } catch (RemoteException e) {}
                    }
                    releaseWakeLock();
                    break;

                case RESUME_GEOFENCE_CALLBACK:
                    geofenceId = msg.arg1;
                    synchronized (mGeofences) {
                        callback = mGeofences.get(geofenceId);
                    }

                    if (callback != null) {
                        try {
                            callback.onGeofenceResume(geofenceId, msg.arg2);
                        } catch (RemoteException e) {}
                    }
                    releaseWakeLock();
                    break;

                case GEOFENCE_TRANSITION_CALLBACK:
                    GeofenceTransition geofenceTransition = (GeofenceTransition)(msg.obj);
                    synchronized (mGeofences) {
                        callback = mGeofences.get(geofenceTransition.mGeofenceId);

                        // need to keep access to mGeofences synchronized at all times
                        if (DEBUG) Log.d(TAG, "GeofenceTransistionCallback: GPS : GeofenceId: " +
                                geofenceTransition.mGeofenceId +
                                " Transition: " + geofenceTransition.mTransition +
                                " Location: " + geofenceTransition.mLocation + ":" + mGeofences);
                    }

                    if (callback != null) {
                        try {
                            callback.onGeofenceTransition(
                                    geofenceTransition.mGeofenceId, geofenceTransition.mTransition,
                                    geofenceTransition.mLocation, geofenceTransition.mTimestamp,
                                    geofenceTransition.mMonitoringType);
                        } catch (RemoteException e) {}
                    }
                    releaseWakeLock();
                    break;
                case GEOFENCE_CALLBACK_BINDER_DIED:
                   // Find all geofences associated with this callback and remove them.
                   callback = (IGeofenceHardwareCallback) (msg.obj);
                   if (DEBUG) Log.d(TAG, "Geofence callback reaped:" + callback);
                   int monitoringType = msg.arg1;
                   synchronized (mGeofences) {
                       for (int i = 0; i < mGeofences.size(); i++) {
                            if (mGeofences.valueAt(i).equals(callback)) {
                                geofenceId = mGeofences.keyAt(i);
                                removeGeofence(mGeofences.keyAt(i), monitoringType);
                                mGeofences.remove(geofenceId);
                            }
                       }
                   }
            }
        }
    };

    // All operations on mCallbacks
    private Handler mCallbacksHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int monitoringType;
            ArrayList<IGeofenceHardwareMonitorCallback> callbackList;
            IGeofenceHardwareMonitorCallback callback;

            switch (msg.what) {
                case GEOFENCE_STATUS:
                    GeofenceHardwareMonitorEvent event = (GeofenceHardwareMonitorEvent) msg.obj;
                    callbackList = mCallbacks[event.getMonitoringType()];
                    if (callbackList != null) {
                        if (DEBUG) Log.d(TAG, "MonitoringSystemChangeCallback: " + event);

                        for (IGeofenceHardwareMonitorCallback c : callbackList) {
                            try {
                                c.onMonitoringSystemChange(event);
                            } catch (RemoteException e) {
                                Log.d(TAG, "Error reporting onMonitoringSystemChange.", e);
                            }
                        }
                    }
                    releaseWakeLock();
                    break;
                case CALLBACK_ADD:
                    monitoringType = msg.arg1;
                    callback = (IGeofenceHardwareMonitorCallback) msg.obj;
                    callbackList = mCallbacks[monitoringType];
                    if (callbackList == null) {
                        callbackList = new ArrayList<IGeofenceHardwareMonitorCallback>();
                        mCallbacks[monitoringType] = callbackList;
                    }
                    if (!callbackList.contains(callback)) callbackList.add(callback);
                    break;
                case CALLBACK_REMOVE:
                    monitoringType = msg.arg1;
                    callback = (IGeofenceHardwareMonitorCallback) msg.obj;
                    callbackList = mCallbacks[monitoringType];
                    if (callbackList != null) {
                        callbackList.remove(callback);
                    }
                    break;
                case MONITOR_CALLBACK_BINDER_DIED:
                    callback = (IGeofenceHardwareMonitorCallback) msg.obj;
                    if (DEBUG) Log.d(TAG, "Monitor callback reaped:" + callback);
                    callbackList = mCallbacks[msg.arg1];
                    if (callbackList != null && callbackList.contains(callback)) {
                        callbackList.remove(callback);
                    }
            }
        }
    };

    // All operations on mReaper
    private Handler mReaperHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Reaper r;
            IGeofenceHardwareCallback callback;
            IGeofenceHardwareMonitorCallback monitorCallback;
            int monitoringType;

            switch (msg.what) {
                case REAPER_GEOFENCE_ADDED:
                    callback = (IGeofenceHardwareCallback) msg.obj;
                    monitoringType = msg.arg1;
                    r = new Reaper(callback, monitoringType);
                    if (!mReapers.contains(r)) {
                        mReapers.add(r);
                        IBinder b = callback.asBinder();
                        try {
                            b.linkToDeath(r, 0);
                        } catch (RemoteException e) {}
                    }
                    break;
                case REAPER_MONITOR_CALLBACK_ADDED:
                    monitorCallback = (IGeofenceHardwareMonitorCallback) msg.obj;
                    monitoringType = msg.arg1;

                    r = new Reaper(monitorCallback, monitoringType);
                    if (!mReapers.contains(r)) {
                        mReapers.add(r);
                        IBinder b = monitorCallback.asBinder();
                        try {
                            b.linkToDeath(r, 0);
                        } catch (RemoteException e) {}
                    }
                    break;
                case REAPER_REMOVED:
                    r = (Reaper) msg.obj;
                    mReapers.remove(r);
            }
        }
    };

    private class GeofenceTransition {
        private int mGeofenceId, mTransition;
        private long mTimestamp;
        private Location mLocation;
        private int mMonitoringType;
        private int mSourcesUsed;

        GeofenceTransition(
                int geofenceId,
                int transition,
                long timestamp,
                Location location,
                int monitoringType,
                int sourcesUsed) {
            mGeofenceId = geofenceId;
            mTransition = transition;
            mTimestamp = timestamp;
            mLocation = location;
            mMonitoringType = monitoringType;
            mSourcesUsed = sourcesUsed;
        }
    }

    private void setMonitorAvailability(int monitor, int val) {
        synchronized (mSupportedMonitorTypes) {
            mSupportedMonitorTypes[monitor] = val;
        }
    }


    int getMonitoringResolutionLevel(int monitoringType) {
        switch (monitoringType) {
            case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
                return RESOLUTION_LEVEL_FINE;
            case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
                return RESOLUTION_LEVEL_FINE;
        }
        return RESOLUTION_LEVEL_NONE;
    }

    class Reaper implements IBinder.DeathRecipient {
        private IGeofenceHardwareMonitorCallback mMonitorCallback;
        private IGeofenceHardwareCallback mCallback;
        private int mMonitoringType;

        Reaper(IGeofenceHardwareCallback c, int monitoringType) {
            mCallback = c;
            mMonitoringType = monitoringType;
        }

        Reaper(IGeofenceHardwareMonitorCallback c, int monitoringType) {
            mMonitorCallback = c;
            mMonitoringType = monitoringType;
        }

        @Override
        public void binderDied() {
            Message m;
            if (mCallback != null) {
                m = mGeofenceHandler.obtainMessage(GEOFENCE_CALLBACK_BINDER_DIED, mCallback);
                m.arg1 = mMonitoringType;
                mGeofenceHandler.sendMessage(m);
            } else if (mMonitorCallback != null) {
                m = mCallbacksHandler.obtainMessage(MONITOR_CALLBACK_BINDER_DIED, mMonitorCallback);
                m.arg1 = mMonitoringType;
                mCallbacksHandler.sendMessage(m);
            }
            Message reaperMessage = mReaperHandler.obtainMessage(REAPER_REMOVED, this);
            mReaperHandler.sendMessage(reaperMessage);
        }

        @Override
        public int hashCode() {
            int result = 17;
            result = 31 * result + (mCallback != null ? mCallback.asBinder().hashCode() : 0);
            result = 31 * result + (mMonitorCallback != null
                    ? mMonitorCallback.asBinder().hashCode() : 0);
            result = 31 * result + mMonitoringType;
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) return false;
            if (obj == this) return true;

            Reaper rhs = (Reaper) obj;
            return binderEquals(rhs.mCallback, mCallback) &&
                    binderEquals(rhs.mMonitorCallback, mMonitorCallback) &&
                    rhs.mMonitoringType == mMonitoringType;
        }

        /**
         * Compares the underlying Binder of the given two IInterface objects and returns true if
         * they equals. null values are accepted.
         */
        private boolean binderEquals(IInterface left, IInterface right) {
          if (left == null) {
            return right == null;
          } else {
            return right == null ? false : left.asBinder() == right.asBinder();
          }
        }

        /**
         * Unlinks this DeathRecipient.
         */
        private boolean unlinkToDeath() {
          if (mMonitorCallback != null) {
            return mMonitorCallback.asBinder().unlinkToDeath(this, 0);
          } else if (mCallback != null) {
            return mCallback.asBinder().unlinkToDeath(this, 0);
          }
          return true;
        }

        private boolean callbackEquals(IGeofenceHardwareCallback cb) {
          return mCallback != null && mCallback.asBinder() == cb.asBinder();
        }
    }

    int getAllowedResolutionLevel(int pid, int uid) {
        if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
                pid, uid) == PackageManager.PERMISSION_GRANTED) {
            return RESOLUTION_LEVEL_FINE;
        } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
                pid, uid) == PackageManager.PERMISSION_GRANTED) {
            return RESOLUTION_LEVEL_COARSE;
        } else {
            return RESOLUTION_LEVEL_NONE;
        }
    }
}
