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.SwitchPreference; 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 SwitchPreference 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 return AVAILABLE; 93 } 94 95 @Override isChecked()96 public boolean isChecked() { 97 return getWifiWakeupEnabled() 98 && getWifiScanningEnabled() 99 && mLocationManager.isLocationEnabled(); 100 } 101 102 @Override setChecked(boolean isChecked)103 public boolean setChecked(boolean isChecked) { 104 if (isChecked) { 105 if (mFragment == null) { 106 throw new IllegalStateException("No fragment to start activity"); 107 } 108 109 if (!mLocationManager.isLocationEnabled()) { 110 final Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); 111 mFragment.startActivityForResult(intent, WIFI_WAKEUP_REQUEST_CODE); 112 return false; 113 } else if (!getWifiScanningEnabled()) { 114 showScanningDialog(); 115 return false; 116 } 117 } 118 119 setWifiWakeupEnabled(isChecked); 120 return true; 121 } 122 123 @Override updateState(Preference preference)124 public void updateState(Preference preference) { 125 super.updateState(preference); 126 refreshSummary(preference); 127 } 128 129 @Override getSummary()130 public CharSequence getSummary() { 131 if (!mLocationManager.isLocationEnabled()) { 132 return getNoLocationSummary(); 133 } else { 134 return mContext.getText(R.string.wifi_wakeup_summary); 135 } 136 } 137 138 @VisibleForTesting getNoLocationSummary()139 CharSequence getNoLocationSummary() { 140 AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo("link", null); 141 CharSequence locationText = mContext.getText(R.string.wifi_wakeup_summary_no_location); 142 return AnnotationSpan.linkify(locationText, linkInfo); 143 } 144 onActivityResult(int requestCode, int resultCode)145 public void onActivityResult(int requestCode, int resultCode) { 146 if (requestCode != WIFI_WAKEUP_REQUEST_CODE) { 147 return; 148 } 149 if (mLocationManager.isLocationEnabled() && getWifiScanningEnabled()) { 150 setWifiWakeupEnabled(true); 151 updateState(mPreference); 152 } 153 } 154 getWifiScanningEnabled()155 private boolean getWifiScanningEnabled() { 156 return mWifiManager.isScanAlwaysAvailable(); 157 } 158 showScanningDialog()159 private void showScanningDialog() { 160 final WifiScanningRequiredFragment dialogFragment = 161 WifiScanningRequiredFragment.newInstance(); 162 dialogFragment.setTargetFragment(mFragment, WIFI_WAKEUP_REQUEST_CODE /* requestCode */); 163 dialogFragment.show(mFragment.getFragmentManager(), TAG); 164 } 165 getWifiWakeupEnabled()166 private boolean getWifiWakeupEnabled() { 167 return mWifiManager.isAutoWakeupEnabled(); 168 } 169 setWifiWakeupEnabled(boolean enabled)170 private void setWifiWakeupEnabled(boolean enabled) { 171 mWifiManager.setAutoWakeupEnabled(enabled); 172 } 173 174 @Override onResume()175 public void onResume() { 176 mContext.registerReceiver(mLocationReceiver, mLocationFilter); 177 } 178 179 @Override onPause()180 public void onPause() { 181 mContext.unregisterReceiver(mLocationReceiver); 182 } 183 } 184