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 Ganeshpackage com.android.server.location; 178ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 188ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.content.ComponentName; 198ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.content.Intent; 208ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.content.ServiceConnection; 218ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.hardware.location.GeofenceHardwareService; 228ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.hardware.location.IGeofenceHardware; 238ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.location.IGeofenceProvider; 248ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.location.IGpsGeofenceHardware; 250682809ad08db284d7110aab44108d5e9c310e6bdestradaaimport android.location.IFusedGeofenceHardware; 268ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.content.Context; 278ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.os.Handler; 288ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.os.IBinder; 298ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.os.Message; 308ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.os.RemoteException; 318ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.os.UserHandle; 328ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.util.Log; 338ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport com.android.server.ServiceWatcher; 348ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 358ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh/** 368ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh * @hide 378ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh */ 388ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshpublic final class GeofenceProxy { 398ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private static final String TAG = "GeofenceProxy"; 408ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private static final String SERVICE_ACTION = 418ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh "com.android.location.service.GeofenceProvider"; 42d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun private final ServiceWatcher mServiceWatcher; 43d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun private final Context mContext; 44d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun private final IGpsGeofenceHardware mGpsGeofenceHardware; 45d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun private final IFusedGeofenceHardware mFusedGeofenceHardware; 46d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun 47d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun private final Object mLock = new Object(); 48d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun 49d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun // Access to mGeofenceHardware needs to be synchronized by mLock. 508ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private IGeofenceHardware mGeofenceHardware; 518ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 528ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private static final int GEOFENCE_PROVIDER_CONNECTED = 1; 538ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private static final int GEOFENCE_HARDWARE_CONNECTED = 2; 548ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private static final int GEOFENCE_HARDWARE_DISCONNECTED = 3; 558ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private static final int GEOFENCE_GPS_HARDWARE_CONNECTED = 4; 568ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private static final int GEOFENCE_GPS_HARDWARE_DISCONNECTED = 5; 578ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 588ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private Runnable mRunnable = new Runnable() { 598ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh @Override 608ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh public void run() { 618ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh mHandler.sendEmptyMessage(GEOFENCE_PROVIDER_CONNECTED); 628ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 638ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh }; 648ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 658ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh public static GeofenceProxy createAndBind(Context context, 66c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun int overlaySwitchResId, int defaultServicePackageNameResId, 670682809ad08db284d7110aab44108d5e9c310e6bdestradaa int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence, 680682809ad08db284d7110aab44108d5e9c310e6bdestradaa IFusedGeofenceHardware fusedGeofenceHardware) { 69c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun GeofenceProxy proxy = new GeofenceProxy(context, overlaySwitchResId, 700682809ad08db284d7110aab44108d5e9c310e6bdestradaa defaultServicePackageNameResId, initialPackageNamesResId, handler, gpsGeofence, 710682809ad08db284d7110aab44108d5e9c310e6bdestradaa fusedGeofenceHardware); 728ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh if (proxy.bindGeofenceProvider()) { 738ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh return proxy; 748ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } else { 758ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh return null; 768ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 778ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 788ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 79c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun private GeofenceProxy(Context context, 80c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun int overlaySwitchResId, int defaultServicePackageNameResId, 810682809ad08db284d7110aab44108d5e9c310e6bdestradaa int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence, 820682809ad08db284d7110aab44108d5e9c310e6bdestradaa IFusedGeofenceHardware fusedGeofenceHardware) { 838ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh mContext = context; 84c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId, 85c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun defaultServicePackageNameResId, initialPackageNamesResId, mRunnable, handler); 868ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh mGpsGeofenceHardware = gpsGeofence; 870682809ad08db284d7110aab44108d5e9c310e6bdestradaa mFusedGeofenceHardware = fusedGeofenceHardware; 888ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh bindHardwareGeofence(); 898ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 908ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 918ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private boolean bindGeofenceProvider() { 928ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh return mServiceWatcher.start(); 938ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 948ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 958ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private void bindHardwareGeofence() { 968ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh mContext.bindServiceAsUser(new Intent(mContext, GeofenceHardwareService.class), 978ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh mServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.OWNER); 988ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 998ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 1008ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private ServiceConnection mServiceConnection = new ServiceConnection() { 1018ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh @Override 1028ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh public void onServiceConnected(ComponentName name, IBinder service) { 103d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun synchronized (mLock) { 104d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun mGeofenceHardware = IGeofenceHardware.Stub.asInterface(service); 105d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun mHandler.sendEmptyMessage(GEOFENCE_HARDWARE_CONNECTED); 106d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun } 1078ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 1088ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 1098ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh @Override 1108ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh public void onServiceDisconnected(ComponentName name) { 111d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun synchronized (mLock) { 112d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun mGeofenceHardware = null; 113d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun mHandler.sendEmptyMessage(GEOFENCE_HARDWARE_DISCONNECTED); 114d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun } 1158ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 1168ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh }; 1178ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 118d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun private void setGeofenceHardwareInProviderLocked() { 1198ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh try { 120d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun IGeofenceProvider provider = IGeofenceProvider.Stub.asInterface( 121d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun mServiceWatcher.getBinder()); 122d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun if (provider != null) { 123d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun provider.setGeofenceHardware(mGeofenceHardware); 124d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun } 1258ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } catch (RemoteException e) { 126d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun Log.e(TAG, "Remote Exception: setGeofenceHardwareInProviderLocked: " + e); 1278ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 1288ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 1298ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 130d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun private void setGpsGeofenceLocked() { 1318ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh try { 1325241a4cb55b4015549242ac7d8aa5c99e5f157e5Wei Liu if (mGpsGeofenceHardware != null) { 1335241a4cb55b4015549242ac7d8aa5c99e5f157e5Wei Liu mGeofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware); 1345241a4cb55b4015549242ac7d8aa5c99e5f157e5Wei Liu } 1358ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } catch (RemoteException e) { 1368ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh Log.e(TAG, "Error while connecting to GeofenceHardwareService"); 1378ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 1388ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 1398ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 140d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun private void setFusedGeofenceLocked() { 1410682809ad08db284d7110aab44108d5e9c310e6bdestradaa try { 1420682809ad08db284d7110aab44108d5e9c310e6bdestradaa mGeofenceHardware.setFusedGeofenceHardware(mFusedGeofenceHardware); 1430682809ad08db284d7110aab44108d5e9c310e6bdestradaa } catch(RemoteException e) { 1440682809ad08db284d7110aab44108d5e9c310e6bdestradaa Log.e(TAG, "Error while connecting to GeofenceHardwareService"); 1450682809ad08db284d7110aab44108d5e9c310e6bdestradaa } 1460682809ad08db284d7110aab44108d5e9c310e6bdestradaa } 1478ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 1488ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh // This needs to be reworked, when more services get added, 1498ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh // Might need a state machine or add a framework utility class, 1508ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh private Handler mHandler = new Handler() { 1518ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh 1528ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh @Override 1538ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh public void handleMessage(Message msg) { 1548ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh switch (msg.what) { 1558ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh case GEOFENCE_PROVIDER_CONNECTED: 156d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun synchronized (mLock) { 157d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun if (mGeofenceHardware != null) { 158d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun setGeofenceHardwareInProviderLocked(); 159d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun } 160d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun // else: the geofence provider will be notified when the connection to 161d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun // GeofenceHardwareService is established. 1628ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 1638ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh break; 1648ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh case GEOFENCE_HARDWARE_CONNECTED: 165d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun synchronized (mLock) { 166d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun // Theoretically this won't happen because once the GeofenceHardwareService 167d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun // is connected to, we won't lose connection to it because it's a system 168d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun // service. But this check does make the code more robust. 169d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun if (mGeofenceHardware != null) { 170d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun setGpsGeofenceLocked(); 171d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun setFusedGeofenceLocked(); 172d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun setGeofenceHardwareInProviderLocked(); 173d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun } 1748ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 1758ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh break; 1768ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh case GEOFENCE_HARDWARE_DISCONNECTED: 177d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun synchronized (mLock) { 178d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun if (mGeofenceHardware == null) { 179d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun setGeofenceHardwareInProviderLocked(); 180d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun } 181d535ead295abf3b74afb6450c83bd197f69c5a26Zhentao Sun } 1828ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh break; 1838ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 1848ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh } 1858ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh }; 1868ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh} 187