• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 
17 package com.android.server.location;
18 
19 import java.io.FileDescriptor;
20 import java.io.PrintWriter;
21 import java.util.List;
22 
23 import android.content.Context;
24 import android.location.LocationProvider;
25 import android.os.Bundle;
26 import android.os.Handler;
27 import android.os.RemoteException;
28 import android.os.WorkSource;
29 import android.util.Log;
30 
31 import com.android.internal.location.ProviderProperties;
32 import com.android.internal.location.ILocationProvider;
33 import com.android.internal.location.ProviderRequest;
34 import com.android.server.LocationManagerService;
35 import com.android.server.ServiceWatcher;
36 
37 /**
38  * Proxy for ILocationProvider implementations.
39  */
40 public class LocationProviderProxy implements LocationProviderInterface {
41     private static final String TAG = "LocationProviderProxy";
42     private static final boolean D = LocationManagerService.D;
43 
44     private final Context mContext;
45     private final String mName;
46     private final ServiceWatcher mServiceWatcher;
47 
48     private Object mLock = new Object();
49 
50     // cached values set by the location manager, synchronized on mLock
51     private ProviderProperties mProperties;
52     private boolean mEnabled = false;
53     private ProviderRequest mRequest = null;
54     private WorkSource mWorksource = new WorkSource();
55 
createAndBind( Context context, String name, String action, int overlaySwitchResId, int defaultServicePackageNameResId, int initialPackageNamesResId, Handler handler)56     public static LocationProviderProxy createAndBind(
57             Context context, String name, String action,
58             int overlaySwitchResId, int defaultServicePackageNameResId,
59             int initialPackageNamesResId, Handler handler) {
60         LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,
61                 overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId,
62                 handler);
63         if (proxy.bind()) {
64             return proxy;
65         } else {
66             return null;
67         }
68     }
69 
LocationProviderProxy(Context context, String name, String action, int overlaySwitchResId, int defaultServicePackageNameResId, int initialPackageNamesResId, Handler handler)70     private LocationProviderProxy(Context context, String name, String action,
71             int overlaySwitchResId, int defaultServicePackageNameResId,
72             int initialPackageNamesResId, Handler handler) {
73         mContext = context;
74         mName = name;
75         mServiceWatcher = new ServiceWatcher(mContext, TAG + "-" + name, action, overlaySwitchResId,
76                 defaultServicePackageNameResId, initialPackageNamesResId,
77                 mNewServiceWork, handler);
78     }
79 
bind()80     private boolean bind () {
81         return mServiceWatcher.start();
82     }
83 
getService()84     private ILocationProvider getService() {
85         return ILocationProvider.Stub.asInterface(mServiceWatcher.getBinder());
86     }
87 
getConnectedPackageName()88     public String getConnectedPackageName() {
89         return mServiceWatcher.getBestPackageName();
90     }
91 
92     /**
93      * Work to apply current state to a newly connected provider.
94      * Remember we can switch the service that implements a providers
95      * at run-time, so need to apply current state.
96      */
97     private Runnable mNewServiceWork = new Runnable() {
98         @Override
99         public void run() {
100             if (D) Log.d(TAG, "applying state to connected service");
101 
102             boolean enabled;
103             ProviderProperties properties = null;
104             ProviderRequest request;
105             WorkSource source;
106             ILocationProvider service;
107             synchronized (mLock) {
108                 enabled = mEnabled;
109                 request = mRequest;
110                 source = mWorksource;
111                 service = getService();
112             }
113 
114             if (service == null) return;
115 
116             try {
117                 // load properties from provider
118                 properties = service.getProperties();
119                 if (properties == null) {
120                     Log.e(TAG, mServiceWatcher.getBestPackageName() +
121                             " has invalid locatino provider properties");
122                 }
123 
124                 // apply current state to new service
125                 if (enabled) {
126                     service.enable();
127                     if (request != null) {
128                         service.setRequest(request, source);
129                     }
130                 }
131             } catch (RemoteException e) {
132                 Log.w(TAG, e);
133             } catch (Exception e) {
134                 // never let remote service crash system server
135                 Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
136             }
137 
138             synchronized (mLock) {
139                 mProperties = properties;
140             }
141         }
142     };
143 
144     @Override
getName()145     public String getName() {
146         return mName;
147     }
148 
149     @Override
getProperties()150     public ProviderProperties getProperties() {
151         synchronized (mLock) {
152             return mProperties;
153         }
154     }
155 
156     @Override
enable()157     public void enable() {
158         synchronized (mLock) {
159             mEnabled = true;
160         }
161         ILocationProvider service = getService();
162         if (service == null) return;
163 
164         try {
165             service.enable();
166         } catch (RemoteException e) {
167             Log.w(TAG, e);
168         } catch (Exception e) {
169             // never let remote service crash system server
170             Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
171         }
172     }
173 
174     @Override
disable()175     public void disable() {
176         synchronized (mLock) {
177             mEnabled = false;
178         }
179         ILocationProvider service = getService();
180         if (service == null) return;
181 
182         try {
183             service.disable();
184         } catch (RemoteException e) {
185             Log.w(TAG, e);
186         } catch (Exception e) {
187             // never let remote service crash system server
188             Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
189         }
190     }
191 
192     @Override
isEnabled()193     public boolean isEnabled() {
194         synchronized (mLock) {
195             return mEnabled;
196         }
197     }
198 
199     @Override
setRequest(ProviderRequest request, WorkSource source)200     public void setRequest(ProviderRequest request, WorkSource source) {
201         synchronized (mLock) {
202             mRequest = request;
203             mWorksource = source;
204         }
205         ILocationProvider service = getService();
206         if (service == null) return;
207 
208         try {
209             service.setRequest(request, source);
210         } catch (RemoteException e) {
211             Log.w(TAG, e);
212         } catch (Exception e) {
213             // never let remote service crash system server
214             Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
215         }
216     }
217 
218     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)219     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
220         pw.append("REMOTE SERVICE");
221         pw.append(" name=").append(mName);
222         pw.append(" pkg=").append(mServiceWatcher.getBestPackageName());
223         pw.append(" version=").append("" + mServiceWatcher.getBestVersion());
224         pw.append('\n');
225 
226         ILocationProvider service = getService();
227         if (service == null) {
228             pw.println("service down (null)");
229             return;
230         }
231         pw.flush();
232 
233         try {
234             service.asBinder().dump(fd, args);
235         } catch (RemoteException e) {
236             pw.println("service down (RemoteException)");
237             Log.w(TAG, e);
238         } catch (Exception e) {
239             pw.println("service down (Exception)");
240             // never let remote service crash system server
241             Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
242         }
243     }
244 
245     @Override
getStatus(Bundle extras)246     public int getStatus(Bundle extras) {
247         ILocationProvider service = getService();
248         if (service == null) return LocationProvider.TEMPORARILY_UNAVAILABLE;
249 
250         try {
251             return service.getStatus(extras);
252         } catch (RemoteException e) {
253             Log.w(TAG, e);
254         } catch (Exception e) {
255             // never let remote service crash system server
256             Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
257         }
258         return LocationProvider.TEMPORARILY_UNAVAILABLE;
259     }
260 
261     @Override
getStatusUpdateTime()262     public long getStatusUpdateTime() {
263         ILocationProvider service = getService();
264         if (service == null) return 0;
265 
266         try {
267             return service.getStatusUpdateTime();
268         } catch (RemoteException e) {
269             Log.w(TAG, e);
270         } catch (Exception e) {
271             // never let remote service crash system server
272             Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
273         }
274         return 0;
275     }
276 
277     @Override
sendExtraCommand(String command, Bundle extras)278     public boolean sendExtraCommand(String command, Bundle extras) {
279         ILocationProvider service = getService();
280         if (service == null) return false;
281 
282         try {
283             return service.sendExtraCommand(command, extras);
284         } catch (RemoteException e) {
285             Log.w(TAG, e);
286         } catch (Exception e) {
287             // never let remote service crash system server
288             Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
289         }
290         return false;
291     }
292  }
293