18ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh/*
28ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * Copyright (C) 2013 The Android Open Source Project
38ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh *
48ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * Licensed under the Apache License, Version 2.0 (the "License");
58ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * you may not use this file except in compliance with the License.
68ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * You may obtain a copy of the License at
78ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh *
88ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh *      http://www.apache.org/licenses/LICENSE-2.0
98ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh *
108ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * Unless required by applicable law or agreed to in writing, software
118ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * distributed under the License is distributed on an "AS IS" BASIS,
128ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * See the License for the specific language governing permissions and
148ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * limitations under the License.
158ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh */
168ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
178ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshpackage android.hardware.location;
188ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
198ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.content.Context;
208ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.content.pm.PackageManager;
210682809ad08db284d7110aab44108d5e9c310e6bdestradaaimport android.location.IFusedGeofenceHardware;
228ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.location.IGpsGeofenceHardware;
238ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.location.Location;
248ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.os.Handler;
25da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganeshimport android.os.IBinder;
268ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.os.Message;
278ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.os.PowerManager;
288ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.os.RemoteException;
298ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.util.Log;
308ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.util.SparseArray;
318ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
328ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport java.util.ArrayList;
338ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
348ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh/**
358ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * This class manages the geofences which are handled by hardware.
368ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh *
378ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * @hide
388ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh */
398ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshpublic final class GeofenceHardwareImpl {
408ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final String TAG = "GeofenceHardwareImpl";
418ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
428ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
438ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private final Context mContext;
448ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static GeofenceHardwareImpl sInstance;
458ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private PowerManager.WakeLock mWakeLock;
46f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun    private final SparseArray<IGeofenceHardwareCallback> mGeofences =
478ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            new SparseArray<IGeofenceHardwareCallback>();
48f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun    private final ArrayList<IGeofenceHardwareMonitorCallback>[] mCallbacks =
498ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            new ArrayList[GeofenceHardware.NUM_MONITORS];
50f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun    private final ArrayList<Reaper> mReapers = new ArrayList<Reaper>();
518ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
520682809ad08db284d7110aab44108d5e9c310e6bdestradaa    private IFusedGeofenceHardware mFusedService;
538ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private IGpsGeofenceHardware mGpsService;
548ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
558ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private int[] mSupportedMonitorTypes = new int[GeofenceHardware.NUM_MONITORS];
568ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
578ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    // mGeofenceHandler message types
588ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int GEOFENCE_TRANSITION_CALLBACK = 1;
598ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int ADD_GEOFENCE_CALLBACK = 2;
608ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int REMOVE_GEOFENCE_CALLBACK = 3;
618ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int PAUSE_GEOFENCE_CALLBACK = 4;
628ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int RESUME_GEOFENCE_CALLBACK = 5;
63f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun    private static final int GEOFENCE_CALLBACK_BINDER_DIED = 6;
648ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
658ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    // mCallbacksHandler message types
660682809ad08db284d7110aab44108d5e9c310e6bdestradaa    private static final int GEOFENCE_STATUS = 1;
678ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int CALLBACK_ADD = 2;
688ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int CALLBACK_REMOVE = 3;
69da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    private static final int MONITOR_CALLBACK_BINDER_DIED = 4;
70da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
71da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    // mReaperHandler message types
72da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    private static final int REAPER_GEOFENCE_ADDED = 1;
73da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    private static final int REAPER_MONITOR_CALLBACK_ADDED = 2;
74da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    private static final int REAPER_REMOVED = 3;
758ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
768ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    // The following constants need to match GpsLocationFlags enum in gps.h
778ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int LOCATION_INVALID = 0;
788ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int LOCATION_HAS_LAT_LONG = 1;
798ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int LOCATION_HAS_ALTITUDE = 2;
808ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int LOCATION_HAS_SPEED = 4;
818ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int LOCATION_HAS_BEARING = 8;
828ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int LOCATION_HAS_ACCURACY = 16;
838ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
848ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    // Resolution level constants used for permission checks.
858ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    // These constants must be in increasing order of finer resolution.
868ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int RESOLUTION_LEVEL_NONE = 1;
878ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int RESOLUTION_LEVEL_COARSE = 2;
888ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static final int RESOLUTION_LEVEL_FINE = 3;
898ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
908ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    public synchronized static GeofenceHardwareImpl getInstance(Context context) {
918ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (sInstance == null) {
928ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            sInstance = new GeofenceHardwareImpl(context);
938ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
948ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        return sInstance;
958ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
968ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
978ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private GeofenceHardwareImpl(Context context) {
988ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        mContext = context;
998ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        // Init everything to unsupported.
1008ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        setMonitorAvailability(GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1018ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                GeofenceHardware.MONITOR_UNSUPPORTED);
1020682809ad08db284d7110aab44108d5e9c310e6bdestradaa        setMonitorAvailability(
1030682809ad08db284d7110aab44108d5e9c310e6bdestradaa                GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
1040682809ad08db284d7110aab44108d5e9c310e6bdestradaa                GeofenceHardware.MONITOR_UNSUPPORTED);
1058ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
1068ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
1078ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
1088ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private void acquireWakeLock() {
1098ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (mWakeLock == null) {
1108ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            PowerManager powerManager =
1118ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
1128ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
1138ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
1148ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        mWakeLock.acquire();
1158ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
1168ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
1178ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private void releaseWakeLock() {
1188ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (mWakeLock.isHeld()) mWakeLock.release();
1198ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
1208ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
1218ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private void updateGpsHardwareAvailability() {
1228ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        //Check which monitors are available.
1238ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        boolean gpsSupported;
1248ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        try {
1258ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            gpsSupported = mGpsService.isHardwareGeofenceSupported();
1268ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        } catch (RemoteException e) {
1278ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            Log.e(TAG, "Remote Exception calling LocationManagerService");
1288ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            gpsSupported = false;
1298ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
1308ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
1318ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (gpsSupported) {
1328ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            // Its assumed currently available at startup.
1338ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            // native layer will update later.
1348ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            setMonitorAvailability(GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1358ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE);
1368ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
1378ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
1388ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
1390682809ad08db284d7110aab44108d5e9c310e6bdestradaa    private void updateFusedHardwareAvailability() {
1400682809ad08db284d7110aab44108d5e9c310e6bdestradaa        boolean fusedSupported;
1410682809ad08db284d7110aab44108d5e9c310e6bdestradaa        try {
1420682809ad08db284d7110aab44108d5e9c310e6bdestradaa            fusedSupported = mFusedService.isSupported();
1430682809ad08db284d7110aab44108d5e9c310e6bdestradaa        } catch(RemoteException e) {
1440682809ad08db284d7110aab44108d5e9c310e6bdestradaa            Log.e(TAG, "RemoteException calling LocationManagerService");
1450682809ad08db284d7110aab44108d5e9c310e6bdestradaa            fusedSupported = false;
1460682809ad08db284d7110aab44108d5e9c310e6bdestradaa        }
1470682809ad08db284d7110aab44108d5e9c310e6bdestradaa
1480682809ad08db284d7110aab44108d5e9c310e6bdestradaa        if(fusedSupported) {
1490682809ad08db284d7110aab44108d5e9c310e6bdestradaa            setMonitorAvailability(
1500682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
1510682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE);
1520682809ad08db284d7110aab44108d5e9c310e6bdestradaa        }
1530682809ad08db284d7110aab44108d5e9c310e6bdestradaa    }
1540682809ad08db284d7110aab44108d5e9c310e6bdestradaa
1558ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    public void setGpsHardwareGeofence(IGpsGeofenceHardware service) {
1568ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (mGpsService == null) {
1578ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mGpsService = service;
1588ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            updateGpsHardwareAvailability();
1598ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        } else if (service == null) {
1608ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mGpsService = null;
1618ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            Log.w(TAG, "GPS Geofence Hardware service seems to have crashed");
1628ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        } else {
1638ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            Log.e(TAG, "Error: GpsService being set again.");
1648ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
1658ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
1668ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
1670682809ad08db284d7110aab44108d5e9c310e6bdestradaa    public void setFusedGeofenceHardware(IFusedGeofenceHardware service) {
1680682809ad08db284d7110aab44108d5e9c310e6bdestradaa        if(mFusedService == null) {
1690682809ad08db284d7110aab44108d5e9c310e6bdestradaa            mFusedService = service;
1700682809ad08db284d7110aab44108d5e9c310e6bdestradaa            updateFusedHardwareAvailability();
1710682809ad08db284d7110aab44108d5e9c310e6bdestradaa        } else if(service == null) {
1720682809ad08db284d7110aab44108d5e9c310e6bdestradaa            mFusedService = null;
1730682809ad08db284d7110aab44108d5e9c310e6bdestradaa            Log.w(TAG, "Fused Geofence Hardware service seems to have crashed");
1740682809ad08db284d7110aab44108d5e9c310e6bdestradaa        } else {
1750682809ad08db284d7110aab44108d5e9c310e6bdestradaa            Log.e(TAG, "Error: FusedService being set again");
1760682809ad08db284d7110aab44108d5e9c310e6bdestradaa        }
1770682809ad08db284d7110aab44108d5e9c310e6bdestradaa    }
1780682809ad08db284d7110aab44108d5e9c310e6bdestradaa
179da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    public int[] getMonitoringTypes() {
1800682809ad08db284d7110aab44108d5e9c310e6bdestradaa        boolean gpsSupported;
1810682809ad08db284d7110aab44108d5e9c310e6bdestradaa        boolean fusedSupported;
1828ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        synchronized (mSupportedMonitorTypes) {
1830682809ad08db284d7110aab44108d5e9c310e6bdestradaa            gpsSupported = mSupportedMonitorTypes[GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE]
1840682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    != GeofenceHardware.MONITOR_UNSUPPORTED;
1850682809ad08db284d7110aab44108d5e9c310e6bdestradaa            fusedSupported = mSupportedMonitorTypes[GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE]
1860682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    != GeofenceHardware.MONITOR_UNSUPPORTED;
1870682809ad08db284d7110aab44108d5e9c310e6bdestradaa        }
1880682809ad08db284d7110aab44108d5e9c310e6bdestradaa
1890682809ad08db284d7110aab44108d5e9c310e6bdestradaa        if(gpsSupported) {
1900682809ad08db284d7110aab44108d5e9c310e6bdestradaa            if(fusedSupported) {
1910682809ad08db284d7110aab44108d5e9c310e6bdestradaa                return new int[] {
1920682809ad08db284d7110aab44108d5e9c310e6bdestradaa                        GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1930682809ad08db284d7110aab44108d5e9c310e6bdestradaa                        GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE };
1940682809ad08db284d7110aab44108d5e9c310e6bdestradaa            } else {
1950682809ad08db284d7110aab44108d5e9c310e6bdestradaa                return new int[] { GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE };
196da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            }
1970682809ad08db284d7110aab44108d5e9c310e6bdestradaa        } else if (fusedSupported) {
1980682809ad08db284d7110aab44108d5e9c310e6bdestradaa            return new int[] { GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE };
1990682809ad08db284d7110aab44108d5e9c310e6bdestradaa        } else {
200da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            return new int[0];
201da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        }
202da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    }
203da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
204da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    public int getStatusOfMonitoringType(int monitoringType) {
205da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        synchronized (mSupportedMonitorTypes) {
206da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            if (monitoringType >= mSupportedMonitorTypes.length || monitoringType < 0) {
207da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                throw new IllegalArgumentException("Unknown monitoring type");
208da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            }
209da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            return mSupportedMonitorTypes[monitoringType];
2108ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
2118ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
2128ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
213da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    public boolean addCircularFence(int geofenceId,  int monitoringType, double latitude,
214da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            double longitude, double radius, int lastTransition,int monitorTransitions,
215da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            int notificationResponsivenes, int unknownTimer, IGeofenceHardwareCallback callback) {
2168ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        // This API is not thread safe. Operations on the same geofence need to be serialized
2178ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        // by upper layers
2188ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (DEBUG) {
219f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun            Log.d(TAG, "addCircularFence: GeofenceId: " + geofenceId + " Latitude: " + latitude +
220f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    " Longitude: " + longitude + " Radius: " + radius + " LastTransition: "
221f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    + lastTransition + " MonitorTransition: " + monitorTransitions +
222f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    " NotificationResponsiveness: " + notificationResponsivenes +
223f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    " UnKnown Timer: " + unknownTimer + " MonitoringType: " + monitoringType);
2248ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
2258ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
2268ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        boolean result;
227f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun
228f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        // The callback must be added before addCircularHardwareGeofence is called otherwise the
229f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        // callback might not be called after the geofence is added in the geofence hardware.
230f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        // This also means that the callback must be removed if the addCircularHardwareGeofence
231f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        // operations is not called or fails.
232f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        synchronized (mGeofences) {
233f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun            mGeofences.put(geofenceId, callback);
234f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        }
2358ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
2368ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        switch (monitoringType) {
2378ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
2388ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                if (mGpsService == null) return false;
2398ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                try {
2408ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    result = mGpsService.addCircularHardwareGeofence(geofenceId, latitude,
2418ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                            longitude, radius, lastTransition, monitorTransitions,
2428ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                            notificationResponsivenes, unknownTimer);
2438ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                } catch (RemoteException e) {
2448ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    Log.e(TAG, "AddGeofence: Remote Exception calling LocationManagerService");
2458ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    result = false;
2468ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                }
2478ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                break;
2480682809ad08db284d7110aab44108d5e9c310e6bdestradaa            case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
2490682809ad08db284d7110aab44108d5e9c310e6bdestradaa                if(mFusedService == null) {
2500682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    return false;
2510682809ad08db284d7110aab44108d5e9c310e6bdestradaa                }
2520682809ad08db284d7110aab44108d5e9c310e6bdestradaa                GeofenceHardwareRequest request = GeofenceHardwareRequest.createCircularGeofence(
2530682809ad08db284d7110aab44108d5e9c310e6bdestradaa                        latitude,
2540682809ad08db284d7110aab44108d5e9c310e6bdestradaa                        longitude,
2550682809ad08db284d7110aab44108d5e9c310e6bdestradaa                        radius);
2560682809ad08db284d7110aab44108d5e9c310e6bdestradaa                request.setUnknownTimer(unknownTimer);
2570682809ad08db284d7110aab44108d5e9c310e6bdestradaa                request.setNotificationResponsiveness(notificationResponsivenes);
2580682809ad08db284d7110aab44108d5e9c310e6bdestradaa                request.setMonitorTransitions(monitorTransitions);
2590682809ad08db284d7110aab44108d5e9c310e6bdestradaa                request.setLastTransition(lastTransition);
2600682809ad08db284d7110aab44108d5e9c310e6bdestradaa
2610682809ad08db284d7110aab44108d5e9c310e6bdestradaa                GeofenceHardwareRequestParcelable parcelableRequest =
2620682809ad08db284d7110aab44108d5e9c310e6bdestradaa                        new GeofenceHardwareRequestParcelable(geofenceId, request);
2630682809ad08db284d7110aab44108d5e9c310e6bdestradaa                try {
2640682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    mFusedService.addGeofences(
2650682809ad08db284d7110aab44108d5e9c310e6bdestradaa                            new GeofenceHardwareRequestParcelable[] { parcelableRequest });
2660682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    result = true;
2670682809ad08db284d7110aab44108d5e9c310e6bdestradaa                } catch(RemoteException e) {
2680682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    Log.e(TAG, "AddGeofence: RemoteException calling LocationManagerService");
2690682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    result = false;
2700682809ad08db284d7110aab44108d5e9c310e6bdestradaa                }
2710682809ad08db284d7110aab44108d5e9c310e6bdestradaa                break;
2728ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            default:
2738ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                result = false;
2748ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
275da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        if (result) {
276f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun            Message m = mReaperHandler.obtainMessage(REAPER_GEOFENCE_ADDED, callback);
277da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            m.arg1 = monitoringType;
278da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            mReaperHandler.sendMessage(m);
279da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        } else {
280f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun            synchronized (mGeofences) {
281f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                mGeofences.remove(geofenceId);
282f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun            }
2838ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
2848ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
2858ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (DEBUG) Log.d(TAG, "addCircularFence: Result is: " + result);
2868ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        return result;
2878ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
2888ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
2898ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    public boolean removeGeofence(int geofenceId, int monitoringType) {
2908ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        // This API is not thread safe. Operations on the same geofence need to be serialized
2918ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        // by upper layers
2928ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (DEBUG) Log.d(TAG, "Remove Geofence: GeofenceId: " + geofenceId);
2938ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        boolean result = false;
294f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun
295f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        synchronized (mGeofences) {
296f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun            if (mGeofences.get(geofenceId) == null) {
297f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                throw new IllegalArgumentException("Geofence " + geofenceId + " not registered.");
298f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun            }
299f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        }
3008ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        switch (monitoringType) {
3018ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
3028ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                if (mGpsService == null) return false;
3038ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                try {
3048ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    result = mGpsService.removeHardwareGeofence(geofenceId);
3058ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                } catch (RemoteException e) {
3068ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    Log.e(TAG, "RemoveGeofence: Remote Exception calling LocationManagerService");
3078ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    result = false;
3088ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                }
3098ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                break;
3100682809ad08db284d7110aab44108d5e9c310e6bdestradaa            case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
3110682809ad08db284d7110aab44108d5e9c310e6bdestradaa                if(mFusedService == null) {
3120682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    return false;
3130682809ad08db284d7110aab44108d5e9c310e6bdestradaa                }
3140682809ad08db284d7110aab44108d5e9c310e6bdestradaa                try {
3150682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    mFusedService.removeGeofences(new int[] { geofenceId });
3160682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    result = true;
3170682809ad08db284d7110aab44108d5e9c310e6bdestradaa                } catch(RemoteException e) {
3180682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    Log.e(TAG, "RemoveGeofence: RemoteException calling LocationManagerService");
3190682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    result = false;
3200682809ad08db284d7110aab44108d5e9c310e6bdestradaa                }
3210682809ad08db284d7110aab44108d5e9c310e6bdestradaa                break;
3228ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            default:
3238ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                result = false;
3248ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
3258ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (DEBUG) Log.d(TAG, "removeGeofence: Result is: " + result);
3268ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        return result;
3278ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
3288ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
3298ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    public boolean pauseGeofence(int geofenceId, int monitoringType) {
3308ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        // This API is not thread safe. Operations on the same geofence need to be serialized
3318ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        // by upper layers
3328ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (DEBUG) Log.d(TAG, "Pause Geofence: GeofenceId: " + geofenceId);
3338ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        boolean result;
334f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        synchronized (mGeofences) {
335f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun            if (mGeofences.get(geofenceId) == null) {
336f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                throw new IllegalArgumentException("Geofence " + geofenceId + " not registered.");
337f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun            }
338f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        }
3398ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        switch (monitoringType) {
3408ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
3418ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                if (mGpsService == null) return false;
3428ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                try {
3438ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    result = mGpsService.pauseHardwareGeofence(geofenceId);
3448ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                } catch (RemoteException e) {
3458ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    Log.e(TAG, "PauseGeofence: Remote Exception calling LocationManagerService");
3468ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    result = false;
3478ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                }
3488ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                break;
3490682809ad08db284d7110aab44108d5e9c310e6bdestradaa            case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
3500682809ad08db284d7110aab44108d5e9c310e6bdestradaa                if(mFusedService == null) {
3510682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    return false;
3520682809ad08db284d7110aab44108d5e9c310e6bdestradaa                }
3530682809ad08db284d7110aab44108d5e9c310e6bdestradaa                try {
3540682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    mFusedService.pauseMonitoringGeofence(geofenceId);
3550682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    result = true;
3560682809ad08db284d7110aab44108d5e9c310e6bdestradaa                } catch(RemoteException e) {
3570682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    Log.e(TAG, "PauseGeofence: RemoteException calling LocationManagerService");
3580682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    result = false;
3590682809ad08db284d7110aab44108d5e9c310e6bdestradaa                }
3600682809ad08db284d7110aab44108d5e9c310e6bdestradaa                break;
3618ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            default:
3628ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                result = false;
3638ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
3648ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (DEBUG) Log.d(TAG, "pauseGeofence: Result is: " + result);
3658ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        return result;
3668ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
3678ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
3688ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
369da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    public boolean resumeGeofence(int geofenceId,  int monitoringType, int monitorTransition) {
3708ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        // This API is not thread safe. Operations on the same geofence need to be serialized
3718ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        // by upper layers
3728ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (DEBUG) Log.d(TAG, "Resume Geofence: GeofenceId: " + geofenceId);
3738ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        boolean result;
374f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        synchronized (mGeofences) {
375f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun            if (mGeofences.get(geofenceId) == null) {
376f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                throw new IllegalArgumentException("Geofence " + geofenceId + " not registered.");
377f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun            }
378f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun        }
3798ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        switch (monitoringType) {
3808ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
3818ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                if (mGpsService == null) return false;
3828ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                try {
3838ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    result = mGpsService.resumeHardwareGeofence(geofenceId, monitorTransition);
3848ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                } catch (RemoteException e) {
3858ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    Log.e(TAG, "ResumeGeofence: Remote Exception calling LocationManagerService");
3868ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    result = false;
3878ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                }
3888ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                break;
3890682809ad08db284d7110aab44108d5e9c310e6bdestradaa            case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
3900682809ad08db284d7110aab44108d5e9c310e6bdestradaa                if(mFusedService == null) {
3910682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    return false;
3920682809ad08db284d7110aab44108d5e9c310e6bdestradaa                }
3930682809ad08db284d7110aab44108d5e9c310e6bdestradaa                try {
3940682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    mFusedService.resumeMonitoringGeofence(geofenceId, monitorTransition);
3950682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    result = true;
3960682809ad08db284d7110aab44108d5e9c310e6bdestradaa                } catch(RemoteException e) {
3970682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    Log.e(TAG, "ResumeGeofence: RemoteException calling LocationManagerService");
3980682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    result = false;
3990682809ad08db284d7110aab44108d5e9c310e6bdestradaa                }
4000682809ad08db284d7110aab44108d5e9c310e6bdestradaa                break;
4018ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            default:
4028ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                result = false;
4038ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
4048ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (DEBUG) Log.d(TAG, "resumeGeofence: Result is: " + result);
4058ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        return result;
4068ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
4078ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
4088ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    public boolean registerForMonitorStateChangeCallback(int monitoringType,
409da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            IGeofenceHardwareMonitorCallback callback) {
410da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        Message reaperMessage =
411da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                mReaperHandler.obtainMessage(REAPER_MONITOR_CALLBACK_ADDED, callback);
412da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        reaperMessage.arg1 = monitoringType;
413da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        mReaperHandler.sendMessage(reaperMessage);
414da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
4158ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        Message m = mCallbacksHandler.obtainMessage(CALLBACK_ADD, callback);
4168ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        m.arg1 = monitoringType;
4178ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        mCallbacksHandler.sendMessage(m);
4188ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        return true;
4198ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
4208ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
4218ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    public boolean unregisterForMonitorStateChangeCallback(int monitoringType,
422da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            IGeofenceHardwareMonitorCallback callback) {
4238ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        Message m = mCallbacksHandler.obtainMessage(CALLBACK_REMOVE, callback);
4248ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        m.arg1 = monitoringType;
4258ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        mCallbacksHandler.sendMessage(m);
4268ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        return true;
4278ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
4288ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
4290682809ad08db284d7110aab44108d5e9c310e6bdestradaa    /**
4300682809ad08db284d7110aab44108d5e9c310e6bdestradaa     * Used to report geofence transitions
4310682809ad08db284d7110aab44108d5e9c310e6bdestradaa     */
4320682809ad08db284d7110aab44108d5e9c310e6bdestradaa    public void reportGeofenceTransition(
4330682809ad08db284d7110aab44108d5e9c310e6bdestradaa            int geofenceId,
4340682809ad08db284d7110aab44108d5e9c310e6bdestradaa            Location location,
4350682809ad08db284d7110aab44108d5e9c310e6bdestradaa            int transition,
4360682809ad08db284d7110aab44108d5e9c310e6bdestradaa            long transitionTimestamp,
4370682809ad08db284d7110aab44108d5e9c310e6bdestradaa            int monitoringType,
4380682809ad08db284d7110aab44108d5e9c310e6bdestradaa            int sourcesUsed) {
4390682809ad08db284d7110aab44108d5e9c310e6bdestradaa        if(location == null) {
4400682809ad08db284d7110aab44108d5e9c310e6bdestradaa            Log.e(TAG, String.format("Invalid Geofence Transition: location=%p", location));
4410682809ad08db284d7110aab44108d5e9c310e6bdestradaa            return;
4420682809ad08db284d7110aab44108d5e9c310e6bdestradaa        }
4430682809ad08db284d7110aab44108d5e9c310e6bdestradaa        if(DEBUG) {
4440682809ad08db284d7110aab44108d5e9c310e6bdestradaa            Log.d(
4450682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    TAG,
4460682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    "GeofenceTransition| " + location + ", transition:" + transition +
4470682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    ", transitionTimestamp:" + transitionTimestamp + ", monitoringType:" +
4480682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    monitoringType + ", sourcesUsed:" + sourcesUsed);
4490682809ad08db284d7110aab44108d5e9c310e6bdestradaa        }
4500682809ad08db284d7110aab44108d5e9c310e6bdestradaa
4510682809ad08db284d7110aab44108d5e9c310e6bdestradaa        GeofenceTransition geofenceTransition = new GeofenceTransition(
4520682809ad08db284d7110aab44108d5e9c310e6bdestradaa                geofenceId,
4530682809ad08db284d7110aab44108d5e9c310e6bdestradaa                transition,
4540682809ad08db284d7110aab44108d5e9c310e6bdestradaa                transitionTimestamp,
4550682809ad08db284d7110aab44108d5e9c310e6bdestradaa                location,
4560682809ad08db284d7110aab44108d5e9c310e6bdestradaa                monitoringType,
4570682809ad08db284d7110aab44108d5e9c310e6bdestradaa                sourcesUsed);
4580682809ad08db284d7110aab44108d5e9c310e6bdestradaa        acquireWakeLock();
4590682809ad08db284d7110aab44108d5e9c310e6bdestradaa
4600682809ad08db284d7110aab44108d5e9c310e6bdestradaa        Message message = mGeofenceHandler.obtainMessage(
4610682809ad08db284d7110aab44108d5e9c310e6bdestradaa                GEOFENCE_TRANSITION_CALLBACK,
4620682809ad08db284d7110aab44108d5e9c310e6bdestradaa                geofenceTransition);
4630682809ad08db284d7110aab44108d5e9c310e6bdestradaa        message.sendToTarget();
4648ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
4658ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
4668ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
4670682809ad08db284d7110aab44108d5e9c310e6bdestradaa     * Used to report Monitor status changes.
4688ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
4690682809ad08db284d7110aab44108d5e9c310e6bdestradaa    public void reportGeofenceMonitorStatus(
4700682809ad08db284d7110aab44108d5e9c310e6bdestradaa            int monitoringType,
4710682809ad08db284d7110aab44108d5e9c310e6bdestradaa            int monitoringStatus,
4720682809ad08db284d7110aab44108d5e9c310e6bdestradaa            Location location,
4730682809ad08db284d7110aab44108d5e9c310e6bdestradaa            int source) {
4740682809ad08db284d7110aab44108d5e9c310e6bdestradaa        // TODO: use the source if needed in the future
4750682809ad08db284d7110aab44108d5e9c310e6bdestradaa        setMonitorAvailability(monitoringType, monitoringStatus);
4768ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        acquireWakeLock();
4770682809ad08db284d7110aab44108d5e9c310e6bdestradaa        Message message = mCallbacksHandler.obtainMessage(GEOFENCE_STATUS, location);
4780682809ad08db284d7110aab44108d5e9c310e6bdestradaa        message.arg1 = monitoringStatus;
4790682809ad08db284d7110aab44108d5e9c310e6bdestradaa        message.arg2 = monitoringType;
4800682809ad08db284d7110aab44108d5e9c310e6bdestradaa        message.sendToTarget();
4818ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
4828ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
4838ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
4840682809ad08db284d7110aab44108d5e9c310e6bdestradaa     * Internal generic status report function for Geofence operations.
4850682809ad08db284d7110aab44108d5e9c310e6bdestradaa     *
4860682809ad08db284d7110aab44108d5e9c310e6bdestradaa     * @param operation The operation to be reported as defined internally.
4870682809ad08db284d7110aab44108d5e9c310e6bdestradaa     * @param geofenceId The id of the geofence the operation is related to.
4880682809ad08db284d7110aab44108d5e9c310e6bdestradaa     * @param operationStatus The status of the operation as defined in GeofenceHardware class. This
4890682809ad08db284d7110aab44108d5e9c310e6bdestradaa     *                        status is independent of the statuses reported by different HALs.
4908ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
4910682809ad08db284d7110aab44108d5e9c310e6bdestradaa    private void reportGeofenceOperationStatus(int operation, int geofenceId, int operationStatus) {
4928ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        acquireWakeLock();
4930682809ad08db284d7110aab44108d5e9c310e6bdestradaa        Message message = mGeofenceHandler.obtainMessage(operation);
4940682809ad08db284d7110aab44108d5e9c310e6bdestradaa        message.arg1 = geofenceId;
4950682809ad08db284d7110aab44108d5e9c310e6bdestradaa        message.arg2 = operationStatus;
4960682809ad08db284d7110aab44108d5e9c310e6bdestradaa        message.sendToTarget();
4978ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
4988ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
4998ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
5000682809ad08db284d7110aab44108d5e9c310e6bdestradaa     * Used to report the status of a Geofence Add operation.
5018ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
5020682809ad08db284d7110aab44108d5e9c310e6bdestradaa    public void reportGeofenceAddStatus(int geofenceId, int status) {
5030682809ad08db284d7110aab44108d5e9c310e6bdestradaa        if(DEBUG) Log.d(TAG, "AddCallback| id:" + geofenceId + ", status:" + status);
5040682809ad08db284d7110aab44108d5e9c310e6bdestradaa        reportGeofenceOperationStatus(ADD_GEOFENCE_CALLBACK, geofenceId, status);
5058ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
5068ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
5078ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
5080682809ad08db284d7110aab44108d5e9c310e6bdestradaa     * Used to report the status of a Geofence Remove operation.
5098ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
5100682809ad08db284d7110aab44108d5e9c310e6bdestradaa    public void reportGeofenceRemoveStatus(int geofenceId, int status) {
5110682809ad08db284d7110aab44108d5e9c310e6bdestradaa        if(DEBUG) Log.d(TAG, "RemoveCallback| id:" + geofenceId + ", status:" + status);
5120682809ad08db284d7110aab44108d5e9c310e6bdestradaa        reportGeofenceOperationStatus(REMOVE_GEOFENCE_CALLBACK, geofenceId, status);
5138ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
5148ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
5158ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
5160682809ad08db284d7110aab44108d5e9c310e6bdestradaa     * Used to report the status of a Geofence Pause operation.
5178ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
5180682809ad08db284d7110aab44108d5e9c310e6bdestradaa    public void reportGeofencePauseStatus(int geofenceId, int status) {
5190682809ad08db284d7110aab44108d5e9c310e6bdestradaa        if(DEBUG) Log.d(TAG, "PauseCallbac| id:" + geofenceId + ", status" + status);
5200682809ad08db284d7110aab44108d5e9c310e6bdestradaa        reportGeofenceOperationStatus(PAUSE_GEOFENCE_CALLBACK, geofenceId, status);
5218ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
5228ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
5238ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
5240682809ad08db284d7110aab44108d5e9c310e6bdestradaa     * Used to report the status of a Geofence Resume operation.
5258ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
5260682809ad08db284d7110aab44108d5e9c310e6bdestradaa    public void reportGeofenceResumeStatus(int geofenceId, int status) {
5270682809ad08db284d7110aab44108d5e9c310e6bdestradaa        if(DEBUG) Log.d(TAG, "ResumeCallback| id:" + geofenceId + ", status:" + status);
5280682809ad08db284d7110aab44108d5e9c310e6bdestradaa        reportGeofenceOperationStatus(RESUME_GEOFENCE_CALLBACK, geofenceId, status);
5298ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
5308ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
5318ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    // All operations on mGeofences
5328ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private Handler mGeofenceHandler = new Handler() {
5338ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        @Override
5348ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        public void handleMessage(Message msg) {
5358ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            int geofenceId;
5368ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            int status;
5378ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            IGeofenceHardwareCallback callback;
5388ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            switch (msg.what) {
5398ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                case ADD_GEOFENCE_CALLBACK:
5408ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    geofenceId = msg.arg1;
541f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    synchronized (mGeofences) {
542f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                        callback = mGeofences.get(geofenceId);
543f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    }
5448ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
545cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                    if (callback != null) {
546cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        try {
547cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                            callback.onGeofenceAdd(geofenceId, msg.arg2);
548cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        } catch (RemoteException e) {Log.i(TAG, "Remote Exception:" + e);}
549cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                    }
5508ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    releaseWakeLock();
5518ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    break;
5528ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                case REMOVE_GEOFENCE_CALLBACK:
5538ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    geofenceId = msg.arg1;
554f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    synchronized (mGeofences) {
555f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                        callback = mGeofences.get(geofenceId);
556f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    }
5578ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
558cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                    if (callback != null) {
559cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        try {
560cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                            callback.onGeofenceRemove(geofenceId, msg.arg2);
561cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        } catch (RemoteException e) {}
562cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        synchronized (mGeofences) {
563cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                            mGeofences.remove(geofenceId);
564cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        }
565f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    }
5668ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    releaseWakeLock();
5678ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    break;
5688ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
5698ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                case PAUSE_GEOFENCE_CALLBACK:
5708ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    geofenceId = msg.arg1;
571f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    synchronized (mGeofences) {
572f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                        callback = mGeofences.get(geofenceId);
573f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    }
5748ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
575cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                    if (callback != null) {
576cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        try {
577cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                            callback.onGeofencePause(geofenceId, msg.arg2);
578cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        } catch (RemoteException e) {}
579cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                    }
5808ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    releaseWakeLock();
5818ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    break;
5828ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
5838ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                case RESUME_GEOFENCE_CALLBACK:
5848ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    geofenceId = msg.arg1;
585f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    synchronized (mGeofences) {
586f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                        callback = mGeofences.get(geofenceId);
587f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    }
5888ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
589cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                    if (callback != null) {
590cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        try {
591cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                            callback.onGeofenceResume(geofenceId, msg.arg2);
592cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        } catch (RemoteException e) {}
593cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                    }
5948ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    releaseWakeLock();
5958ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    break;
5968ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
5978ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                case GEOFENCE_TRANSITION_CALLBACK:
5988ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    GeofenceTransition geofenceTransition = (GeofenceTransition)(msg.obj);
599f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                    synchronized (mGeofences) {
600f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                        callback = mGeofences.get(geofenceTransition.mGeofenceId);
6018ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
6027f02eb2c84c0a39e6357aca10a4fda1dd090a8a6destradaa                        // need to keep access to mGeofences synchronized at all times
6037f02eb2c84c0a39e6357aca10a4fda1dd090a8a6destradaa                        if (DEBUG) Log.d(TAG, "GeofenceTransistionCallback: GPS : GeofenceId: " +
6047f02eb2c84c0a39e6357aca10a4fda1dd090a8a6destradaa                                geofenceTransition.mGeofenceId +
6057f02eb2c84c0a39e6357aca10a4fda1dd090a8a6destradaa                                " Transition: " + geofenceTransition.mTransition +
6067f02eb2c84c0a39e6357aca10a4fda1dd090a8a6destradaa                                " Location: " + geofenceTransition.mLocation + ":" + mGeofences);
6077f02eb2c84c0a39e6357aca10a4fda1dd090a8a6destradaa                    }
6088ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
609cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                    if (callback != null) {
610cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        try {
611cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                            callback.onGeofenceTransition(
612cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                                    geofenceTransition.mGeofenceId, geofenceTransition.mTransition,
613cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                                    geofenceTransition.mLocation, geofenceTransition.mTimestamp,
6140682809ad08db284d7110aab44108d5e9c310e6bdestradaa                                    geofenceTransition.mMonitoringType);
615cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        } catch (RemoteException e) {}
616cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                    }
6178ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    releaseWakeLock();
6188ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    break;
619da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                case GEOFENCE_CALLBACK_BINDER_DIED:
620da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                   // Find all geofences associated with this callback and remove them.
621da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                   callback = (IGeofenceHardwareCallback) (msg.obj);
622da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                   if (DEBUG) Log.d(TAG, "Geofence callback reaped:" + callback);
623da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                   int monitoringType = msg.arg1;
624f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                   synchronized (mGeofences) {
625f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                       for (int i = 0; i < mGeofences.size(); i++) {
626f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                            if (mGeofences.valueAt(i).equals(callback)) {
627f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                                geofenceId = mGeofences.keyAt(i);
628f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                                removeGeofence(mGeofences.keyAt(i), monitoringType);
629f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                                mGeofences.remove(geofenceId);
630f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                            }
631f8f085c51b5f8b180ad964d0385b34f8fa97cd32Zhentao Sun                       }
632da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                   }
6338ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            }
6348ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
6358ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    };
6368ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
6378ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    // All operations on mCallbacks
6388ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private Handler mCallbacksHandler = new Handler() {
6398ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        @Override
6408ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        public void handleMessage(Message msg) {
6418ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            int monitoringType;
642da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            ArrayList<IGeofenceHardwareMonitorCallback> callbackList;
643da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            IGeofenceHardwareMonitorCallback callback;
6448ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
6458ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            switch (msg.what) {
6460682809ad08db284d7110aab44108d5e9c310e6bdestradaa                case GEOFENCE_STATUS:
6478ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    Location location = (Location) msg.obj;
6488ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    int val = msg.arg1;
6490682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    monitoringType = msg.arg2;
6508ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    boolean available;
6518ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    available = (val == GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE ?
6528ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                            true : false);
6530682809ad08db284d7110aab44108d5e9c310e6bdestradaa                    callbackList = mCallbacks[monitoringType];
654cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                    if (callbackList != null) {
655cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        if (DEBUG) Log.d(TAG, "MonitoringSystemChangeCallback: GPS : " + available);
656cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun
657cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        for (IGeofenceHardwareMonitorCallback c: callbackList) {
658cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                            try {
6590682809ad08db284d7110aab44108d5e9c310e6bdestradaa                                c.onMonitoringSystemChange(monitoringType, available, location);
660cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                            } catch (RemoteException e) {}
661cfa496f7cdc52711e9ad7521224f67d1aaee002cZhentao Sun                        }
6628ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    }
6638ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    releaseWakeLock();
6648ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    break;
6658ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                case CALLBACK_ADD:
6668ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    monitoringType = msg.arg1;
667da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    callback = (IGeofenceHardwareMonitorCallback) msg.obj;
6688ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    callbackList = mCallbacks[monitoringType];
6698ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    if (callbackList == null) {
670da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                        callbackList = new ArrayList<IGeofenceHardwareMonitorCallback>();
6718ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                        mCallbacks[monitoringType] = callbackList;
6728ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    }
6738ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    if (!callbackList.contains(callback)) callbackList.add(callback);
6748ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    break;
6758ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                case CALLBACK_REMOVE:
6768ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    monitoringType = msg.arg1;
677da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    callback = (IGeofenceHardwareMonitorCallback) msg.obj;
6788ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    callbackList = mCallbacks[monitoringType];
6798ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    if (callbackList != null) {
6808ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                        callbackList.remove(callback);
6818ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    }
6828ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    break;
683da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                case MONITOR_CALLBACK_BINDER_DIED:
684da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    callback = (IGeofenceHardwareMonitorCallback) msg.obj;
685da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    if (DEBUG) Log.d(TAG, "Monitor callback reaped:" + callback);
686da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    callbackList = mCallbacks[msg.arg1];
687da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    if (callbackList != null && callbackList.contains(callback)) {
688da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                        callbackList.remove(callback);
689da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    }
690da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            }
691da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        }
692da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    };
693da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
694da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    // All operations on mReaper
695da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    private Handler mReaperHandler = new Handler() {
696da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        @Override
697da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        public void handleMessage(Message msg) {
698da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            Reaper r;
699da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            IGeofenceHardwareCallback callback;
700da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            IGeofenceHardwareMonitorCallback monitorCallback;
701da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            int monitoringType;
702da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
703da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            switch (msg.what) {
704da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                case REAPER_GEOFENCE_ADDED:
705da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    callback = (IGeofenceHardwareCallback) msg.obj;
706da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    monitoringType = msg.arg1;
707da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    r = new Reaper(callback, monitoringType);
708da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    if (!mReapers.contains(r)) {
709da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                        mReapers.add(r);
710da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                        IBinder b = callback.asBinder();
711da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                        try {
712da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                            b.linkToDeath(r, 0);
713da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                        } catch (RemoteException e) {}
714da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    }
715da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    break;
716da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                case REAPER_MONITOR_CALLBACK_ADDED:
717da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    monitorCallback = (IGeofenceHardwareMonitorCallback) msg.obj;
718da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    monitoringType = msg.arg1;
719da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
720da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    r = new Reaper(monitorCallback, monitoringType);
721da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    if (!mReapers.contains(r)) {
722da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                        mReapers.add(r);
723da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                        IBinder b = monitorCallback.asBinder();
724da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                        try {
725da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                            b.linkToDeath(r, 0);
726da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                        } catch (RemoteException e) {}
727da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    }
728da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    break;
729da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                case REAPER_REMOVED:
730da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    r = (Reaper) msg.obj;
731da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    mReapers.remove(r);
7328ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            }
7338ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
7348ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    };
7358ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
7368ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private class GeofenceTransition {
7378ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        private int mGeofenceId, mTransition;
7388ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        private long mTimestamp;
7398ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        private Location mLocation;
7400682809ad08db284d7110aab44108d5e9c310e6bdestradaa        private int mMonitoringType;
7410682809ad08db284d7110aab44108d5e9c310e6bdestradaa        private int mSourcesUsed;
7420682809ad08db284d7110aab44108d5e9c310e6bdestradaa
7430682809ad08db284d7110aab44108d5e9c310e6bdestradaa        GeofenceTransition(
7440682809ad08db284d7110aab44108d5e9c310e6bdestradaa                int geofenceId,
7450682809ad08db284d7110aab44108d5e9c310e6bdestradaa                int transition,
7460682809ad08db284d7110aab44108d5e9c310e6bdestradaa                long timestamp,
7470682809ad08db284d7110aab44108d5e9c310e6bdestradaa                Location location,
7480682809ad08db284d7110aab44108d5e9c310e6bdestradaa                int monitoringType,
7490682809ad08db284d7110aab44108d5e9c310e6bdestradaa                int sourcesUsed) {
7508ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mGeofenceId = geofenceId;
7518ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mTransition = transition;
7528ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mTimestamp = timestamp;
7538ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mLocation = location;
7540682809ad08db284d7110aab44108d5e9c310e6bdestradaa            mMonitoringType = monitoringType;
7550682809ad08db284d7110aab44108d5e9c310e6bdestradaa            mSourcesUsed = sourcesUsed;
7568ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
7578ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
7588ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
7598ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private void setMonitorAvailability(int monitor, int val) {
7608ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        synchronized (mSupportedMonitorTypes) {
7618ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mSupportedMonitorTypes[monitor] = val;
7628ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
7638ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
7648ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
7658ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
7668ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    int getMonitoringResolutionLevel(int monitoringType) {
7678ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        switch (monitoringType) {
7688ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
7698ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                return RESOLUTION_LEVEL_FINE;
7700682809ad08db284d7110aab44108d5e9c310e6bdestradaa            case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
7710682809ad08db284d7110aab44108d5e9c310e6bdestradaa                return RESOLUTION_LEVEL_FINE;
7728ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
7738ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        return RESOLUTION_LEVEL_NONE;
7748ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
7758ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
776da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    class Reaper implements IBinder.DeathRecipient {
777da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        private IGeofenceHardwareMonitorCallback mMonitorCallback;
778da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        private IGeofenceHardwareCallback mCallback;
779da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        private int mMonitoringType;
780da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
781da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        Reaper(IGeofenceHardwareCallback c, int monitoringType) {
782da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            mCallback = c;
783da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            mMonitoringType = monitoringType;
784da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        }
785da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
786da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        Reaper(IGeofenceHardwareMonitorCallback c, int monitoringType) {
787da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            mMonitorCallback = c;
788da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            mMonitoringType = monitoringType;
789da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        }
790da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
791da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        @Override
792da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        public void binderDied() {
793da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            Message m;
794da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            if (mCallback != null) {
795da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                m = mGeofenceHandler.obtainMessage(GEOFENCE_CALLBACK_BINDER_DIED, mCallback);
796da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                m.arg1 = mMonitoringType;
797da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                mGeofenceHandler.sendMessage(m);
798da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            } else if (mMonitorCallback != null) {
799da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                m = mCallbacksHandler.obtainMessage(MONITOR_CALLBACK_BINDER_DIED, mMonitorCallback);
800da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                m.arg1 = mMonitoringType;
801da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                mCallbacksHandler.sendMessage(m);
802da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            }
803da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            Message reaperMessage = mReaperHandler.obtainMessage(REAPER_REMOVED, this);
804da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            mReaperHandler.sendMessage(reaperMessage);
805da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        }
806da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
807da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        @Override
808da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        public int hashCode() {
809da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            int result = 17;
810da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            result = 31 * result + (mCallback != null ? mCallback.hashCode() : 0);
811da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            result = 31 * result + (mMonitorCallback != null ? mMonitorCallback.hashCode() : 0);
812da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            result = 31 * result + mMonitoringType;
813da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            return result;
814da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        }
815da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
816da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        @Override
817da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        public boolean equals(Object obj) {
818da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            if (obj == null) return false;
819da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            if (obj == this) return true;
820da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
821da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            Reaper rhs = (Reaper) obj;
822da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh            return rhs.mCallback == mCallback && rhs.mMonitorCallback == mMonitorCallback &&
823da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh                    rhs.mMonitoringType == mMonitoringType;
824da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh        }
825da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh    }
826da6508954a492f3dd4397e70e4fa08ee54bd2741Jaikumar Ganesh
8278ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    int getAllowedResolutionLevel(int pid, int uid) {
8288ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
8298ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                pid, uid) == PackageManager.PERMISSION_GRANTED) {
8308ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            return RESOLUTION_LEVEL_FINE;
8318ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
8328ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                pid, uid) == PackageManager.PERMISSION_GRANTED) {
8338ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            return RESOLUTION_LEVEL_COARSE;
8348ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        } else {
8358ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            return RESOLUTION_LEVEL_NONE;
8368ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
8378ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
8388ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh}
839