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.net.wifi.WifiManager; 28 import android.provider.Settings; 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.TwoStatePreference; 35 36 import com.android.settings.R; 37 import com.android.settings.core.TogglePreferenceController; 38 import com.android.settings.utils.AnnotationSpan; 39 import com.android.settingslib.core.lifecycle.LifecycleObserver; 40 import com.android.settingslib.core.lifecycle.events.OnPause; 41 import com.android.settingslib.core.lifecycle.events.OnResume; 42 43 /** 44 * {@link TogglePreferenceController} that controls whether the Wi-Fi Wakeup feature should be 45 * enabled. 46 */ 47 public class WifiWakeupPreferenceController extends TogglePreferenceController implements 48 LifecycleObserver, OnPause, OnResume { 49 50 private static final String TAG = "WifiWakeupPrefController"; 51 private static final String KEY_ENABLE_WIFI_WAKEUP = "enable_wifi_wakeup"; 52 53 private Fragment mFragment; 54 55 @VisibleForTesting 56 TwoStatePreference mPreference; 57 58 @VisibleForTesting 59 LocationManager mLocationManager; 60 61 @VisibleForTesting 62 WifiManager mWifiManager; 63 64 private final BroadcastReceiver mLocationReceiver = new BroadcastReceiver() { 65 @Override 66 public void onReceive(Context context, Intent intent) { 67 updateState(mPreference); 68 } 69 }; 70 71 private final IntentFilter mLocationFilter = 72 new IntentFilter(LocationManager.MODE_CHANGED_ACTION); 73 WifiWakeupPreferenceController(Context context)74 public WifiWakeupPreferenceController(Context context) { 75 super(context, KEY_ENABLE_WIFI_WAKEUP); 76 mLocationManager = (LocationManager) context.getSystemService(Service.LOCATION_SERVICE); 77 mWifiManager = context.getSystemService(WifiManager.class); 78 } 79 setFragment(Fragment hostFragment)80 public void setFragment(Fragment hostFragment) { 81 mFragment = hostFragment; 82 } 83 84 @Override displayPreference(PreferenceScreen screen)85 public void displayPreference(PreferenceScreen screen) { 86 super.displayPreference(screen); 87 mPreference = screen.findPreference(getPreferenceKey()); 88 } 89 90 @Override getAvailabilityStatus()91 public int getAvailabilityStatus() { 92 // Since mFragment is set only when entering Network preferences settings. So when 93 // mFragment == null, we can assume that the object is created by Search settings. 94 // When Search settings is called, if the dependent condition is not enabled, then 95 // return DISABLED_DEPENDENT_SETTING to hide the toggle. 96 if (mFragment == null && (!getLocationEnabled() || !getWifiScanningEnabled())) { 97 return DISABLED_DEPENDENT_SETTING; 98 } 99 return AVAILABLE; 100 } 101 102 @Override isChecked()103 public boolean isChecked() { 104 return getWifiWakeupEnabled() 105 && getWifiScanningEnabled() 106 && getLocationEnabled(); 107 } 108 109 @Override setChecked(boolean isChecked)110 public boolean setChecked(boolean isChecked) { 111 if (isChecked) { 112 if (!getLocationEnabled()) { 113 if (mFragment == null) { 114 throw new IllegalStateException("No fragment to start activity"); 115 } 116 117 final Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS) 118 .setPackage(mContext.getPackageName()); 119 mFragment.startActivityForResult(intent, WIFI_WAKEUP_REQUEST_CODE); 120 return false; 121 } else if (!getWifiScanningEnabled()) { 122 showScanningDialog(); 123 return false; 124 } 125 } 126 127 setWifiWakeupEnabled(isChecked); 128 return true; 129 } 130 131 @Override updateState(Preference preference)132 public void updateState(Preference preference) { 133 super.updateState(preference); 134 refreshSummary(preference); 135 } 136 137 @Override getSummary()138 public CharSequence getSummary() { 139 if (!getLocationEnabled()) { 140 return getNoLocationSummary(); 141 } else { 142 return mContext.getText(R.string.wifi_wakeup_summary); 143 } 144 } 145 146 @Override getSliceHighlightMenuRes()147 public int getSliceHighlightMenuRes() { 148 return R.string.menu_key_network; 149 } 150 151 @VisibleForTesting getNoLocationSummary()152 CharSequence getNoLocationSummary() { 153 AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo("link", null); 154 CharSequence locationText = mContext.getText(R.string.wifi_wakeup_summary_no_location); 155 return AnnotationSpan.linkify(locationText, linkInfo); 156 } 157 onActivityResult(int requestCode, int resultCode)158 public void onActivityResult(int requestCode, int resultCode) { 159 if (requestCode != WIFI_WAKEUP_REQUEST_CODE) { 160 return; 161 } 162 if (getLocationEnabled() && getWifiScanningEnabled()) { 163 setWifiWakeupEnabled(true); 164 updateState(mPreference); 165 } 166 } 167 getLocationEnabled()168 private boolean getLocationEnabled() { 169 return mLocationManager.isLocationEnabled(); 170 } 171 getWifiScanningEnabled()172 private boolean getWifiScanningEnabled() { 173 return mWifiManager.isScanAlwaysAvailable(); 174 } 175 showScanningDialog()176 private void showScanningDialog() { 177 final WifiScanningRequiredFragment dialogFragment = 178 WifiScanningRequiredFragment.newInstance(); 179 dialogFragment.setTargetFragment(mFragment, WIFI_WAKEUP_REQUEST_CODE /* requestCode */); 180 dialogFragment.show(mFragment.getFragmentManager(), TAG); 181 } 182 getWifiWakeupEnabled()183 private boolean getWifiWakeupEnabled() { 184 return mWifiManager.isAutoWakeupEnabled(); 185 } 186 setWifiWakeupEnabled(boolean enabled)187 private void setWifiWakeupEnabled(boolean enabled) { 188 mWifiManager.setAutoWakeupEnabled(enabled); 189 } 190 191 @Override onResume()192 public void onResume() { 193 mContext.registerReceiver(mLocationReceiver, mLocationFilter); 194 } 195 196 @Override onPause()197 public void onPause() { 198 mContext.unregisterReceiver(mLocationReceiver); 199 } 200 } 201