1 package com.android.settings.wifi; 2 3 import android.app.Activity; 4 import android.content.ComponentName; 5 import android.content.ContentResolver; 6 import android.content.Context; 7 import android.content.Intent; 8 import android.database.ContentObserver; 9 import android.net.NetworkScoreManager; 10 import android.net.NetworkScorerAppData; 11 import android.net.Uri; 12 import android.os.Handler; 13 import android.os.Looper; 14 import android.provider.Settings; 15 import android.text.TextUtils; 16 17 import androidx.fragment.app.Fragment; 18 import androidx.preference.Preference; 19 import androidx.preference.PreferenceScreen; 20 import androidx.preference.SwitchPreference; 21 22 import com.android.settings.R; 23 import com.android.settings.core.PreferenceControllerMixin; 24 import com.android.settingslib.core.AbstractPreferenceController; 25 import com.android.settingslib.core.lifecycle.Lifecycle; 26 import com.android.settingslib.core.lifecycle.LifecycleObserver; 27 import com.android.settingslib.core.lifecycle.events.OnPause; 28 import com.android.settingslib.core.lifecycle.events.OnResume; 29 30 import java.util.List; 31 32 /** 33 * {@link AbstractPreferenceController} that controls whether a user wants to enable the "use open 34 * networks automatically" feature provider by the current network recommendation provider. 35 */ 36 public class UseOpenWifiPreferenceController extends AbstractPreferenceController 37 implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener, 38 LifecycleObserver, OnResume, OnPause { 39 public static final int REQUEST_CODE_OPEN_WIFI_AUTOMATICALLY = 400; 40 41 private static final String KEY_USE_OPEN_WIFI_AUTOMATICALLY = "use_open_wifi_automatically"; 42 43 private final ContentResolver mContentResolver; 44 private final Fragment mFragment; 45 private final NetworkScoreManager mNetworkScoreManager; 46 private final SettingObserver mSettingObserver; 47 48 private Preference mPreference; 49 private ComponentName mEnableUseWifiComponentName; 50 private boolean mDoFeatureSupportedScorersExist; 51 UseOpenWifiPreferenceController(Context context, Fragment fragment, Lifecycle lifecycle)52 public UseOpenWifiPreferenceController(Context context, Fragment fragment, 53 Lifecycle lifecycle) { 54 super(context); 55 mContentResolver = context.getContentResolver(); 56 mFragment = fragment; 57 mNetworkScoreManager = 58 (NetworkScoreManager) context.getSystemService(Context.NETWORK_SCORE_SERVICE); 59 mSettingObserver = new SettingObserver(); 60 updateEnableUseWifiComponentName(); 61 checkForFeatureSupportedScorers(); 62 lifecycle.addObserver(this); 63 } 64 updateEnableUseWifiComponentName()65 private void updateEnableUseWifiComponentName() { 66 NetworkScorerAppData appData = mNetworkScoreManager.getActiveScorer(); 67 mEnableUseWifiComponentName = 68 appData == null ? null : appData.getEnableUseOpenWifiActivity(); 69 } 70 checkForFeatureSupportedScorers()71 private void checkForFeatureSupportedScorers() { 72 if (mEnableUseWifiComponentName != null) { 73 mDoFeatureSupportedScorersExist = true; 74 return; 75 } 76 List<NetworkScorerAppData> scorers = mNetworkScoreManager.getAllValidScorers(); 77 for (NetworkScorerAppData scorer : scorers) { 78 if (scorer.getEnableUseOpenWifiActivity() != null) { 79 mDoFeatureSupportedScorersExist = true; 80 return; 81 } 82 } 83 mDoFeatureSupportedScorersExist = false; 84 } 85 86 @Override displayPreference(PreferenceScreen screen)87 public void displayPreference(PreferenceScreen screen) { 88 super.displayPreference(screen); 89 mPreference = screen.findPreference(KEY_USE_OPEN_WIFI_AUTOMATICALLY); 90 } 91 92 @Override onResume()93 public void onResume() { 94 mSettingObserver.register(mContentResolver); 95 } 96 97 @Override onPause()98 public void onPause() { 99 mSettingObserver.unregister(mContentResolver); 100 } 101 102 @Override isAvailable()103 public boolean isAvailable() { 104 return mDoFeatureSupportedScorersExist; 105 } 106 107 @Override getPreferenceKey()108 public String getPreferenceKey() { 109 return KEY_USE_OPEN_WIFI_AUTOMATICALLY; 110 } 111 112 @Override updateState(Preference preference)113 public void updateState(Preference preference) { 114 if (!(preference instanceof SwitchPreference)) { 115 return; 116 } 117 final SwitchPreference useOpenWifiPreference = (SwitchPreference) preference; 118 119 boolean isScorerSet = mNetworkScoreManager.getActiveScorerPackage() != null; 120 boolean doesActiveScorerSupportFeature = mEnableUseWifiComponentName != null; 121 122 useOpenWifiPreference.setChecked(isSettingEnabled()); 123 useOpenWifiPreference.setVisible(isAvailable()); 124 useOpenWifiPreference.setEnabled(isScorerSet && doesActiveScorerSupportFeature); 125 126 if (!isScorerSet) { 127 useOpenWifiPreference.setSummary( 128 R.string.use_open_wifi_automatically_summary_scoring_disabled); 129 } else if (!doesActiveScorerSupportFeature) { 130 useOpenWifiPreference.setSummary( 131 R.string.use_open_wifi_automatically_summary_scorer_unsupported_disabled); 132 } else { 133 useOpenWifiPreference.setSummary(R.string.use_open_wifi_automatically_summary); 134 } 135 } 136 137 @Override onPreferenceChange(Preference preference, Object newValue)138 public boolean onPreferenceChange(Preference preference, Object newValue) { 139 if (!TextUtils.equals(preference.getKey(), KEY_USE_OPEN_WIFI_AUTOMATICALLY) 140 || !isAvailable()) { 141 return false; 142 } 143 144 if (isSettingEnabled()) { 145 Settings.Global.putString(mContentResolver, 146 Settings.Global.USE_OPEN_WIFI_PACKAGE, ""); 147 return true; 148 } 149 150 Intent intent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE); 151 intent.setComponent(mEnableUseWifiComponentName); 152 mFragment.startActivityForResult(intent, REQUEST_CODE_OPEN_WIFI_AUTOMATICALLY); 153 return false; // Updating state is done in onActivityResult. 154 } 155 isSettingEnabled()156 private boolean isSettingEnabled() { 157 String enabledUseOpenWifiPackage = Settings.Global.getString(mContentResolver, 158 Settings.Global.USE_OPEN_WIFI_PACKAGE); 159 String currentUseOpenWifiPackage = mEnableUseWifiComponentName == null 160 ? null : mEnableUseWifiComponentName.getPackageName(); 161 return TextUtils.equals(enabledUseOpenWifiPackage, currentUseOpenWifiPackage); 162 } 163 onActivityResult(int requestCode, int resultCode)164 public boolean onActivityResult(int requestCode, int resultCode) { 165 if (requestCode != REQUEST_CODE_OPEN_WIFI_AUTOMATICALLY) { 166 return false; 167 } 168 169 if (resultCode == Activity.RESULT_OK) { 170 Settings.Global.putString(mContentResolver, Settings.Global.USE_OPEN_WIFI_PACKAGE, 171 mEnableUseWifiComponentName.getPackageName()); 172 } 173 return true; 174 } 175 176 class SettingObserver extends ContentObserver { 177 private final Uri NETWORK_RECOMMENDATIONS_ENABLED_URI = 178 Settings.Global.getUriFor(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED); 179 SettingObserver()180 public SettingObserver() { 181 super(new Handler(Looper.getMainLooper())); 182 } 183 register(ContentResolver cr)184 public void register(ContentResolver cr) { 185 cr.registerContentObserver(NETWORK_RECOMMENDATIONS_ENABLED_URI, false, this); 186 onChange(true /* selfChange */, NETWORK_RECOMMENDATIONS_ENABLED_URI); 187 } 188 unregister(ContentResolver cr)189 public void unregister(ContentResolver cr) { 190 cr.unregisterContentObserver(this); 191 } 192 193 @Override onChange(boolean selfChange, Uri uri)194 public void onChange(boolean selfChange, Uri uri) { 195 super.onChange(selfChange, uri); 196 if (NETWORK_RECOMMENDATIONS_ENABLED_URI.equals(uri)) { 197 updateEnableUseWifiComponentName(); 198 updateState(mPreference); 199 } 200 } 201 } 202 } 203