Home | History | Annotate | Download | only in location
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.server.location;
     17 
     18 import android.content.ComponentName;
     19 import android.content.Intent;
     20 import android.content.ServiceConnection;
     21 import android.hardware.location.GeofenceHardwareService;
     22 import android.hardware.location.IGeofenceHardware;
     23 import android.location.IGeofenceProvider;
     24 import android.location.IGpsGeofenceHardware;
     25 import android.content.Context;
     26 import android.os.Handler;
     27 import android.os.IBinder;
     28 import android.os.Message;
     29 import android.os.RemoteException;
     30 import android.os.UserHandle;
     31 import android.util.Log;
     32 import com.android.server.ServiceWatcher;
     33 
     34 import java.util.List;
     35 
     36 /**
     37  * @hide
     38  */
     39 public final class GeofenceProxy {
     40     private static final String TAG = "GeofenceProxy";
     41     private static final String SERVICE_ACTION =
     42             "com.android.location.service.GeofenceProvider";
     43     private ServiceWatcher mServiceWatcher;
     44     private Context mContext;
     45     private IGeofenceHardware mGeofenceHardware;
     46     private IGpsGeofenceHardware mGpsGeofenceHardware;
     47 
     48     private static final int GEOFENCE_PROVIDER_CONNECTED = 1;
     49     private static final int GEOFENCE_HARDWARE_CONNECTED = 2;
     50     private static final int GEOFENCE_HARDWARE_DISCONNECTED = 3;
     51     private static final int GEOFENCE_GPS_HARDWARE_CONNECTED = 4;
     52     private static final int GEOFENCE_GPS_HARDWARE_DISCONNECTED = 5;
     53 
     54     private Runnable mRunnable = new Runnable() {
     55         @Override
     56         public void run() {
     57             mHandler.sendEmptyMessage(GEOFENCE_PROVIDER_CONNECTED);
     58         }
     59     };
     60 
     61     public static GeofenceProxy createAndBind(Context context,
     62             int overlaySwitchResId, int defaultServicePackageNameResId,
     63             int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence) {
     64         GeofenceProxy proxy = new GeofenceProxy(context, overlaySwitchResId,
     65             defaultServicePackageNameResId, initialPackageNamesResId, handler, gpsGeofence);
     66         if (proxy.bindGeofenceProvider()) {
     67             return proxy;
     68         } else {
     69             return null;
     70         }
     71     }
     72 
     73     private GeofenceProxy(Context context,
     74             int overlaySwitchResId, int defaultServicePackageNameResId,
     75             int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence) {
     76         mContext = context;
     77         mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
     78             defaultServicePackageNameResId, initialPackageNamesResId, mRunnable, handler);
     79         mGpsGeofenceHardware = gpsGeofence;
     80         bindHardwareGeofence();
     81     }
     82 
     83     private boolean bindGeofenceProvider() {
     84         return mServiceWatcher.start();
     85     }
     86 
     87     private IGeofenceProvider getGeofenceProviderService() {
     88         return IGeofenceProvider.Stub.asInterface(mServiceWatcher.getBinder());
     89     }
     90 
     91     private void bindHardwareGeofence() {
     92         mContext.bindServiceAsUser(new Intent(mContext, GeofenceHardwareService.class),
     93                 mServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.OWNER);
     94     }
     95 
     96     private ServiceConnection mServiceConnection = new ServiceConnection() {
     97         @Override
     98         public void onServiceConnected(ComponentName name, IBinder service) {
     99             mGeofenceHardware = IGeofenceHardware.Stub.asInterface(service);
    100             mHandler.sendEmptyMessage(GEOFENCE_HARDWARE_CONNECTED);
    101         }
    102 
    103         @Override
    104         public void onServiceDisconnected(ComponentName name) {
    105             mGeofenceHardware = null;
    106             mHandler.sendEmptyMessage(GEOFENCE_HARDWARE_DISCONNECTED);
    107         }
    108     };
    109 
    110     private void setGeofenceHardwareInProvider() {
    111         try {
    112             getGeofenceProviderService().setGeofenceHardware(mGeofenceHardware);
    113         } catch (RemoteException e) {
    114             Log.e(TAG, "Remote Exception: setGeofenceHardwareInProvider: " + e);
    115         }
    116     }
    117 
    118     private void setGpsGeofence() {
    119         try {
    120             mGeofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware);
    121         } catch (RemoteException e) {
    122             Log.e(TAG, "Error while connecting to GeofenceHardwareService");
    123         }
    124     }
    125 
    126 
    127     // This needs to be reworked, when more services get added,
    128     // Might need a state machine or add a framework utility class,
    129     private Handler mHandler = new Handler() {
    130         private boolean mGeofenceHardwareConnected = false;
    131         private boolean mGeofenceProviderConnected = false;
    132 
    133 
    134         @Override
    135         public void handleMessage(Message msg) {
    136             switch (msg.what) {
    137                 case GEOFENCE_PROVIDER_CONNECTED:
    138                     mGeofenceProviderConnected = true;
    139                     if (mGeofenceHardwareConnected) {
    140                         setGeofenceHardwareInProvider();
    141                     }
    142                     break;
    143                 case GEOFENCE_HARDWARE_CONNECTED:
    144                     setGpsGeofence();
    145                     mGeofenceHardwareConnected = true;
    146                     if (mGeofenceProviderConnected) {
    147                         setGeofenceHardwareInProvider();
    148                     }
    149                     break;
    150                 case GEOFENCE_HARDWARE_DISCONNECTED:
    151                     mGeofenceHardwareConnected = false;
    152                     setGeofenceHardwareInProvider();
    153                     break;
    154             }
    155         }
    156     };
    157 }
    158