1 /* 2 * Copyright (C) 2021 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 package com.android.systemui.qs.tiles.dialog; 17 18 import static com.android.systemui.Prefs.Key.QS_HAS_TURNED_OFF_MOBILE_DATA; 19 import static com.android.systemui.qs.tiles.dialog.InternetDialogController.MAX_WIFI_ENTRY_COUNT; 20 21 import android.app.AlertDialog; 22 import android.content.Context; 23 import android.content.res.TypedArray; 24 import android.graphics.drawable.Drawable; 25 import android.net.Network; 26 import android.net.NetworkCapabilities; 27 import android.net.wifi.WifiManager; 28 import android.os.Bundle; 29 import android.os.Handler; 30 import android.telephony.ServiceState; 31 import android.telephony.SignalStrength; 32 import android.telephony.SubscriptionManager; 33 import android.telephony.TelephonyDisplayInfo; 34 import android.telephony.TelephonyManager; 35 import android.text.Html; 36 import android.text.TextUtils; 37 import android.text.method.LinkMovementMethod; 38 import android.util.Log; 39 import android.view.Gravity; 40 import android.view.LayoutInflater; 41 import android.view.View; 42 import android.view.Window; 43 import android.view.WindowManager; 44 import android.widget.Button; 45 import android.widget.FrameLayout; 46 import android.widget.ImageView; 47 import android.widget.LinearLayout; 48 import android.widget.ProgressBar; 49 import android.widget.Switch; 50 import android.widget.TextView; 51 52 import androidx.annotation.MainThread; 53 import androidx.annotation.Nullable; 54 import androidx.annotation.VisibleForTesting; 55 import androidx.annotation.WorkerThread; 56 import androidx.recyclerview.widget.LinearLayoutManager; 57 import androidx.recyclerview.widget.RecyclerView; 58 59 import com.android.internal.logging.UiEvent; 60 import com.android.internal.logging.UiEventLogger; 61 import com.android.settingslib.Utils; 62 import com.android.systemui.Prefs; 63 import com.android.systemui.R; 64 import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan; 65 import com.android.systemui.dagger.SysUISingleton; 66 import com.android.systemui.dagger.qualifiers.Background; 67 import com.android.systemui.dagger.qualifiers.Main; 68 import com.android.systemui.statusbar.phone.SystemUIDialog; 69 import com.android.wifitrackerlib.WifiEntry; 70 71 import java.util.List; 72 import java.util.concurrent.Executor; 73 74 /** 75 * Dialog for showing mobile network, connected Wi-Fi network and Wi-Fi networks. 76 */ 77 @SysUISingleton 78 public class InternetDialog extends SystemUIDialog implements 79 InternetDialogController.InternetDialogCallback, Window.Callback { 80 private static final String TAG = "InternetDialog"; 81 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 82 83 static final long PROGRESS_DELAY_MS = 1500L; 84 static final int MAX_NETWORK_COUNT = 4; 85 86 private final Handler mHandler; 87 private final Executor mBackgroundExecutor; 88 89 @VisibleForTesting 90 protected InternetAdapter mAdapter; 91 @VisibleForTesting 92 protected WifiManager mWifiManager; 93 @VisibleForTesting 94 protected View mDialogView; 95 @VisibleForTesting 96 protected boolean mCanConfigWifi; 97 98 private InternetDialogFactory mInternetDialogFactory; 99 private SubscriptionManager mSubscriptionManager; 100 private TelephonyManager mTelephonyManager; 101 private AlertDialog mAlertDialog; 102 private UiEventLogger mUiEventLogger; 103 private Context mContext; 104 private InternetDialogController mInternetDialogController; 105 private TextView mInternetDialogTitle; 106 private TextView mInternetDialogSubTitle; 107 private View mDivider; 108 private ProgressBar mProgressBar; 109 private LinearLayout mInternetDialogLayout; 110 private LinearLayout mConnectedWifListLayout; 111 private LinearLayout mMobileNetworkLayout; 112 private LinearLayout mTurnWifiOnLayout; 113 private LinearLayout mEthernetLayout; 114 private TextView mWifiToggleTitleText; 115 private LinearLayout mWifiScanNotifyLayout; 116 private TextView mWifiScanNotifyText; 117 private LinearLayout mSeeAllLayout; 118 private RecyclerView mWifiRecyclerView; 119 private ImageView mConnectedWifiIcon; 120 private ImageView mWifiSettingsIcon; 121 private TextView mConnectedWifiTitleText; 122 private TextView mConnectedWifiSummaryText; 123 private ImageView mSignalIcon; 124 private TextView mMobileTitleText; 125 private TextView mMobileSummaryText; 126 private TextView mAirplaneModeSummaryText; 127 private Switch mMobileDataToggle; 128 private View mMobileToggleDivider; 129 private Switch mWiFiToggle; 130 private Button mDoneButton; 131 private Button mAirplaneModeButton; 132 private Drawable mBackgroundOn; 133 private Drawable mBackgroundOff = null; 134 private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 135 private boolean mCanConfigMobileData; 136 137 // Wi-Fi entries 138 private int mWifiNetworkHeight; 139 @VisibleForTesting 140 protected WifiEntry mConnectedWifiEntry; 141 @VisibleForTesting 142 protected int mWifiEntriesCount; 143 @VisibleForTesting 144 protected boolean mHasMoreWifiEntries; 145 146 // Wi-Fi scanning progress bar 147 protected boolean mIsProgressBarVisible; 148 protected boolean mIsSearchingHidden; 149 protected final Runnable mHideProgressBarRunnable = () -> { 150 setProgressBarVisible(false); 151 }; 152 protected Runnable mHideSearchingRunnable = () -> { 153 mIsSearchingHidden = true; 154 mInternetDialogSubTitle.setText(getSubtitleText()); 155 }; 156 InternetDialog(Context context, InternetDialogFactory internetDialogFactory, InternetDialogController internetDialogController, boolean canConfigMobileData, boolean canConfigWifi, boolean aboveStatusBar, UiEventLogger uiEventLogger, @Main Handler handler, @Background Executor executor)157 public InternetDialog(Context context, InternetDialogFactory internetDialogFactory, 158 InternetDialogController internetDialogController, boolean canConfigMobileData, 159 boolean canConfigWifi, boolean aboveStatusBar, UiEventLogger uiEventLogger, 160 @Main Handler handler, @Background Executor executor) { 161 super(context); 162 if (DEBUG) { 163 Log.d(TAG, "Init InternetDialog"); 164 } 165 166 // Save the context that is wrapped with our theme. 167 mContext = getContext(); 168 mHandler = handler; 169 mBackgroundExecutor = executor; 170 mInternetDialogFactory = internetDialogFactory; 171 mInternetDialogController = internetDialogController; 172 mSubscriptionManager = mInternetDialogController.getSubscriptionManager(); 173 mDefaultDataSubId = mInternetDialogController.getDefaultDataSubscriptionId(); 174 mTelephonyManager = mInternetDialogController.getTelephonyManager(); 175 mWifiManager = mInternetDialogController.getWifiManager(); 176 mCanConfigMobileData = canConfigMobileData; 177 mCanConfigWifi = canConfigWifi; 178 179 mUiEventLogger = uiEventLogger; 180 mAdapter = new InternetAdapter(mInternetDialogController); 181 if (!aboveStatusBar) { 182 getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); 183 } 184 } 185 186 @Override onCreate(Bundle savedInstanceState)187 public void onCreate(Bundle savedInstanceState) { 188 super.onCreate(savedInstanceState); 189 if (DEBUG) { 190 Log.d(TAG, "onCreate"); 191 } 192 mUiEventLogger.log(InternetDialogEvent.INTERNET_DIALOG_SHOW); 193 mDialogView = LayoutInflater.from(mContext).inflate(R.layout.internet_connectivity_dialog, 194 null); 195 final Window window = getWindow(); 196 window.setContentView(mDialogView); 197 198 window.setWindowAnimations(R.style.Animation_InternetDialog); 199 200 mWifiNetworkHeight = mContext.getResources() 201 .getDimensionPixelSize(R.dimen.internet_dialog_wifi_network_height); 202 203 mInternetDialogLayout = mDialogView.requireViewById(R.id.internet_connectivity_dialog); 204 mInternetDialogTitle = mDialogView.requireViewById(R.id.internet_dialog_title); 205 mInternetDialogSubTitle = mDialogView.requireViewById(R.id.internet_dialog_subtitle); 206 mDivider = mDialogView.requireViewById(R.id.divider); 207 mProgressBar = mDialogView.requireViewById(R.id.wifi_searching_progress); 208 mEthernetLayout = mDialogView.requireViewById(R.id.ethernet_layout); 209 mMobileNetworkLayout = mDialogView.requireViewById(R.id.mobile_network_layout); 210 mTurnWifiOnLayout = mDialogView.requireViewById(R.id.turn_on_wifi_layout); 211 mWifiToggleTitleText = mDialogView.requireViewById(R.id.wifi_toggle_title); 212 mWifiScanNotifyLayout = mDialogView.requireViewById(R.id.wifi_scan_notify_layout); 213 mWifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text); 214 mConnectedWifListLayout = mDialogView.requireViewById(R.id.wifi_connected_layout); 215 mConnectedWifiIcon = mDialogView.requireViewById(R.id.wifi_connected_icon); 216 mConnectedWifiTitleText = mDialogView.requireViewById(R.id.wifi_connected_title); 217 mConnectedWifiSummaryText = mDialogView.requireViewById(R.id.wifi_connected_summary); 218 mWifiSettingsIcon = mDialogView.requireViewById(R.id.wifi_settings_icon); 219 mWifiRecyclerView = mDialogView.requireViewById(R.id.wifi_list_layout); 220 mSeeAllLayout = mDialogView.requireViewById(R.id.see_all_layout); 221 mDoneButton = mDialogView.requireViewById(R.id.done_button); 222 mAirplaneModeButton = mDialogView.requireViewById(R.id.apm_button); 223 mSignalIcon = mDialogView.requireViewById(R.id.signal_icon); 224 mMobileTitleText = mDialogView.requireViewById(R.id.mobile_title); 225 mMobileSummaryText = mDialogView.requireViewById(R.id.mobile_summary); 226 mAirplaneModeSummaryText = mDialogView.requireViewById(R.id.airplane_mode_summary); 227 mMobileToggleDivider = mDialogView.requireViewById(R.id.mobile_toggle_divider); 228 mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_toggle); 229 mWiFiToggle = mDialogView.requireViewById(R.id.wifi_toggle); 230 mBackgroundOn = mContext.getDrawable(R.drawable.settingslib_switch_bar_bg_on); 231 mInternetDialogTitle.setText(getDialogTitleText()); 232 mInternetDialogTitle.setGravity(Gravity.START | Gravity.CENTER_VERTICAL); 233 234 TypedArray typedArray = mContext.obtainStyledAttributes( 235 new int[]{android.R.attr.selectableItemBackground}); 236 try { 237 mBackgroundOff = typedArray.getDrawable(0 /* index */); 238 } finally { 239 typedArray.recycle(); 240 } 241 242 setOnClickListener(); 243 mTurnWifiOnLayout.setBackground(null); 244 mAirplaneModeButton.setVisibility( 245 mInternetDialogController.isAirplaneModeEnabled() ? View.VISIBLE : View.GONE); 246 mWifiRecyclerView.setLayoutManager(new LinearLayoutManager(mContext)); 247 mWifiRecyclerView.setAdapter(mAdapter); 248 } 249 250 @Override onStart()251 public void onStart() { 252 super.onStart(); 253 if (DEBUG) { 254 Log.d(TAG, "onStart"); 255 } 256 mInternetDialogController.onStart(this, mCanConfigWifi); 257 if (!mCanConfigWifi) { 258 hideWifiViews(); 259 } 260 } 261 262 @VisibleForTesting hideWifiViews()263 void hideWifiViews() { 264 setProgressBarVisible(false); 265 mTurnWifiOnLayout.setVisibility(View.GONE); 266 mConnectedWifListLayout.setVisibility(View.GONE); 267 mWifiRecyclerView.setVisibility(View.GONE); 268 mSeeAllLayout.setVisibility(View.GONE); 269 } 270 271 @Override onStop()272 public void onStop() { 273 super.onStop(); 274 if (DEBUG) { 275 Log.d(TAG, "onStop"); 276 } 277 mHandler.removeCallbacks(mHideProgressBarRunnable); 278 mHandler.removeCallbacks(mHideSearchingRunnable); 279 mMobileNetworkLayout.setOnClickListener(null); 280 mMobileDataToggle.setOnCheckedChangeListener(null); 281 mConnectedWifListLayout.setOnClickListener(null); 282 mSeeAllLayout.setOnClickListener(null); 283 mWiFiToggle.setOnCheckedChangeListener(null); 284 mDoneButton.setOnClickListener(null); 285 mAirplaneModeButton.setOnClickListener(null); 286 mInternetDialogController.onStop(); 287 mInternetDialogFactory.destroyDialog(); 288 } 289 290 @Override dismissDialog()291 public void dismissDialog() { 292 if (DEBUG) { 293 Log.d(TAG, "dismissDialog"); 294 } 295 mInternetDialogFactory.destroyDialog(); 296 dismiss(); 297 } 298 299 /** 300 * Update the internet dialog when receiving the callback. 301 * 302 * @param shouldUpdateMobileNetwork {@code true} for update the mobile network layout, 303 * otherwise {@code false}. 304 */ updateDialog(boolean shouldUpdateMobileNetwork)305 void updateDialog(boolean shouldUpdateMobileNetwork) { 306 if (DEBUG) { 307 Log.d(TAG, "updateDialog"); 308 } 309 mInternetDialogTitle.setText(getDialogTitleText()); 310 mInternetDialogSubTitle.setText(getSubtitleText()); 311 mAirplaneModeButton.setVisibility( 312 mInternetDialogController.isAirplaneModeEnabled() ? View.VISIBLE : View.GONE); 313 314 updateEthernet(); 315 if (shouldUpdateMobileNetwork) { 316 setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular(), 317 mInternetDialogController.isCarrierNetworkActive()); 318 } 319 320 if (!mCanConfigWifi) { 321 return; 322 } 323 324 showProgressBar(); 325 final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked(); 326 final boolean isWifiEnabled = mWifiManager.isWifiEnabled(); 327 final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled(); 328 updateWifiToggle(isWifiEnabled, isDeviceLocked); 329 updateConnectedWifi(isWifiEnabled, isDeviceLocked); 330 updateWifiListAndSeeAll(isWifiEnabled, isDeviceLocked); 331 updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked); 332 } 333 setOnClickListener()334 private void setOnClickListener() { 335 mMobileNetworkLayout.setOnClickListener(v -> { 336 if (mInternetDialogController.isMobileDataEnabled() 337 && !mInternetDialogController.isDeviceLocked()) { 338 if (!mInternetDialogController.activeNetworkIsCellular()) { 339 mInternetDialogController.connectCarrierNetwork(); 340 } 341 } 342 }); 343 mMobileDataToggle.setOnCheckedChangeListener( 344 (buttonView, isChecked) -> { 345 if (!isChecked && shouldShowMobileDialog()) { 346 showTurnOffMobileDialog(); 347 } else if (!shouldShowMobileDialog()) { 348 mInternetDialogController.setMobileDataEnabled(mContext, mDefaultDataSubId, 349 isChecked, false); 350 } 351 }); 352 mConnectedWifListLayout.setOnClickListener(v -> onClickConnectedWifi()); 353 mSeeAllLayout.setOnClickListener(v -> onClickSeeMoreButton()); 354 mWiFiToggle.setOnCheckedChangeListener( 355 (buttonView, isChecked) -> { 356 buttonView.setChecked(isChecked); 357 mWifiManager.setWifiEnabled(isChecked); 358 }); 359 mDoneButton.setOnClickListener(v -> dismiss()); 360 mAirplaneModeButton.setOnClickListener(v -> { 361 mInternetDialogController.setAirplaneModeDisabled(); 362 }); 363 } 364 365 @MainThread updateEthernet()366 private void updateEthernet() { 367 mEthernetLayout.setVisibility( 368 mInternetDialogController.hasEthernet() ? View.VISIBLE : View.GONE); 369 } 370 setMobileDataLayout(boolean activeNetworkIsCellular, boolean isCarrierNetworkActive)371 private void setMobileDataLayout(boolean activeNetworkIsCellular, 372 boolean isCarrierNetworkActive) { 373 boolean isNetworkConnected = activeNetworkIsCellular || isCarrierNetworkActive; 374 // 1. Mobile network should be gone if airplane mode ON or the list of active 375 // subscriptionId is null. 376 // 2. Carrier network should be gone if airplane mode ON and Wi-Fi is OFF. 377 if (DEBUG) { 378 Log.d(TAG, "setMobileDataLayout, isCarrierNetworkActive = " + isCarrierNetworkActive); 379 } 380 381 if (!mInternetDialogController.hasActiveSubId() 382 && (!mWifiManager.isWifiEnabled() || !isCarrierNetworkActive)) { 383 mMobileNetworkLayout.setVisibility(View.GONE); 384 } else { 385 mMobileNetworkLayout.setVisibility(View.VISIBLE); 386 mMobileDataToggle.setChecked(mInternetDialogController.isMobileDataEnabled()); 387 mMobileTitleText.setText(getMobileNetworkTitle()); 388 String summary = getMobileNetworkSummary(); 389 if (!TextUtils.isEmpty(summary)) { 390 mMobileSummaryText.setText( 391 Html.fromHtml(summary, Html.FROM_HTML_MODE_LEGACY)); 392 mMobileSummaryText.setVisibility(View.VISIBLE); 393 } else { 394 mMobileSummaryText.setVisibility(View.GONE); 395 } 396 mBackgroundExecutor.execute(() -> { 397 Drawable drawable = getSignalStrengthDrawable(); 398 mHandler.post(() -> { 399 mSignalIcon.setImageDrawable(drawable); 400 }); 401 }); 402 mMobileTitleText.setTextAppearance(isNetworkConnected 403 ? R.style.TextAppearance_InternetDialog_Active 404 : R.style.TextAppearance_InternetDialog); 405 int secondaryRes = isNetworkConnected 406 ? R.style.TextAppearance_InternetDialog_Secondary_Active 407 : R.style.TextAppearance_InternetDialog_Secondary; 408 mMobileSummaryText.setTextAppearance(secondaryRes); 409 // Set airplane mode to the summary for carrier network 410 if (mInternetDialogController.isAirplaneModeEnabled()) { 411 mAirplaneModeSummaryText.setVisibility(View.VISIBLE); 412 mAirplaneModeSummaryText.setText(mContext.getText(R.string.airplane_mode)); 413 mAirplaneModeSummaryText.setTextAppearance(secondaryRes); 414 } else { 415 mAirplaneModeSummaryText.setVisibility(View.GONE); 416 } 417 mMobileNetworkLayout.setBackground( 418 isNetworkConnected ? mBackgroundOn : mBackgroundOff); 419 420 TypedArray array = mContext.obtainStyledAttributes( 421 R.style.InternetDialog_Divider_Active, new int[]{android.R.attr.background}); 422 int dividerColor = Utils.getColorAttrDefaultColor(mContext, 423 android.R.attr.textColorSecondary); 424 mMobileToggleDivider.setBackgroundColor(isNetworkConnected 425 ? array.getColor(0, dividerColor) : dividerColor); 426 array.recycle(); 427 428 mMobileDataToggle.setVisibility(mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE); 429 mMobileToggleDivider.setVisibility( 430 mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE); 431 } 432 } 433 434 @MainThread updateWifiToggle(boolean isWifiEnabled, boolean isDeviceLocked)435 private void updateWifiToggle(boolean isWifiEnabled, boolean isDeviceLocked) { 436 mWiFiToggle.setChecked(isWifiEnabled); 437 if (isDeviceLocked) { 438 mWifiToggleTitleText.setTextAppearance((mConnectedWifiEntry != null) 439 ? R.style.TextAppearance_InternetDialog_Active 440 : R.style.TextAppearance_InternetDialog); 441 } 442 mTurnWifiOnLayout.setBackground( 443 (isDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn : null); 444 } 445 446 @MainThread updateConnectedWifi(boolean isWifiEnabled, boolean isDeviceLocked)447 private void updateConnectedWifi(boolean isWifiEnabled, boolean isDeviceLocked) { 448 if (!isWifiEnabled || mConnectedWifiEntry == null || isDeviceLocked) { 449 mConnectedWifListLayout.setVisibility(View.GONE); 450 return; 451 } 452 mConnectedWifListLayout.setVisibility(View.VISIBLE); 453 mConnectedWifiTitleText.setText(mConnectedWifiEntry.getTitle()); 454 mConnectedWifiSummaryText.setText(mConnectedWifiEntry.getSummary(false)); 455 mConnectedWifiIcon.setImageDrawable( 456 mInternetDialogController.getInternetWifiDrawable(mConnectedWifiEntry)); 457 mWifiSettingsIcon.setColorFilter( 458 mContext.getColor(R.color.connected_network_primary_color)); 459 } 460 461 @MainThread updateWifiListAndSeeAll(boolean isWifiEnabled, boolean isDeviceLocked)462 private void updateWifiListAndSeeAll(boolean isWifiEnabled, boolean isDeviceLocked) { 463 if (!isWifiEnabled || isDeviceLocked) { 464 mWifiRecyclerView.setVisibility(View.GONE); 465 mSeeAllLayout.setVisibility(View.GONE); 466 return; 467 } 468 final int wifiListMaxCount = getWifiListMaxCount(); 469 if (mAdapter.getItemCount() > wifiListMaxCount) { 470 mHasMoreWifiEntries = true; 471 } 472 mAdapter.setMaxEntriesCount(wifiListMaxCount); 473 final int wifiListMinHeight = mWifiNetworkHeight * wifiListMaxCount; 474 if (mWifiRecyclerView.getMinimumHeight() != wifiListMinHeight) { 475 mWifiRecyclerView.setMinimumHeight(wifiListMinHeight); 476 } 477 mWifiRecyclerView.setVisibility(View.VISIBLE); 478 mSeeAllLayout.setVisibility(mHasMoreWifiEntries ? View.VISIBLE : View.INVISIBLE); 479 } 480 481 @VisibleForTesting 482 @MainThread getWifiListMaxCount()483 int getWifiListMaxCount() { 484 // Use the maximum count of networks to calculate the remaining count for Wi-Fi networks. 485 int count = MAX_NETWORK_COUNT; 486 if (mEthernetLayout.getVisibility() == View.VISIBLE) { 487 count -= 1; 488 } 489 if (mMobileNetworkLayout.getVisibility() == View.VISIBLE) { 490 count -= 1; 491 } 492 493 // If the remaining count is greater than the maximum count of the Wi-Fi network, the 494 // maximum count of the Wi-Fi network is used. 495 if (count > MAX_WIFI_ENTRY_COUNT) { 496 count = MAX_WIFI_ENTRY_COUNT; 497 } 498 if (mConnectedWifListLayout.getVisibility() == View.VISIBLE) { 499 count -= 1; 500 } 501 return count; 502 } 503 504 @MainThread updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled, boolean isDeviceLocked)505 private void updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled, 506 boolean isDeviceLocked) { 507 if (isWifiEnabled || !isWifiScanEnabled || isDeviceLocked) { 508 mWifiScanNotifyLayout.setVisibility(View.GONE); 509 return; 510 } 511 if (TextUtils.isEmpty(mWifiScanNotifyText.getText())) { 512 final AnnotationLinkSpan.LinkInfo linkInfo = new AnnotationLinkSpan.LinkInfo( 513 AnnotationLinkSpan.LinkInfo.DEFAULT_ANNOTATION, 514 v -> mInternetDialogController.launchWifiScanningSetting()); 515 mWifiScanNotifyText.setText(AnnotationLinkSpan.linkify( 516 getContext().getText(R.string.wifi_scan_notify_message), linkInfo)); 517 mWifiScanNotifyText.setMovementMethod(LinkMovementMethod.getInstance()); 518 } 519 mWifiScanNotifyLayout.setVisibility(View.VISIBLE); 520 } 521 onClickConnectedWifi()522 void onClickConnectedWifi() { 523 if (mConnectedWifiEntry == null) { 524 return; 525 } 526 mInternetDialogController.launchWifiNetworkDetailsSetting(mConnectedWifiEntry.getKey()); 527 } 528 onClickSeeMoreButton()529 void onClickSeeMoreButton() { 530 mInternetDialogController.launchNetworkSetting(); 531 } 532 getDialogTitleText()533 CharSequence getDialogTitleText() { 534 return mInternetDialogController.getDialogTitleText(); 535 } 536 getSubtitleText()537 CharSequence getSubtitleText() { 538 return mInternetDialogController.getSubtitleText( 539 mIsProgressBarVisible && !mIsSearchingHidden); 540 } 541 getSignalStrengthDrawable()542 private Drawable getSignalStrengthDrawable() { 543 return mInternetDialogController.getSignalStrengthDrawable(); 544 } 545 getMobileNetworkTitle()546 CharSequence getMobileNetworkTitle() { 547 return mInternetDialogController.getMobileNetworkTitle(); 548 } 549 getMobileNetworkSummary()550 String getMobileNetworkSummary() { 551 return mInternetDialogController.getMobileNetworkSummary(); 552 } 553 showProgressBar()554 protected void showProgressBar() { 555 if (mWifiManager == null || !mWifiManager.isWifiEnabled() 556 || mInternetDialogController.isDeviceLocked()) { 557 setProgressBarVisible(false); 558 return; 559 } 560 setProgressBarVisible(true); 561 if (mConnectedWifiEntry != null || mWifiEntriesCount > 0) { 562 mHandler.postDelayed(mHideProgressBarRunnable, PROGRESS_DELAY_MS); 563 } else if (!mIsSearchingHidden) { 564 mHandler.postDelayed(mHideSearchingRunnable, PROGRESS_DELAY_MS); 565 } 566 } 567 setProgressBarVisible(boolean visible)568 private void setProgressBarVisible(boolean visible) { 569 if (mIsProgressBarVisible == visible) { 570 return; 571 } 572 mIsProgressBarVisible = visible; 573 mProgressBar.setVisibility(visible ? View.VISIBLE : View.GONE); 574 mProgressBar.setIndeterminate(visible); 575 mDivider.setVisibility(visible ? View.GONE : View.VISIBLE); 576 mInternetDialogSubTitle.setText(getSubtitleText()); 577 } 578 shouldShowMobileDialog()579 private boolean shouldShowMobileDialog() { 580 boolean flag = Prefs.getBoolean(mContext, QS_HAS_TURNED_OFF_MOBILE_DATA, 581 false); 582 if (mInternetDialogController.isMobileDataEnabled() && !flag) { 583 return true; 584 } 585 return false; 586 } 587 showTurnOffMobileDialog()588 private void showTurnOffMobileDialog() { 589 CharSequence carrierName = getMobileNetworkTitle(); 590 boolean isInService = mInternetDialogController.isVoiceStateInService(); 591 if (TextUtils.isEmpty(carrierName) || !isInService) { 592 carrierName = mContext.getString(R.string.mobile_data_disable_message_default_carrier); 593 } 594 mAlertDialog = new Builder(mContext) 595 .setTitle(R.string.mobile_data_disable_title) 596 .setMessage(mContext.getString(R.string.mobile_data_disable_message, carrierName)) 597 .setNegativeButton(android.R.string.cancel, (d, w) -> { 598 mMobileDataToggle.setChecked(true); 599 }) 600 .setPositiveButton( 601 com.android.internal.R.string.alert_windows_notification_turn_off_action, 602 (d, w) -> { 603 mInternetDialogController.setMobileDataEnabled(mContext, 604 mDefaultDataSubId, false, false); 605 mMobileDataToggle.setChecked(false); 606 Prefs.putBoolean(mContext, QS_HAS_TURNED_OFF_MOBILE_DATA, true); 607 }) 608 .create(); 609 mAlertDialog.setOnCancelListener(dialog -> mMobileDataToggle.setChecked(true)); 610 mAlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 611 SystemUIDialog.setShowForAllUsers(mAlertDialog, true); 612 SystemUIDialog.registerDismissListener(mAlertDialog); 613 SystemUIDialog.setWindowOnTop(mAlertDialog); 614 mAlertDialog.show(); 615 } 616 617 @Override onRefreshCarrierInfo()618 public void onRefreshCarrierInfo() { 619 mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); 620 } 621 622 @Override onSimStateChanged()623 public void onSimStateChanged() { 624 mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); 625 } 626 627 @Override 628 @WorkerThread onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities)629 public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { 630 mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); 631 } 632 633 @Override 634 @WorkerThread onLost(Network network)635 public void onLost(Network network) { 636 mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); 637 } 638 639 @Override onSubscriptionsChanged(int defaultDataSubId)640 public void onSubscriptionsChanged(int defaultDataSubId) { 641 mDefaultDataSubId = defaultDataSubId; 642 mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId); 643 mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); 644 } 645 646 @Override onUserMobileDataStateChanged(boolean enabled)647 public void onUserMobileDataStateChanged(boolean enabled) { 648 mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); 649 } 650 651 @Override onServiceStateChanged(ServiceState serviceState)652 public void onServiceStateChanged(ServiceState serviceState) { 653 mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); 654 } 655 656 @Override 657 @WorkerThread onDataConnectionStateChanged(int state, int networkType)658 public void onDataConnectionStateChanged(int state, int networkType) { 659 mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); 660 } 661 662 @Override onSignalStrengthsChanged(SignalStrength signalStrength)663 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 664 mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); 665 } 666 667 @Override onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo)668 public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) { 669 mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); 670 } 671 672 @Override 673 @WorkerThread onAccessPointsChanged(@ullable List<WifiEntry> wifiEntries, @Nullable WifiEntry connectedEntry, boolean hasMoreWifiEntries)674 public void onAccessPointsChanged(@Nullable List<WifiEntry> wifiEntries, 675 @Nullable WifiEntry connectedEntry, boolean hasMoreWifiEntries) { 676 // Should update the carrier network layout when it is connected under airplane mode ON. 677 boolean shouldUpdateCarrierNetwork = mMobileNetworkLayout.getVisibility() == View.VISIBLE 678 && mInternetDialogController.isAirplaneModeEnabled(); 679 mHandler.post(() -> { 680 mConnectedWifiEntry = connectedEntry; 681 mWifiEntriesCount = wifiEntries == null ? 0 : wifiEntries.size(); 682 mHasMoreWifiEntries = hasMoreWifiEntries; 683 updateDialog(shouldUpdateCarrierNetwork /* shouldUpdateMobileNetwork */); 684 mAdapter.setWifiEntries(wifiEntries, mWifiEntriesCount); 685 mAdapter.notifyDataSetChanged(); 686 }); 687 } 688 689 @Override onWindowFocusChanged(boolean hasFocus)690 public void onWindowFocusChanged(boolean hasFocus) { 691 super.onWindowFocusChanged(hasFocus); 692 if (mAlertDialog != null && !mAlertDialog.isShowing()) { 693 if (!hasFocus && isShowing()) { 694 dismiss(); 695 } 696 } 697 } 698 699 public enum InternetDialogEvent implements UiEventLogger.UiEventEnum { 700 @UiEvent(doc = "The Internet dialog became visible on the screen.") 701 INTERNET_DIALOG_SHOW(843); 702 703 private final int mId; 704 InternetDialogEvent(int id)705 InternetDialogEvent(int id) { 706 mId = id; 707 } 708 709 @Override getId()710 public int getId() { 711 return mId; 712 } 713 } 714 } 715