1 /* 2 * Copyright (C) 2017 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.settings.wifi; 18 19 import static com.android.settings.wifi.ConfigureWifiSettings.WIFI_WAKEUP_REQUEST_CODE; 20 21 import android.app.Service; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.location.LocationManager; 27 import android.provider.Settings; 28 import android.text.TextUtils; 29 30 import androidx.annotation.VisibleForTesting; 31 import androidx.fragment.app.Fragment; 32 import androidx.preference.Preference; 33 import androidx.preference.PreferenceScreen; 34 import androidx.preference.SwitchPreference; 35 36 import com.android.settings.R; 37 import com.android.settings.core.PreferenceControllerMixin; 38 import com.android.settings.dashboard.DashboardFragment; 39 import com.android.settings.utils.AnnotationSpan; 40 import com.android.settingslib.core.AbstractPreferenceController; 41 import com.android.settingslib.core.lifecycle.Lifecycle; 42 import com.android.settingslib.core.lifecycle.LifecycleObserver; 43 import com.android.settingslib.core.lifecycle.events.OnPause; 44 import com.android.settingslib.core.lifecycle.events.OnResume; 45 46 /** 47 * {@link PreferenceControllerMixin} that controls whether the Wi-Fi Wakeup feature should be 48 * enabled. 49 */ 50 public class WifiWakeupPreferenceController extends AbstractPreferenceController implements 51 LifecycleObserver, OnPause, OnResume { 52 53 private static final String TAG = "WifiWakeupPrefController"; 54 private static final String KEY_ENABLE_WIFI_WAKEUP = "enable_wifi_wakeup"; 55 56 private final Fragment mFragment; 57 58 @VisibleForTesting 59 SwitchPreference mPreference; 60 @VisibleForTesting 61 LocationManager mLocationManager; 62 private final BroadcastReceiver mLocationReceiver = new BroadcastReceiver() { 63 @Override 64 public void onReceive(Context context, Intent intent) { 65 updateState(mPreference); 66 } 67 }; 68 private final IntentFilter mLocationFilter = 69 new IntentFilter(LocationManager.MODE_CHANGED_ACTION); 70 WifiWakeupPreferenceController(Context context, DashboardFragment fragment, Lifecycle lifecycle)71 public WifiWakeupPreferenceController(Context context, DashboardFragment fragment, 72 Lifecycle lifecycle) { 73 super(context); 74 mFragment = fragment; 75 mLocationManager = (LocationManager) context.getSystemService(Service.LOCATION_SERVICE); 76 lifecycle.addObserver(this); 77 } 78 79 @Override displayPreference(PreferenceScreen screen)80 public void displayPreference(PreferenceScreen screen) { 81 super.displayPreference(screen); 82 mPreference = screen.findPreference(KEY_ENABLE_WIFI_WAKEUP); 83 updateState(mPreference); 84 } 85 86 @Override isAvailable()87 public boolean isAvailable() { 88 return true; 89 } 90 91 @Override handlePreferenceTreeClick(Preference preference)92 public boolean handlePreferenceTreeClick(Preference preference) { 93 if (!TextUtils.equals(preference.getKey(), KEY_ENABLE_WIFI_WAKEUP)) { 94 return false; 95 } 96 if (!(preference instanceof SwitchPreference)) { 97 return false; 98 } 99 100 // TODO(b/132391311): WifiWakeupPreferenceController is essentially reimplementing 101 // TogglePreferenceController. Refactor it into TogglePreferenceController. 102 103 // Toggle wifi-wakeup setting between 1/0 based on its current state, and some other checks. 104 if (isWifiWakeupAvailable()) { 105 setWifiWakeupEnabled(false); 106 } else { 107 if (!mLocationManager.isLocationEnabled()) { 108 final Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); 109 mFragment.startActivityForResult(intent, WIFI_WAKEUP_REQUEST_CODE); 110 return true; 111 } else if (!getWifiScanningEnabled()) { 112 showScanningDialog(); 113 } else { 114 setWifiWakeupEnabled(true); 115 } 116 } 117 118 updateState(mPreference); 119 return true; 120 } 121 122 @Override getPreferenceKey()123 public String getPreferenceKey() { 124 return KEY_ENABLE_WIFI_WAKEUP; 125 } 126 127 @Override updateState(Preference preference)128 public void updateState(Preference preference) { 129 if (!(preference instanceof SwitchPreference)) { 130 return; 131 } 132 final SwitchPreference enableWifiWakeup = (SwitchPreference) preference; 133 134 enableWifiWakeup.setChecked(isWifiWakeupAvailable()); 135 if (!mLocationManager.isLocationEnabled()) { 136 preference.setSummary(getNoLocationSummary()); 137 } else { 138 preference.setSummary(R.string.wifi_wakeup_summary); 139 } 140 } 141 142 @VisibleForTesting getNoLocationSummary()143 CharSequence getNoLocationSummary() { 144 AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo("link", null); 145 CharSequence locationText = mContext.getText(R.string.wifi_wakeup_summary_no_location); 146 return AnnotationSpan.linkify(locationText, linkInfo); 147 } 148 onActivityResult(int requestCode, int resultCode)149 public void onActivityResult(int requestCode, int resultCode) { 150 if (requestCode != WIFI_WAKEUP_REQUEST_CODE) { 151 return; 152 } 153 if (mLocationManager.isLocationEnabled() && getWifiScanningEnabled()) { 154 setWifiWakeupEnabled(true); 155 } 156 updateState(mPreference); 157 } 158 getWifiScanningEnabled()159 private boolean getWifiScanningEnabled() { 160 return Settings.Global.getInt(mContext.getContentResolver(), 161 Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1; 162 } 163 showScanningDialog()164 private void showScanningDialog() { 165 final WifiScanningRequiredFragment dialogFragment = 166 WifiScanningRequiredFragment.newInstance(); 167 dialogFragment.setTargetFragment(mFragment, WIFI_WAKEUP_REQUEST_CODE /* requestCode */); 168 dialogFragment.show(mFragment.getFragmentManager(), TAG); 169 } 170 getWifiWakeupEnabled()171 private boolean getWifiWakeupEnabled() { 172 return Settings.Global.getInt(mContext.getContentResolver(), 173 Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1; 174 } 175 176 /** 177 * Wifi wakeup is available only when both location and Wi-Fi scanning are enabled. 178 */ isWifiWakeupAvailable()179 private boolean isWifiWakeupAvailable() { 180 return getWifiWakeupEnabled() 181 && getWifiScanningEnabled() 182 && mLocationManager.isLocationEnabled(); 183 } 184 setWifiWakeupEnabled(boolean enabled)185 private void setWifiWakeupEnabled(boolean enabled) { 186 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.WIFI_WAKEUP_ENABLED, 187 enabled ? 1 : 0); 188 } 189 190 @Override onResume()191 public void onResume() { 192 mContext.registerReceiver(mLocationReceiver, mLocationFilter); 193 } 194 195 @Override onPause()196 public void onPause() { 197 mContext.unregisterReceiver(mLocationReceiver); 198 } 199 } 200