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