18872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb/*
2ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan * Copyright (C) 2013 The Android Open Source Project
38872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
48872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
58872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * you may not use this file except in compliance with the License.
68872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * You may obtain a copy of the License at
78872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
88872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
98872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Unless required by applicable law or agreed to in writing, software
118872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * See the License for the specific language governing permissions and
148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * limitations under the License.
158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */
168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
17ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayanpackage com.android.camera.app;
188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.content.Context;
208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.location.Location;
218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.os.Bundle;
222bca210e5fc8a77685775ffb403096167b017dceAngus Kong
232bca210e5fc8a77685775ffb403096167b017dceAngus Kongimport com.android.camera.debug.Log;
248be316c7a8caf962cf3fcf5e49d332fb2718319fPaul Rohdeimport com.android.camera.util.AndroidServices;
258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
268872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb/**
27ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan * A class that handles legacy (network, gps) location providers, in the event
28ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan * the fused location provider from Google Play Services is unavailable.
298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */
30ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayanpublic class LegacyLocationProvider implements LocationProvider {
312bca210e5fc8a77685775ffb403096167b017dceAngus Kong    private static final Log.Tag TAG = new Log.Tag("LcyLocProvider");
328872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private Context mContext;
348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private android.location.LocationManager mLocationManager;
358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private boolean mRecordLocation;
368872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
378872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    LocationListener [] mLocationListeners = new LocationListener[] {
388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            new LocationListener(android.location.LocationManager.GPS_PROVIDER),
398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            new LocationListener(android.location.LocationManager.NETWORK_PROVIDER)
408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    };
418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
42ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan    public LegacyLocationProvider(Context context) {
438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mContext = context;
448872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
458872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
46ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan    @Override
478872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public Location getCurrentLocation() {
484708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger        if (!mRecordLocation) {
494708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger            return null;
504708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger        }
518872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
528872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        // go in best to worst order
538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        for (int i = 0; i < mLocationListeners.length; i++) {
548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            Location l = mLocationListeners[i].current();
554708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger            if (l != null) {
564708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger                return l;
574708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger            }
588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        Log.d(TAG, "No location received yet.");
608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return null;
618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
634708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger    @Override
648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void recordLocation(boolean recordLocation) {
658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mRecordLocation != recordLocation) {
668872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mRecordLocation = recordLocation;
678872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (recordLocation) {
688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                startReceivingLocationUpdates();
698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            } else {
708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                stopReceivingLocationUpdates();
718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
75ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan    @Override
76ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan    public void disconnect() {
77ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan        Log.d(TAG, "disconnect");
78ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan        // The onPause() call to stopReceivingLocationUpdates is sufficient to unregister the
79ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan        // Network/GPS listener.
80ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan    }
81ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan
828872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private void startReceivingLocationUpdates() {
834708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger        Log.v(TAG, "starting location updates");
848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mLocationManager == null) {
858be316c7a8caf962cf3fcf5e49d332fb2718319fPaul Rohde            mLocationManager = AndroidServices.instance().provideLocationManager();
868872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
878872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mLocationManager != null) {
888872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            try {
898872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                mLocationManager.requestLocationUpdates(
908872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                        android.location.LocationManager.NETWORK_PROVIDER,
918872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                        1000,
928872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                        0F,
938872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                        mLocationListeners[1]);
948872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            } catch (SecurityException ex) {
958872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                Log.i(TAG, "fail to request location update, ignore", ex);
968872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            } catch (IllegalArgumentException ex) {
978872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                Log.d(TAG, "provider does not exist " + ex.getMessage());
988872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
998872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            try {
1008872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                mLocationManager.requestLocationUpdates(
1018872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                        android.location.LocationManager.GPS_PROVIDER,
1028872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                        1000,
1038872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                        0F,
1048872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                        mLocationListeners[0]);
1058872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            } catch (SecurityException ex) {
1068872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                Log.i(TAG, "fail to request location update, ignore", ex);
1078872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            } catch (IllegalArgumentException ex) {
1088872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                Log.d(TAG, "provider does not exist " + ex.getMessage());
1098872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            Log.d(TAG, "startReceivingLocationUpdates");
1118872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private void stopReceivingLocationUpdates() {
1154708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger        Log.v(TAG, "stopping location updates");
1168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mLocationManager != null) {
1178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            for (int i = 0; i < mLocationListeners.length; i++) {
1188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                try {
1198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                    mLocationManager.removeUpdates(mLocationListeners[i]);
1208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                } catch (Exception ex) {
1218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                    Log.i(TAG, "fail to remove location listners, ignore", ex);
1228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                }
1238872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            Log.d(TAG, "stopReceivingLocationUpdates");
1258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1268872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private class LocationListener
1298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            implements android.location.LocationListener {
1308872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        Location mLastLocation;
1318872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        boolean mValid = false;
1328872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        String mProvider;
1338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public LocationListener(String provider) {
1358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mProvider = provider;
1368872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mLastLocation = new Location(mProvider);
1378872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        @Override
1408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void onLocationChanged(Location newLocation) {
1418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (newLocation.getLatitude() == 0.0
1428872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                    && newLocation.getLongitude() == 0.0) {
1438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                // Hack to filter out 0.0,0.0 locations
1448872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                return;
1458872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1468872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (!mValid) {
1478872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                Log.d(TAG, "Got first location.");
1488872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mLastLocation.set(newLocation);
1508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mValid = true;
1518872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1528872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        @Override
1548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void onProviderEnabled(String provider) {
1558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        @Override
1588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void onProviderDisabled(String provider) {
1598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mValid = false;
1608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        @Override
1638872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void onStatusChanged(
1648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                String provider, int status, Bundle extras) {
1658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            switch(status) {
166ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan                case android.location.LocationProvider.OUT_OF_SERVICE:
167ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan                case android.location.LocationProvider.TEMPORARILY_UNAVAILABLE: {
1688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                    mValid = false;
1698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                    break;
1708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                }
1718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public Location current() {
1758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            return mValid ? mLastLocation : null;
1768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1778872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1782bca210e5fc8a77685775ffb403096167b017dceAngus Kong}
179