1/*
2 * Copyright (C) 2013 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.app;
18
19import android.content.Context;
20import android.location.Location;
21import android.os.Bundle;
22
23import com.android.camera.debug.Log;
24
25/**
26 * A class that handles legacy (network, gps) location providers, in the event
27 * the fused location provider from Google Play Services is unavailable.
28 */
29public class LegacyLocationProvider implements LocationProvider {
30    private static final Log.Tag TAG = new Log.Tag("LcyLocProvider");
31
32    private Context mContext;
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 LegacyLocationProvider(Context context) {
42        mContext = context;
43    }
44
45    @Override
46    public Location getCurrentLocation() {
47        if (!mRecordLocation) return null;
48
49        // go in best to worst order
50        for (int i = 0; i < mLocationListeners.length; i++) {
51            Location l = mLocationListeners[i].current();
52            if (l != null) return l;
53        }
54        Log.d(TAG, "No location received yet.");
55        return null;
56    }
57
58    public void recordLocation(boolean recordLocation) {
59        if (mRecordLocation != recordLocation) {
60            mRecordLocation = recordLocation;
61            if (recordLocation) {
62                startReceivingLocationUpdates();
63            } else {
64                stopReceivingLocationUpdates();
65            }
66        }
67    }
68
69    @Override
70    public void disconnect() {
71        Log.d(TAG, "disconnect");
72        // The onPause() call to stopReceivingLocationUpdates is sufficient to unregister the
73        // Network/GPS listener.
74    }
75
76    private void startReceivingLocationUpdates() {
77        if (mLocationManager == null) {
78            mLocationManager = (android.location.LocationManager)
79                    mContext.getSystemService(Context.LOCATION_SERVICE);
80        }
81        if (mLocationManager != null) {
82            try {
83                mLocationManager.requestLocationUpdates(
84                        android.location.LocationManager.NETWORK_PROVIDER,
85                        1000,
86                        0F,
87                        mLocationListeners[1]);
88            } catch (SecurityException ex) {
89                Log.i(TAG, "fail to request location update, ignore", ex);
90            } catch (IllegalArgumentException ex) {
91                Log.d(TAG, "provider does not exist " + ex.getMessage());
92            }
93            try {
94                mLocationManager.requestLocationUpdates(
95                        android.location.LocationManager.GPS_PROVIDER,
96                        1000,
97                        0F,
98                        mLocationListeners[0]);
99            } catch (SecurityException ex) {
100                Log.i(TAG, "fail to request location update, ignore", ex);
101            } catch (IllegalArgumentException ex) {
102                Log.d(TAG, "provider does not exist " + ex.getMessage());
103            }
104            Log.d(TAG, "startReceivingLocationUpdates");
105        }
106    }
107
108    private void stopReceivingLocationUpdates() {
109        if (mLocationManager != null) {
110            for (int i = 0; i < mLocationListeners.length; i++) {
111                try {
112                    mLocationManager.removeUpdates(mLocationListeners[i]);
113                } catch (Exception ex) {
114                    Log.i(TAG, "fail to remove location listners, ignore", ex);
115                }
116            }
117            Log.d(TAG, "stopReceivingLocationUpdates");
118        }
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 (!mValid) {
140                Log.d(TAG, "Got first location.");
141            }
142            mLastLocation.set(newLocation);
143            mValid = true;
144        }
145
146        @Override
147        public void onProviderEnabled(String provider) {
148        }
149
150        @Override
151        public void onProviderDisabled(String provider) {
152            mValid = false;
153        }
154
155        @Override
156        public void onStatusChanged(
157                String provider, int status, Bundle extras) {
158            switch(status) {
159                case android.location.LocationProvider.OUT_OF_SERVICE:
160                case android.location.LocationProvider.TEMPORARILY_UNAVAILABLE: {
161                    mValid = false;
162                    break;
163                }
164            }
165        }
166
167        public Location current() {
168            return mValid ? mLastLocation : null;
169        }
170    }
171}
172