LocationProviderProxy.java revision 00b74270c9f136a8727c5f6cda0997a3a905f385
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
17package com.android.server.location;
18
19import android.content.ComponentName;
20import android.content.Context;
21import android.content.Intent;
22import android.content.ServiceConnection;
23import android.location.ILocationProvider;
24import android.location.Location;
25import android.net.NetworkInfo;
26import android.os.Bundle;
27import android.os.Handler;
28import android.os.IBinder;
29import android.os.RemoteException;
30import android.os.SystemClock;
31import android.util.Log;
32
33import com.android.internal.location.DummyLocationProvider;
34
35/**
36 * A class for proxying location providers implemented as services.
37 *
38 * {@hide}
39 */
40public class LocationProviderProxy implements LocationProviderInterface {
41
42    private static final String TAG = "LocationProviderProxy";
43
44    private final Context mContext;
45    private final String mName;
46    private ILocationProvider mProvider;
47    private Handler mHandler;
48    private final Connection mServiceConnection = new Connection();
49
50    // cached values set by the location manager
51    private boolean mLocationTracking = false;
52    private boolean mEnabled = false;
53    private long mMinTime = -1;
54    private int mNetworkState;
55    private NetworkInfo mNetworkInfo;
56
57    // for caching requiresNetwork, requiresSatellite, etc.
58    private DummyLocationProvider mCachedAttributes;
59
60    // constructor for proxying location providers implemented in a separate service
61    public LocationProviderProxy(Context context, String name, String serviceName,
62            Handler handler) {
63        mContext = context;
64        mName = name;
65        mHandler = handler;
66        mContext.bindService(new Intent(serviceName), mServiceConnection, Context.BIND_AUTO_CREATE);
67    }
68
69    private class Connection implements ServiceConnection {
70        public void onServiceConnected(ComponentName className, IBinder service) {
71            Log.d(TAG, "LocationProviderProxy.onServiceConnected " + className);
72            synchronized (this) {
73                mProvider = ILocationProvider.Stub.asInterface(service);
74                if (mProvider != null) {
75                    mHandler.post(mServiceConnectedTask);
76                }
77            }
78        }
79
80        public void onServiceDisconnected(ComponentName className) {
81            Log.d(TAG, "LocationProviderProxy.onServiceDisconnected " + className);
82            synchronized (this) {
83                mProvider = null;
84            }
85        }
86    }
87
88    private Runnable mServiceConnectedTask = new Runnable() {
89        public void run() {
90            ILocationProvider provider;
91            synchronized (mServiceConnection) {
92                provider = mProvider;
93                if (provider == null) {
94                    return;
95                }
96            }
97
98            if (mCachedAttributes == null) {
99                try {
100                    mCachedAttributes = new DummyLocationProvider(mName);
101                    mCachedAttributes.setRequiresNetwork(provider.requiresNetwork());
102                    mCachedAttributes.setRequiresSatellite(provider.requiresSatellite());
103                    mCachedAttributes.setRequiresCell(provider.requiresCell());
104                    mCachedAttributes.setHasMonetaryCost(provider.hasMonetaryCost());
105                    mCachedAttributes.setSupportsAltitude(provider.supportsAltitude());
106                    mCachedAttributes.setSupportsSpeed(provider.supportsSpeed());
107                    mCachedAttributes.setSupportsBearing(provider.supportsBearing());
108                    mCachedAttributes.setPowerRequirement(provider.getPowerRequirement());
109                    mCachedAttributes.setAccuracy(provider.getAccuracy());
110                } catch (RemoteException e) {
111                    mCachedAttributes = null;
112                }
113            }
114
115            // resend previous values from the location manager if the service has restarted
116            try {
117                if (mEnabled) {
118                    provider.enable();
119                }
120                if (mLocationTracking) {
121                    provider.enableLocationTracking(true);
122                }
123                if (mMinTime >= 0) {
124                    provider.setMinTime(mMinTime);
125                }
126                if (mNetworkInfo != null) {
127                    provider.updateNetworkState(mNetworkState, mNetworkInfo);
128                }
129            } catch (RemoteException e) {
130            }
131        }
132    };
133
134    public String getName() {
135        return mName;
136    }
137
138    public boolean requiresNetwork() {
139        if (mCachedAttributes != null) {
140            return mCachedAttributes.requiresNetwork();
141        } else {
142            return false;
143        }
144    }
145
146    public boolean requiresSatellite() {
147        if (mCachedAttributes != null) {
148            return mCachedAttributes.requiresSatellite();
149        } else {
150            return false;
151        }
152    }
153
154    public boolean requiresCell() {
155        if (mCachedAttributes != null) {
156            return mCachedAttributes.requiresCell();
157        } else {
158            return false;
159        }
160    }
161
162    public boolean hasMonetaryCost() {
163        if (mCachedAttributes != null) {
164            return mCachedAttributes.hasMonetaryCost();
165        } else {
166            return false;
167        }
168    }
169
170    public boolean supportsAltitude() {
171        if (mCachedAttributes != null) {
172            return mCachedAttributes.supportsAltitude();
173        } else {
174            return false;
175        }
176    }
177
178    public boolean supportsSpeed() {
179        if (mCachedAttributes != null) {
180            return mCachedAttributes.supportsSpeed();
181        } else {
182            return false;
183        }
184    }
185
186     public boolean supportsBearing() {
187        if (mCachedAttributes != null) {
188            return mCachedAttributes.supportsBearing();
189        } else {
190            return false;
191        }
192    }
193
194    public int getPowerRequirement() {
195        if (mCachedAttributes != null) {
196            return mCachedAttributes.getPowerRequirement();
197        } else {
198            return -1;
199        }
200    }
201
202    public int getAccuracy() {
203        if (mCachedAttributes != null) {
204            return mCachedAttributes.getAccuracy();
205        } else {
206            return -1;
207        }
208    }
209
210    public void enable() {
211        mEnabled = true;
212        ILocationProvider provider;
213        synchronized (mServiceConnection) {
214            provider = mProvider;
215        }
216        if (provider != null) {
217            try {
218                provider.enable();
219            } catch (RemoteException e) {
220            }
221        }
222    }
223
224    public void disable() {
225        mEnabled = false;
226        ILocationProvider provider;
227        synchronized (mServiceConnection) {
228            provider = mProvider;
229        }
230        if (provider != null) {
231            try {
232                provider.disable();
233            } catch (RemoteException e) {
234            }
235        }
236    }
237
238    public boolean isEnabled() {
239        return mEnabled;
240    }
241
242    public int getStatus(Bundle extras) {
243        ILocationProvider provider;
244        synchronized (mServiceConnection) {
245            provider = mProvider;
246        }
247        if (provider != null) {
248            try {
249                return provider.getStatus(extras);
250            } catch (RemoteException e) {
251            }
252        }
253        return 0;
254    }
255
256    public long getStatusUpdateTime() {
257         ILocationProvider provider;
258        synchronized (mServiceConnection) {
259            provider = mProvider;
260        }
261        if (provider != null) {
262            try {
263                return provider.getStatusUpdateTime();
264            } catch (RemoteException e) {
265            }
266        }
267        return 0;
268     }
269
270    public String getInternalState() {
271        try {
272            return mProvider.getInternalState();
273        } catch (RemoteException e) {
274            Log.e(TAG, "getInternalState failed", e);
275            return null;
276        }
277    }
278
279    public boolean isLocationTracking() {
280        return mLocationTracking;
281    }
282
283    public void enableLocationTracking(boolean enable) {
284        mLocationTracking = enable;
285        if (!enable) {
286            mMinTime = -1;
287        }
288        ILocationProvider provider;
289        synchronized (mServiceConnection) {
290            provider = mProvider;
291        }
292        if (provider != null) {
293            try {
294                provider.enableLocationTracking(enable);
295            } catch (RemoteException e) {
296            }
297        }
298    }
299
300    public long getMinTime() {
301        return mMinTime;
302    }
303
304    public void setMinTime(long minTime) {
305       mMinTime = minTime;
306        ILocationProvider provider;
307        synchronized (mServiceConnection) {
308            provider = mProvider;
309        }
310        if (provider != null) {
311            try {
312                provider.setMinTime(minTime);
313            } catch (RemoteException e) {
314            }
315        }
316    }
317
318    public void updateNetworkState(int state, NetworkInfo info) {
319        mNetworkState = state;
320        mNetworkInfo = info;
321        ILocationProvider provider;
322        synchronized (mServiceConnection) {
323            provider = mProvider;
324        }
325        if (provider != null) {
326            try {
327                provider.updateNetworkState(state, info);
328            } catch (RemoteException e) {
329            }
330        }
331    }
332
333    public void updateLocation(Location location) {
334        ILocationProvider provider;
335        synchronized (mServiceConnection) {
336            provider = mProvider;
337        }
338        if (provider != null) {
339            try {
340                provider.updateLocation(location);
341            } catch (RemoteException e) {
342            }
343        }
344    }
345
346    public boolean sendExtraCommand(String command, Bundle extras) {
347        ILocationProvider provider;
348        synchronized (mServiceConnection) {
349            provider = mProvider;
350        }
351        if (provider != null) {
352            try {
353                provider.sendExtraCommand(command, extras);
354            } catch (RemoteException e) {
355            }
356        }
357        return false;
358    }
359
360    public void addListener(int uid) {
361        ILocationProvider provider;
362        synchronized (mServiceConnection) {
363            provider = mProvider;
364        }
365        if (provider != null) {
366            try {
367                provider.addListener(uid);
368            } catch (RemoteException e) {
369            }
370        }
371    }
372
373    public void removeListener(int uid) {
374        ILocationProvider provider;
375        synchronized (mServiceConnection) {
376            provider = mProvider;
377        }
378        if (provider != null) {
379            try {
380                provider.removeListener(uid);
381            } catch (RemoteException e) {
382            }
383        }
384    }
385}
386