/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.location; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.hardware.location.GeofenceHardwareService; import android.hardware.location.IGeofenceHardware; import android.location.IFusedGeofenceHardware; import android.location.IGeofenceProvider; import android.location.IGpsGeofenceHardware; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import com.android.server.FgThread; import com.android.server.ServiceWatcher; /** * @hide */ public final class GeofenceProxy { private static final String TAG = "GeofenceProxy"; private static final String SERVICE_ACTION = "com.android.location.service.GeofenceProvider"; private final Context mContext; private final ServiceWatcher mServiceWatcher; @Nullable private final IGpsGeofenceHardware mGpsGeofenceHardware; @Nullable private final IFusedGeofenceHardware mFusedGeofenceHardware; private volatile IGeofenceHardware mGeofenceHardware; private final ServiceWatcher.BinderRunner mUpdateGeofenceHardware = (binder) -> { IGeofenceProvider provider = IGeofenceProvider.Stub.asInterface(binder); try { provider.setGeofenceHardware(mGeofenceHardware); } catch (RemoteException e) { Log.w(TAG, e); } }; public static GeofenceProxy createAndBind(Context context, int overlaySwitchResId, int defaultServicePackageNameResId, int initialPackageNamesResId, @Nullable IGpsGeofenceHardware gpsGeofence, @Nullable IFusedGeofenceHardware fusedGeofenceHardware) { GeofenceProxy proxy = new GeofenceProxy(context, overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId, gpsGeofence, fusedGeofenceHardware); if (proxy.bind()) { return proxy; } else { return null; } } private GeofenceProxy(Context context, int overlaySwitchResId, int defaultServicePackageNameResId, int initialPackageNamesResId, @Nullable IGpsGeofenceHardware gpsGeofence, @Nullable IFusedGeofenceHardware fusedGeofenceHardware) { mContext = context; mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId, FgThread.getHandler()) { @Override protected void onBind() { runOnBinder(mUpdateGeofenceHardware); } }; mGpsGeofenceHardware = gpsGeofence; mFusedGeofenceHardware = fusedGeofenceHardware; mGeofenceHardware = null; } private boolean bind() { if (mServiceWatcher.start()) { mContext.bindServiceAsUser(new Intent(mContext, GeofenceHardwareService.class), new GeofenceProxyServiceConnection(), Context.BIND_AUTO_CREATE, UserHandle.SYSTEM); return true; } return false; } private class GeofenceProxyServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { IGeofenceHardware geofenceHardware = IGeofenceHardware.Stub.asInterface(service); try { if (mGpsGeofenceHardware != null) { geofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware); } if (mFusedGeofenceHardware != null) { geofenceHardware.setFusedGeofenceHardware(mFusedGeofenceHardware); } mGeofenceHardware = geofenceHardware; mServiceWatcher.runOnBinder(mUpdateGeofenceHardware); } catch (Exception e) { Log.w(TAG, e); } } @Override public void onServiceDisconnected(ComponentName name) { mGeofenceHardware = null; mServiceWatcher.runOnBinder(mUpdateGeofenceHardware); } } }