1/*
2 * Copyright (C) 2011 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.camera;
18
19import android.content.Context;
20import android.location.Location;
21import android.location.LocationProvider;
22import android.os.Bundle;
23import android.util.Log;
24
25/**
26 * A class that handles everything about location.
27 */
28public class LocationManager {
29    private static final String TAG = "LocationManager";
30
31    private Context mContext;
32    private Listener mListener;
33    private android.location.LocationManager mLocationManager;
34    private boolean mRecordLocation;
35
36    LocationListener [] mLocationListeners = new LocationListener[] {
37            new LocationListener(android.location.LocationManager.GPS_PROVIDER),
38            new LocationListener(android.location.LocationManager.NETWORK_PROVIDER)
39    };
40
41    public interface Listener {
42        public void showGpsOnScreenIndicator(boolean hasSignal);
43        public void hideGpsOnScreenIndicator();
44   }
45
46    public LocationManager(Context context, Listener listener) {
47        mContext = context;
48        mListener = listener;
49    }
50
51    public Location getCurrentLocation() {
52        if (!mRecordLocation) return null;
53
54        // go in best to worst order
55        for (int i = 0; i < mLocationListeners.length; i++) {
56            Location l = mLocationListeners[i].current();
57            if (l != null) return l;
58        }
59        Log.d(TAG, "No location received yet.");
60        return null;
61    }
62
63    public void recordLocation(boolean recordLocation) {
64        if (mRecordLocation != recordLocation) {
65            mRecordLocation = recordLocation;
66            if (recordLocation) {
67                startReceivingLocationUpdates();
68            } else {
69                stopReceivingLocationUpdates();
70            }
71        }
72    }
73
74    private void startReceivingLocationUpdates() {
75        if (mLocationManager == null) {
76            mLocationManager = (android.location.LocationManager)
77                    mContext.getSystemService(Context.LOCATION_SERVICE);
78        }
79        if (mLocationManager != null) {
80            try {
81                mLocationManager.requestLocationUpdates(
82                        android.location.LocationManager.NETWORK_PROVIDER,
83                        1000,
84                        0F,
85                        mLocationListeners[1]);
86            } catch (SecurityException ex) {
87                Log.i(TAG, "fail to request location update, ignore", ex);
88            } catch (IllegalArgumentException ex) {
89                Log.d(TAG, "provider does not exist " + ex.getMessage());
90            }
91            try {
92                mLocationManager.requestLocationUpdates(
93                        android.location.LocationManager.GPS_PROVIDER,
94                        1000,
95                        0F,
96                        mLocationListeners[0]);
97                if (mListener != null) mListener.showGpsOnScreenIndicator(false);
98            } catch (SecurityException ex) {
99                Log.i(TAG, "fail to request location update, ignore", ex);
100            } catch (IllegalArgumentException ex) {
101                Log.d(TAG, "provider does not exist " + ex.getMessage());
102            }
103            Log.d(TAG, "startReceivingLocationUpdates");
104        }
105    }
106
107    private void stopReceivingLocationUpdates() {
108        if (mLocationManager != null) {
109            for (int i = 0; i < mLocationListeners.length; i++) {
110                try {
111                    mLocationManager.removeUpdates(mLocationListeners[i]);
112                } catch (Exception ex) {
113                    Log.i(TAG, "fail to remove location listners, ignore", ex);
114                }
115            }
116            Log.d(TAG, "stopReceivingLocationUpdates");
117        }
118        if (mListener != null) mListener.hideGpsOnScreenIndicator();
119    }
120
121    private class LocationListener
122            implements android.location.LocationListener {
123        Location mLastLocation;
124        boolean mValid = false;
125        String mProvider;
126
127        public LocationListener(String provider) {
128            mProvider = provider;
129            mLastLocation = new Location(mProvider);
130        }
131
132        @Override
133        public void onLocationChanged(Location newLocation) {
134            if (newLocation.getLatitude() == 0.0
135                    && newLocation.getLongitude() == 0.0) {
136                // Hack to filter out 0.0,0.0 locations
137                return;
138            }
139            // If GPS is available before start camera, we won't get status
140            // update so update GPS indicator when we receive data.
141            if (mListener != null && mRecordLocation &&
142                    android.location.LocationManager.GPS_PROVIDER.equals(mProvider)) {
143                mListener.showGpsOnScreenIndicator(true);
144            }
145            if (!mValid) {
146                Log.d(TAG, "Got first location.");
147            }
148            mLastLocation.set(newLocation);
149            mValid = true;
150        }
151
152        @Override
153        public void onProviderEnabled(String provider) {
154        }
155
156        @Override
157        public void onProviderDisabled(String provider) {
158            mValid = false;
159        }
160
161        @Override
162        public void onStatusChanged(
163                String provider, int status, Bundle extras) {
164            switch(status) {
165                case LocationProvider.OUT_OF_SERVICE:
166                case LocationProvider.TEMPORARILY_UNAVAILABLE: {
167                    mValid = false;
168                    if (mListener != null && mRecordLocation &&
169                            android.location.LocationManager.GPS_PROVIDER.equals(provider)) {
170                        mListener.showGpsOnScreenIndicator(false);
171                    }
172                    break;
173                }
174            }
175        }
176
177        public Location current() {
178            return mValid ? mLastLocation : null;
179        }
180    }
181}
182