1 /* 2 * Copyright (C) 2019 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.car.settings.wifi.preferences; 18 19 import android.car.drivingstate.CarUxRestrictions; 20 import android.content.ActivityNotFoundException; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.location.LocationManager; 24 import android.net.wifi.WifiManager; 25 import android.provider.Settings; 26 import android.text.SpannableString; 27 import android.text.Spanned; 28 import android.text.TextUtils; 29 import android.text.style.URLSpan; 30 import android.widget.Toast; 31 32 import androidx.annotation.VisibleForTesting; 33 import androidx.preference.TwoStatePreference; 34 35 import com.android.car.settings.R; 36 import com.android.car.settings.common.ConfirmationDialogFragment; 37 import com.android.car.settings.common.FragmentController; 38 import com.android.car.settings.common.Logger; 39 import com.android.car.settings.common.PreferenceController; 40 import com.android.car.settings.location.LocationSettingsFragment; 41 import com.android.settingslib.HelpUtils; 42 43 /** Business logic to allow auto-enabling of wifi near saved networks. */ 44 public class WifiWakeupTogglePreferenceController extends PreferenceController<TwoStatePreference> { 45 46 private static final Logger LOG = new Logger(WifiWakeupTogglePreferenceController.class); 47 private LocationManager mLocationManager; 48 @VisibleForTesting 49 WifiManager mWifiManager; 50 51 @VisibleForTesting 52 final ConfirmationDialogFragment.ConfirmListener mConfirmListener = arguments -> { 53 enableWifiScanning(); 54 if (mLocationManager.isLocationEnabled()) { 55 setWifiWakeupEnabled(true); 56 } 57 refreshUi(); 58 }; 59 60 private final ConfirmationDialogFragment.NeutralListener mNeutralListener = arguments -> { 61 Intent intent = HelpUtils.getHelpIntent(getContext(), 62 getContext().getString(R.string.help_uri_wifi_scanning_required), 63 getContext().getClass().getName()); 64 if (intent != null) { 65 try { 66 getContext().startActivity(intent); 67 } catch (ActivityNotFoundException e) { 68 LOG.e("Activity was not found for intent, " + intent.toString()); 69 } 70 } 71 }; 72 WifiWakeupTogglePreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)73 public WifiWakeupTogglePreferenceController(Context context, String preferenceKey, 74 FragmentController fragmentController, CarUxRestrictions uxRestrictions) { 75 super(context, preferenceKey, fragmentController, uxRestrictions); 76 mLocationManager = context.getSystemService(LocationManager.class); 77 mWifiManager = context.getSystemService(WifiManager.class); 78 } 79 80 @Override getPreferenceType()81 protected Class<TwoStatePreference> getPreferenceType() { 82 return TwoStatePreference.class; 83 } 84 85 @Override onCreateInternal()86 protected void onCreateInternal() { 87 ConfirmationDialogFragment dialog = 88 (ConfirmationDialogFragment) getFragmentController().findDialogByTag( 89 ConfirmationDialogFragment.TAG); 90 ConfirmationDialogFragment.resetListeners( 91 dialog, 92 mConfirmListener, 93 /* rejectListener= */ null, 94 mNeutralListener); 95 } 96 97 @Override updateState(TwoStatePreference preference)98 protected void updateState(TwoStatePreference preference) { 99 preference.setChecked(getWifiWakeupEnabled() 100 && getWifiScanningEnabled() 101 && mLocationManager.isLocationEnabled()); 102 if (!mLocationManager.isLocationEnabled()) { 103 preference.setSummary(getNoLocationSummary()); 104 } else { 105 preference.setSummary(R.string.wifi_wakeup_summary); 106 } 107 } 108 109 @Override handlePreferenceClicked(TwoStatePreference preference)110 protected boolean handlePreferenceClicked(TwoStatePreference preference) { 111 if (!mLocationManager.isLocationEnabled()) { 112 getFragmentController().launchFragment(new LocationSettingsFragment()); 113 } else if (getWifiWakeupEnabled()) { 114 setWifiWakeupEnabled(false); 115 } else if (!getWifiScanningEnabled()) { 116 showScanningDialog(); 117 } else { 118 setWifiWakeupEnabled(true); 119 } 120 121 refreshUi(); 122 return true; 123 } 124 getWifiWakeupEnabled()125 private boolean getWifiWakeupEnabled() { 126 return Settings.Global.getInt(getContext().getContentResolver(), 127 Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1; 128 } 129 setWifiWakeupEnabled(boolean enabled)130 private void setWifiWakeupEnabled(boolean enabled) { 131 Settings.Global.putInt(getContext().getContentResolver(), 132 Settings.Global.WIFI_WAKEUP_ENABLED, 133 enabled ? 1 : 0); 134 } 135 getWifiScanningEnabled()136 private boolean getWifiScanningEnabled() { 137 return mWifiManager.isScanAlwaysAvailable(); 138 } 139 enableWifiScanning()140 private void enableWifiScanning() { 141 mWifiManager.setScanAlwaysAvailable(true); 142 Toast.makeText( 143 getContext(), 144 getContext().getString(R.string.wifi_settings_scanning_required_enabled), 145 Toast.LENGTH_SHORT).show(); 146 } 147 getNoLocationSummary()148 private CharSequence getNoLocationSummary() { 149 String highlightedWord = "link"; 150 CharSequence locationText = getContext() 151 .getText(R.string.wifi_wakeup_summary_no_location); 152 153 SpannableString msg = new SpannableString(locationText); 154 int startIndex = locationText.toString().indexOf(highlightedWord); 155 if (startIndex < 0) { 156 LOG.e("Cannot create URL span"); 157 return locationText; 158 } 159 msg.setSpan(new URLSpan((String) null), startIndex, startIndex + highlightedWord.length(), 160 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 161 return msg; 162 } 163 showScanningDialog()164 private void showScanningDialog() { 165 ConfirmationDialogFragment dialogFragment = 166 getConfirmEnableWifiScanningDialogFragment(); 167 getFragmentController().showDialog( 168 dialogFragment, ConfirmationDialogFragment.TAG); 169 } 170 getConfirmEnableWifiScanningDialogFragment()171 private ConfirmationDialogFragment getConfirmEnableWifiScanningDialogFragment() { 172 ConfirmationDialogFragment.Builder builder = 173 new ConfirmationDialogFragment.Builder(getContext()) 174 .setTitle(R.string.wifi_settings_scanning_required_title) 175 .setPositiveButton( 176 R.string.wifi_settings_scanning_required_turn_on, mConfirmListener) 177 .setNegativeButton(R.string.cancel, /* rejectListener= */ null); 178 179 // Only show "learn more" if there is a help page to show 180 if (!TextUtils.isEmpty(getContext().getString(R.string.help_uri_wifi_scanning_required))) { 181 builder.setNeutralButton(R.string.learn_more, mNeutralListener); 182 } 183 return builder.build(); 184 } 185 } 186