Home | History | Annotate | Download | only in system
      1 /*
      2  * Copyright (C) 2015 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.tv.settings.system;
     18 
     19 import android.content.BroadcastReceiver;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.IntentFilter;
     23 import android.location.LocationManager;
     24 import android.os.BatteryManager;
     25 import android.os.Bundle;
     26 import android.os.UserManager;
     27 import android.provider.Settings;
     28 import android.support.v17.preference.LeanbackPreferenceFragment;
     29 import android.support.v7.preference.ListPreference;
     30 import android.support.v7.preference.Preference;
     31 import android.support.v7.preference.PreferenceCategory;
     32 import android.support.v7.preference.PreferenceGroup;
     33 import android.support.v7.preference.PreferenceScreen;
     34 import android.text.TextUtils;
     35 import android.util.Log;
     36 
     37 import com.android.settingslib.location.RecentLocationApps;
     38 import com.android.tv.settings.R;
     39 import com.android.tv.settings.device.apps.AppManagementFragment;
     40 
     41 import java.util.ArrayList;
     42 import java.util.Collections;
     43 import java.util.Comparator;
     44 import java.util.List;
     45 
     46 public class LocationFragment extends LeanbackPreferenceFragment implements
     47         Preference.OnPreferenceChangeListener {
     48 
     49     private static final String TAG = "LocationFragment";
     50 
     51     private static final String LOCATION_MODE_WIFI = "wifi";
     52     private static final String LOCATION_MODE_OFF = "off";
     53 
     54     private static final String KEY_LOCATION_MODE = "locationMode";
     55 
     56     private static final String MODE_CHANGING_ACTION =
     57             "com.android.settings.location.MODE_CHANGING";
     58     private static final String CURRENT_MODE_KEY = "CURRENT_MODE";
     59     private static final String NEW_MODE_KEY = "NEW_MODE";
     60 
     61     private ListPreference mLocationMode;
     62 
     63     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
     64         @Override
     65         public void onReceive(Context context, Intent intent) {
     66             if (Log.isLoggable(TAG, Log.DEBUG)) {
     67                 Log.d(TAG, "Received location mode change intent: " + intent);
     68             }
     69             refreshLocationMode();
     70         }
     71     };
     72 
     73     public static LocationFragment newInstance() {
     74         return new LocationFragment();
     75     }
     76 
     77     @Override
     78     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
     79         final Context themedContext = getPreferenceManager().getContext();
     80         final PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(
     81                 themedContext);
     82         screen.setTitle(R.string.system_location);
     83 
     84         mLocationMode = new ListPreference(themedContext);
     85         screen.addPreference(mLocationMode);
     86         mLocationMode.setKey(KEY_LOCATION_MODE);
     87         mLocationMode.setPersistent(false);
     88         mLocationMode.setTitle(R.string.location_status);
     89         mLocationMode.setDialogTitle(R.string.location_status);
     90         mLocationMode.setSummary("%s");
     91         mLocationMode.setEntries(new CharSequence[] {
     92                 getString(R.string.location_mode_wifi_description),
     93                 getString(R.string.off)
     94         });
     95         mLocationMode.setEntryValues(new CharSequence[] {
     96                 LOCATION_MODE_WIFI,
     97                 LOCATION_MODE_OFF
     98         });
     99         mLocationMode.setOnPreferenceChangeListener(this);
    100 
    101         final UserManager um = UserManager.get(getContext());
    102         mLocationMode.setEnabled(!um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION));
    103 
    104         final PreferenceCategory recentRequests = new PreferenceCategory(themedContext);
    105         screen.addPreference(recentRequests);
    106         recentRequests.setTitle(R.string.location_category_recent_location_requests);
    107 
    108         List<RecentLocationApps.Request> recentLocationRequests =
    109                 new RecentLocationApps(themedContext).getAppList();
    110         List<Preference> recentLocationPrefs = new ArrayList<>(recentLocationRequests.size());
    111         for (final RecentLocationApps.Request request : recentLocationRequests) {
    112             Preference pref = new Preference(themedContext);
    113             pref.setIcon(request.icon);
    114             pref.setTitle(request.label);
    115             // Most Android TV devices don't have built-in batteries and we ONLY show "High/Low
    116             // battery use" for devices with built-in batteries when they are not plugged-in.
    117             final BatteryManager batteryManager = (BatteryManager) getContext()
    118                     .getSystemService(Context.BATTERY_SERVICE);
    119             if (batteryManager != null && !batteryManager.isCharging()) {
    120                 if (request.isHighBattery) {
    121                     pref.setSummary(R.string.location_high_battery_use);
    122                 } else {
    123                     pref.setSummary(R.string.location_low_battery_use);
    124                 }
    125             }
    126             pref.setFragment(AppManagementFragment.class.getName());
    127             AppManagementFragment.prepareArgs(pref.getExtras(), request.packageName);
    128             recentLocationPrefs.add(pref);
    129         }
    130 
    131         if (recentLocationRequests.size() > 0) {
    132             addPreferencesSorted(recentLocationPrefs, recentRequests);
    133         } else {
    134             // If there's no item to display, add a "No recent apps" item.
    135             Preference banner = new Preference(themedContext);
    136             banner.setTitle(R.string.location_no_recent_apps);
    137             banner.setSelectable(false);
    138             recentRequests.addPreference(banner);
    139         }
    140 
    141         // TODO: are location services relevant on TV?
    142 
    143         setPreferenceScreen(screen);
    144     }
    145 
    146     // When selecting the location preference, LeanbackPreferenceFragment
    147     // creates an inner view with the selection options; that's when we want to
    148     // register our receiver, bacause from now on user can change the location
    149     // providers.
    150     @Override
    151     public void onCreate(Bundle savedInstanceState) {
    152         super.onCreate(savedInstanceState);
    153         getActivity().registerReceiver(mReceiver,
    154                 new IntentFilter(LocationManager.MODE_CHANGED_ACTION));
    155         refreshLocationMode();
    156     }
    157 
    158     @Override
    159     public void onDestroy() {
    160         super.onDestroy();
    161         getActivity().unregisterReceiver(mReceiver);
    162     }
    163 
    164     private void addPreferencesSorted(List<Preference> prefs, PreferenceGroup container) {
    165         // If there's some items to display, sort the items and add them to the container.
    166         Collections.sort(prefs, new Comparator<Preference>() {
    167             @Override
    168             public int compare(Preference lhs, Preference rhs) {
    169                 return lhs.getTitle().toString().compareTo(rhs.getTitle().toString());
    170             }
    171         });
    172         for (Preference entry : prefs) {
    173             container.addPreference(entry);
    174         }
    175     }
    176 
    177     @Override
    178     public boolean onPreferenceChange(Preference preference, Object newValue) {
    179         if (TextUtils.equals(preference.getKey(), KEY_LOCATION_MODE)) {
    180             int mode = Settings.Secure.LOCATION_MODE_OFF;
    181             if (TextUtils.equals((CharSequence) newValue, LOCATION_MODE_WIFI)) {
    182                 mode = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
    183             } else if (TextUtils.equals((CharSequence) newValue, LOCATION_MODE_OFF)) {
    184                 mode = Settings.Secure.LOCATION_MODE_OFF;
    185             } else {
    186                 Log.wtf(TAG, "Tried to set unknown location mode!");
    187             }
    188 
    189             writeLocationMode(mode);
    190             refreshLocationMode();
    191         }
    192         return true;
    193     }
    194 
    195     private void writeLocationMode(int mode) {
    196         int currentMode = Settings.Secure.getInt(getActivity().getContentResolver(),
    197                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
    198         Intent intent = new Intent(MODE_CHANGING_ACTION);
    199         intent.putExtra(CURRENT_MODE_KEY, currentMode);
    200         intent.putExtra(NEW_MODE_KEY, mode);
    201         getActivity().sendBroadcast(intent, android.Manifest.permission.WRITE_SECURE_SETTINGS);
    202         Settings.Secure.putInt(getActivity().getContentResolver(),
    203                 Settings.Secure.LOCATION_MODE, mode);
    204     }
    205 
    206     private void refreshLocationMode() {
    207         if (mLocationMode == null) {
    208             return;
    209         }
    210         final int mode = Settings.Secure.getInt(getActivity().getContentResolver(),
    211                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
    212         if (mode == Settings.Secure.LOCATION_MODE_HIGH_ACCURACY
    213                     || mode == Settings.Secure.LOCATION_MODE_BATTERY_SAVING) {
    214             mLocationMode.setValue(LOCATION_MODE_WIFI);
    215         } else if (mode == Settings.Secure.LOCATION_MODE_OFF) {
    216             mLocationMode.setValue(LOCATION_MODE_OFF);
    217         } else if (mode == Settings.Secure.LOCATION_MODE_SENSORS_ONLY) {
    218             writeLocationMode(Settings.Secure.LOCATION_MODE_OFF);
    219             mLocationMode.setValue(LOCATION_MODE_OFF);
    220         } else {
    221             Log.d(TAG, "Unknown location mode: " + mode);
    222         }
    223     }
    224 }
    225