1 /* 2 * Copyright (C) 2020 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.network; 18 19 import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE; 20 import static androidx.lifecycle.Lifecycle.Event.ON_RESUME; 21 22 import static com.android.settings.network.InternetUpdater.INTERNET_CELLULAR; 23 import static com.android.settings.network.InternetUpdater.INTERNET_ETHERNET; 24 import static com.android.settings.network.InternetUpdater.INTERNET_NETWORKS_AVAILABLE; 25 import static com.android.settings.network.InternetUpdater.INTERNET_OFF; 26 import static com.android.settings.network.InternetUpdater.INTERNET_WIFI; 27 import static com.android.settingslib.wifi.WifiUtils.getHotspotIconResource; 28 29 import android.content.Context; 30 import android.graphics.drawable.Drawable; 31 import android.telephony.SubscriptionManager; 32 33 import androidx.annotation.IdRes; 34 import androidx.annotation.VisibleForTesting; 35 import androidx.lifecycle.Lifecycle; 36 import androidx.lifecycle.LifecycleObserver; 37 import androidx.lifecycle.LifecycleOwner; 38 import androidx.lifecycle.OnLifecycleEvent; 39 import androidx.preference.Preference; 40 import androidx.preference.PreferenceScreen; 41 42 import com.android.settings.R; 43 import com.android.settings.widget.SummaryUpdater; 44 import com.android.settings.wifi.WifiPickerTrackerHelper; 45 import com.android.settings.wifi.WifiSummaryUpdater; 46 import com.android.settings.wifi.repository.SharedConnectivityRepository; 47 import com.android.settingslib.Utils; 48 import com.android.settingslib.core.AbstractPreferenceController; 49 import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; 50 import com.android.settingslib.utils.ThreadUtils; 51 import com.android.wifitrackerlib.HotspotNetworkEntry; 52 import com.android.wifitrackerlib.WifiEntry; 53 import com.android.wifitrackerlib.WifiPickerTracker; 54 55 import java.util.ArrayList; 56 import java.util.HashMap; 57 import java.util.List; 58 import java.util.Map; 59 60 /** 61 * PreferenceController to update the internet state. 62 */ 63 public class InternetPreferenceController extends AbstractPreferenceController implements 64 LifecycleObserver, SummaryUpdater.OnSummaryChangeListener, 65 InternetUpdater.InternetChangeListener, MobileNetworkRepository.MobileNetworkCallback, 66 DefaultSubscriptionReceiver.DefaultSubscriptionListener, 67 WifiPickerTracker.WifiPickerTrackerCallback { 68 69 public static final String KEY = "internet_settings"; 70 71 private Preference mPreference; 72 @VisibleForTesting 73 WifiSummaryUpdater mSummaryHelper; 74 private InternetUpdater mInternetUpdater; 75 private @InternetUpdater.InternetType int mInternetType; 76 private LifecycleOwner mLifecycleOwner; 77 private MobileNetworkRepository mMobileNetworkRepository; 78 private List<SubscriptionInfoEntity> mSubInfoEntityList = new ArrayList<>(); 79 private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 80 private DefaultSubscriptionReceiver mDataSubscriptionChangedReceiver; 81 private boolean mIsHotspotNetworkEnabled = SharedConnectivityRepository.isDeviceConfigEnabled(); 82 @VisibleForTesting 83 WifiPickerTrackerHelper mWifiPickerTrackerHelper; 84 85 @VisibleForTesting 86 static Map<Integer, Integer> sIconMap = new HashMap<>(); 87 static { sIconMap.put(INTERNET_OFF, R.drawable.ic_no_internet_unavailable)88 sIconMap.put(INTERNET_OFF, R.drawable.ic_no_internet_unavailable); sIconMap.put(INTERNET_NETWORKS_AVAILABLE, R.drawable.ic_no_internet_available)89 sIconMap.put(INTERNET_NETWORKS_AVAILABLE, R.drawable.ic_no_internet_available); sIconMap.put(INTERNET_WIFI, R.drawable.ic_wifi_signal_4)90 sIconMap.put(INTERNET_WIFI, R.drawable.ic_wifi_signal_4); sIconMap.put(INTERNET_CELLULAR, R.drawable.ic_network_cell)91 sIconMap.put(INTERNET_CELLULAR, R.drawable.ic_network_cell); sIconMap.put(INTERNET_ETHERNET, R.drawable.ic_settings_ethernet)92 sIconMap.put(INTERNET_ETHERNET, R.drawable.ic_settings_ethernet); 93 } 94 95 private static Map<Integer, Integer> sSummaryMap = new HashMap<>(); 96 static { sSummaryMap.put(INTERNET_OFF, R.string.condition_airplane_title)97 sSummaryMap.put(INTERNET_OFF, R.string.condition_airplane_title); sSummaryMap.put(INTERNET_NETWORKS_AVAILABLE, R.string.networks_available)98 sSummaryMap.put(INTERNET_NETWORKS_AVAILABLE, R.string.networks_available); sSummaryMap.put(INTERNET_WIFI, 0)99 sSummaryMap.put(INTERNET_WIFI, 0); sSummaryMap.put(INTERNET_CELLULAR, 0)100 sSummaryMap.put(INTERNET_CELLULAR, 0); sSummaryMap.put(INTERNET_ETHERNET, R.string.to_switch_networks_disconnect_ethernet)101 sSummaryMap.put(INTERNET_ETHERNET, R.string.to_switch_networks_disconnect_ethernet); 102 } 103 InternetPreferenceController(Context context, Lifecycle lifecycle, LifecycleOwner lifecycleOwner)104 public InternetPreferenceController(Context context, Lifecycle lifecycle, 105 LifecycleOwner lifecycleOwner) { 106 super(context); 107 if (lifecycle == null) { 108 throw new IllegalArgumentException("Lifecycle must be set"); 109 } 110 mSummaryHelper = new WifiSummaryUpdater(mContext, this); 111 mInternetUpdater = new InternetUpdater(context, lifecycle, this); 112 mInternetType = mInternetUpdater.getInternetType(); 113 mLifecycleOwner = lifecycleOwner; 114 mMobileNetworkRepository = MobileNetworkRepository.getInstance(context); 115 mDataSubscriptionChangedReceiver = new DefaultSubscriptionReceiver(context, this); 116 if (mIsHotspotNetworkEnabled) { 117 mWifiPickerTrackerHelper = new WifiPickerTrackerHelper(lifecycle, context, this); 118 } 119 lifecycle.addObserver(this); 120 } 121 122 @Override displayPreference(PreferenceScreen screen)123 public void displayPreference(PreferenceScreen screen) { 124 super.displayPreference(screen); 125 mPreference = screen.findPreference(KEY); 126 } 127 drawIcon(int iconResId)128 private void drawIcon(int iconResId) { 129 Drawable drawable = mContext.getDrawable(iconResId); 130 if (drawable != null) { 131 drawable.setTintList(Utils.getColorAttr(mContext, android.R.attr.colorControlNormal)); 132 mPreference.setIcon(drawable); 133 } 134 } 135 136 @Override updateState(Preference preference)137 public void updateState(Preference preference) { 138 if (mPreference == null) { 139 return; 140 } 141 142 if (mInternetType == INTERNET_WIFI && updateHotspotNetwork()) { 143 return; 144 } 145 146 final @IdRes int icon = sIconMap.get(mInternetType); 147 if (icon != 0) { 148 drawIcon(icon); 149 } 150 151 if (mInternetType == INTERNET_WIFI) { 152 mPreference.setSummary(mSummaryHelper.getSummary()); 153 return; 154 } 155 156 if (mInternetType == INTERNET_CELLULAR) { 157 updateCellularSummary(); 158 return; 159 } 160 161 final @IdRes int summary = sSummaryMap.get(mInternetType); 162 if (summary != 0) { 163 mPreference.setSummary(summary); 164 } 165 } 166 167 @VisibleForTesting updateHotspotNetwork()168 boolean updateHotspotNetwork() { 169 if (mWifiPickerTrackerHelper == null) { 170 return false; 171 } 172 WifiEntry entry = mWifiPickerTrackerHelper.getWifiPickerTracker().getConnectedWifiEntry(); 173 if (!(entry instanceof HotspotNetworkEntry)) { 174 return false; 175 } 176 drawIcon(getHotspotIconResource(((HotspotNetworkEntry) entry).getDeviceType())); 177 mPreference.setSummary(((HotspotNetworkEntry) entry).getAlternateSummary()); 178 return true; 179 } 180 181 @Override isAvailable()182 public boolean isAvailable() { 183 return mContext.getResources().getBoolean(R.bool.config_show_internet_settings); 184 } 185 186 @Override getPreferenceKey()187 public String getPreferenceKey() { 188 return KEY; 189 } 190 191 /** @OnLifecycleEvent(ON_RESUME) */ 192 @OnLifecycleEvent(ON_RESUME) onResume()193 public void onResume() { 194 mMobileNetworkRepository.addRegister(mLifecycleOwner, this, 195 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 196 mMobileNetworkRepository.updateEntity(); 197 mSummaryHelper.register(true); 198 mDataSubscriptionChangedReceiver.registerReceiver(); 199 mDefaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 200 } 201 202 /** @OnLifecycleEvent(ON_PAUSE) */ 203 @OnLifecycleEvent(ON_PAUSE) onPause()204 public void onPause() { 205 mMobileNetworkRepository.removeRegister(this); 206 mSummaryHelper.register(false); 207 mDataSubscriptionChangedReceiver.unRegisterReceiver(); 208 } 209 210 /** 211 * Called when internet type is changed. 212 * 213 * @param internetType the internet type 214 */ 215 @Override onInternetTypeChanged(@nternetUpdater.InternetType int internetType)216 public void onInternetTypeChanged(@InternetUpdater.InternetType int internetType) { 217 final boolean needUpdate = (internetType != mInternetType); 218 mInternetType = internetType; 219 if (needUpdate) { 220 ThreadUtils.postOnMainThread(() -> { 221 updateState(mPreference); 222 }); 223 } 224 } 225 226 /** 227 * Called when airplane mode state is changed. 228 */ 229 @Override onAirplaneModeChanged(boolean isAirplaneModeOn)230 public void onAirplaneModeChanged(boolean isAirplaneModeOn) { 231 ThreadUtils.postOnMainThread(() -> { 232 updateState(mPreference); 233 }); 234 } 235 236 @Override onSummaryChanged(String summary)237 public void onSummaryChanged(String summary) { 238 if (mInternetType == INTERNET_WIFI) { 239 updateState(mPreference); 240 } 241 } 242 243 @VisibleForTesting updateCellularSummary()244 void updateCellularSummary() { 245 CharSequence summary = null; 246 SubscriptionInfoEntity activeSubInfo = null; 247 SubscriptionInfoEntity defaultSubInfo = null; 248 249 for (SubscriptionInfoEntity subInfo : getSubscriptionInfoList()) { 250 if (subInfo.isActiveDataSubscriptionId) { 251 activeSubInfo = subInfo; 252 } 253 if (subInfo.getSubId() == getDefaultDataSubscriptionId()) { 254 defaultSubInfo = subInfo; 255 } 256 } 257 if (activeSubInfo == null || defaultSubInfo == null) { 258 return; 259 } 260 activeSubInfo = activeSubInfo.isSubscriptionVisible ? activeSubInfo : defaultSubInfo; 261 262 if (activeSubInfo.equals(defaultSubInfo)) { 263 // DDS is active 264 summary = activeSubInfo.uniqueName; 265 } else { 266 summary = mContext.getString( 267 R.string.mobile_data_temp_using, activeSubInfo.uniqueName); 268 } 269 270 mPreference.setSummary(summary); 271 } 272 273 @VisibleForTesting getSubscriptionInfoList()274 protected List<SubscriptionInfoEntity> getSubscriptionInfoList() { 275 return mSubInfoEntityList; 276 } 277 278 @VisibleForTesting getDefaultDataSubscriptionId()279 protected int getDefaultDataSubscriptionId() { 280 return mDefaultDataSubId; 281 } 282 283 @Override onAvailableSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList)284 public void onAvailableSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) { 285 mSubInfoEntityList = subInfoEntityList; 286 updateState(mPreference); 287 } 288 289 @Override onDefaultDataChanged(int defaultDataSubId)290 public void onDefaultDataChanged(int defaultDataSubId) { 291 mDefaultDataSubId = defaultDataSubId; 292 updateState(mPreference); 293 } 294 295 @Override onWifiEntriesChanged()296 public void onWifiEntriesChanged() { 297 if (mInternetType == INTERNET_WIFI) { 298 updateState(mPreference); 299 } 300 } 301 302 @Override onWifiStateChanged()303 public void onWifiStateChanged() { 304 // Do nothing 305 } 306 307 @Override onNumSavedNetworksChanged()308 public void onNumSavedNetworksChanged() { 309 // Do nothing 310 } 311 312 @Override onNumSavedSubscriptionsChanged()313 public void onNumSavedSubscriptionsChanged() { 314 // Do nothing 315 } 316 } 317