diff options
Diffstat (limited to 'packages/SystemUI/src')
6 files changed, 876 insertions, 3 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index 76f30a80114a..00b33a416df4 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -65,6 +65,7 @@ import com.android.systemui.power.EnhancedEstimates; import com.android.systemui.power.PowerUI; import com.android.systemui.privacy.PrivacyItemController; import com.android.systemui.qs.ReduceBrightColorsController; +import com.android.systemui.qs.tiles.dialog.InternetDialogFactory; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.recents.Recents; import com.android.systemui.screenrecord.RecordingController; @@ -364,6 +365,7 @@ public class Dependency { @Inject Lazy<UiEventLogger> mUiEventLogger; @Inject Lazy<FeatureFlags> mFeatureFlagsLazy; @Inject Lazy<StatusBarContentInsetsProvider> mContentInsetsProviderLazy; + @Inject Lazy<InternetDialogFactory> mInternetDialogFactory; @Inject public Dependency() { @@ -578,6 +580,7 @@ public class Dependency { mProviders.put(PrivacyDotViewController.class, mPrivacyDotViewControllerLazy::get); mProviders.put(EdgeBackGestureHandler.Factory.class, mEdgeBackGestureHandlerFactoryLazy::get); + mProviders.put(InternetDialogFactory.class, mInternetDialogFactory::get); mProviders.put(UiEventLogger.class, mUiEventLogger::get); mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get); mProviders.put(StatusBarContentInsetsProvider.class, mContentInsetsProviderLazy::get); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java index 41a3fb0211a7..65e93c6f31a3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java @@ -28,6 +28,7 @@ import android.provider.Settings; import android.service.quicksettings.Tile; import android.text.Html; import android.text.TextUtils; +import android.util.FeatureFlagUtils; import android.util.Log; import android.view.View; import android.widget.Switch; @@ -51,6 +52,7 @@ import com.android.systemui.qs.AlphaControlledSignalTileView; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; +import com.android.systemui.qs.tiles.dialog.InternetDialogFactory; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; @@ -75,6 +77,8 @@ public class InternetTile extends QSTileImpl<SignalState> { private int mLastTileState = -1; protected final InternetSignalCallback mSignalCallback = new InternetSignalCallback(); + private final InternetDialogFactory mInternetDialogFactory; + final Handler mHandler; @Inject public InternetTile( @@ -86,10 +90,13 @@ public class InternetTile extends QSTileImpl<SignalState> { StatusBarStateController statusBarStateController, ActivityStarter activityStarter, QSLogger qsLogger, - NetworkController networkController + NetworkController networkController, + InternetDialogFactory internetDialogFactory ) { super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); + mInternetDialogFactory = internetDialogFactory; + mHandler = mainHandler; mController = networkController; mDataController = mController.getMobileDataController(); mController.observe(getLifecycle(), mSignalCallback); @@ -114,7 +121,13 @@ public class InternetTile extends QSTileImpl<SignalState> { @Override protected void handleClick(@Nullable View view) { - mActivityStarter.postStartActivityDismissingKeyguard(INTERNET_PANEL, 0); + if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL)) { + mActivityStarter.postStartActivityDismissingKeyguard(INTERNET_PANEL, 0); + } else { + mHandler.post(() -> { + mInternetDialogFactory.create(true); + }); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java new file mode 100644 index 000000000000..9ab6d47d6af1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles.dialog; + +import static com.android.wifitrackerlib.WifiEntry.SECURITY_NONE; +import static com.android.wifitrackerlib.WifiEntry.SECURITY_OWE; + +import android.annotation.ColorInt; +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.text.Html; +import android.text.TextUtils; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.settingslib.Utils; +import com.android.systemui.R; +import com.android.wifitrackerlib.WifiEntry; + +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +/** + * Adapter for showing Wi-Fi networks. + */ +public class InternetAdapter extends RecyclerView.Adapter<InternetAdapter.InternetViewHolder> { + + private static final String TAG = "InternetAdapter"; + private static final String ACTION_WIFI_DIALOG = "com.android.settings.WIFI_DIALOG"; + private static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key"; + private static final String EXTRA_CONNECT_FOR_CALLER = "connect_for_caller"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private final InternetDialogController mInternetDialogController; + + protected View mHolderView; + protected Context mContext; + + public InternetAdapter(InternetDialogController controller) { + mInternetDialogController = controller; + } + + @Override + public InternetViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, + int viewType) { + mContext = viewGroup.getContext(); + mHolderView = LayoutInflater.from(mContext).inflate(R.layout.internet_list_item, + viewGroup, false); + return new InternetViewHolder(mHolderView, mInternetDialogController); + } + + @Override + public void onBindViewHolder(@NonNull InternetViewHolder viewHolder, int position) { + List<WifiEntry> wifiList = getWifiEntryList(); + if (wifiList != null && wifiList.size() != 0) { + int count = getItemCount(); + if (wifiList.size() > count) { + wifiList = getWifiEntryList().subList(0, count - 1); + } + + if (position < wifiList.size()) { + viewHolder.onBind(wifiList.get(position)); + } + } else if (DEBUG) { + Log.d(TAG, "onBindViewHolder, Wi-Fi entry list = null"); + } + } + + private List<WifiEntry> getWifiEntryList() { + if (mInternetDialogController.getWifiEntryList() == null) { + return null; + } + + return mInternetDialogController.getWifiEntryList().stream() + .filter(wifiAp -> wifiAp.getConnectedState() + != WifiEntry.CONNECTED_STATE_CONNECTED) + .limit(getItemCount()) + .collect(Collectors.toList()); + } + + /** + * The total number of networks (mobile network and entries of Wi-Fi) should be four in + * {@link InternetDialog}. + * + * Airplane mode is ON (mobile network is gone): + * Return four Wi-Fi's entries if no connected Wi-Fi. + * Return three Wi-Fi's entries if one connected Wi-Fi. + * Airplane mode is OFF (mobile network is visible): + * Return three Wi-Fi's entries if no connected Wi-Fi. + * Return two Wi-Fi's entries if one connected Wi-Fi. + * + * @return The total number of networks. + */ + @Override + public int getItemCount() { + boolean hasConnectedWifi = mInternetDialogController.getConnectedWifiEntry() != null; + if (mInternetDialogController.isAirplaneModeEnabled()) { + return hasConnectedWifi ? 3 : 4; + } else { + return hasConnectedWifi ? 2 : 3; + } + } + + /** + * ViewHolder for binding Wi-Fi view. + */ + static class InternetViewHolder extends RecyclerView.ViewHolder { + + final LinearLayout mContainerLayout; + final LinearLayout mWifiListLayout; + final LinearLayout mWifiNetworkLayout; + final ImageView mWifiIcon; + final TextView mWifiTitleText; + final TextView mWifiSummaryText; + final ImageView mWifiLockedIcon; + final Context mContext; + final InternetDialogController mInternetDialogController; + + InternetViewHolder(View view, InternetDialogController internetDialogController) { + super(view); + mContext = view.getContext(); + mInternetDialogController = internetDialogController; + mContainerLayout = view.requireViewById(R.id.internet_container); + mWifiListLayout = view.requireViewById(R.id.wifi_list); + mWifiNetworkLayout = view.requireViewById(R.id.wifi_network_layout); + mWifiIcon = view.requireViewById(R.id.wifi_icon); + mWifiTitleText = view.requireViewById(R.id.wifi_title); + mWifiSummaryText = view.requireViewById(R.id.wifi_summary); + mWifiLockedIcon = view.requireViewById(R.id.wifi_locked_icon); + } + + void onBind(WifiEntry wifiEntry) { + int security = wifiEntry.getSecurity(); + try { + mWifiIcon.setImageDrawable(getWifiDrawable(wifiEntry)); + if (isOpenNetwork(security)) { + mWifiLockedIcon.setVisibility(View.GONE); + } else { + mWifiLockedIcon.setVisibility(View.VISIBLE); + mWifiLockedIcon.setImageDrawable( + mContext.getDrawable(R.drawable.ic_friction_lock_closed)); + } + } catch (Throwable throwable) { + throwable.printStackTrace(); + } + + setWifiNetworkLayout(wifiEntry.getTitle(), + Html.fromHtml(wifiEntry.getSummary(false), Html.FROM_HTML_MODE_LEGACY)); + + mWifiListLayout.setOnClickListener(v -> { + if (!isOpenNetwork(security)) { + // Popup Wi-Fi password dialog condition: + // 1. The access point is a non-open network. + // 2. The Wi-Fi connection is not connected with this access point. + final Intent intent = new Intent(ACTION_WIFI_DIALOG); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + intent.putExtra(EXTRA_CHOSEN_WIFI_ENTRY_KEY, wifiEntry.getKey()); + intent.putExtra(EXTRA_CONNECT_FOR_CALLER, false); + mContext.startActivity(intent); + } + mInternetDialogController.connect(wifiEntry); + }); + } + + /** Return true if this is an open network AccessPoint. */ + boolean isOpenNetwork(int security) { + return security == SECURITY_NONE + || security == SECURITY_OWE; + } + + void setWifiNetworkLayout(CharSequence title, CharSequence summary) { + mWifiNetworkLayout.setVisibility(View.VISIBLE); + mWifiTitleText.setText(title); + if (TextUtils.isEmpty(summary)) { + mWifiTitleText.setGravity(Gravity.CENTER); + mWifiSummaryText.setVisibility(View.GONE); + return; + } else { + mWifiTitleText.setGravity(Gravity.BOTTOM); + mWifiSummaryText.setGravity(Gravity.TOP); + mWifiSummaryText.setVisibility(View.VISIBLE); + } + mWifiSummaryText.setText(summary); + } + + Drawable getWifiDrawable(WifiEntry wifiEntry) throws Throwable { + Drawable drawable = mContext.getDrawable( + com.android.internal.R.drawable.ic_wifi_signal_0); + + AtomicReference<Drawable> shared = new AtomicReference<>(); + final @ColorInt int tint = Utils.getColorAttrDefaultColor(mContext, + android.R.attr.colorControlNormal); + Drawable signalDrawable = mContext.getDrawable( + Utils.getWifiIconResource(wifiEntry.getLevel())); + signalDrawable.setTint(tint); + shared.set(signalDrawable); + drawable = shared.get(); + return drawable; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java new file mode 100644 index 000000000000..64809f3c9475 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java @@ -0,0 +1,552 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.qs.tiles.dialog; + +import static android.view.WindowInsets.Type.navigationBars; +import static android.view.WindowInsets.Type.statusBars; + +import static com.android.systemui.Prefs.Key.QS_HAS_TURNED_OFF_MOBILE_DATA; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiManager; +import android.os.Bundle; +import android.os.Handler; +import android.telephony.ServiceState; +import android.telephony.SignalStrength; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyDisplayInfo; +import android.telephony.TelephonyManager; +import android.text.Html; +import android.text.TextUtils; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.view.Window; +import android.view.WindowInsets; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.Space; +import android.widget.Switch; +import android.widget.TextView; + +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; +import com.android.settingslib.Utils; +import com.android.systemui.Prefs; +import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.statusbar.phone.SystemUIDialog; +import com.android.wifitrackerlib.WifiEntry; + +import java.util.List; + +import androidx.annotation.VisibleForTesting; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +/** + * Dialog for showing mobile network, connected Wi-Fi network and Wi-Fi networks. + */ +@SysUISingleton +public class InternetDialog extends SystemUIDialog implements + InternetDialogController.InternetDialogCallback, Window.Callback { + private static final String TAG = "InternetDialog"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private final Handler mHandler; + private final LinearLayoutManager mLayoutManager; + private final Runnable mHideProgressBarRunnable = () -> { + setProgressBarVisible(false); + }; + + @VisibleForTesting + protected InternetAdapter mAdapter; + @VisibleForTesting + protected WifiManager mWifiManager; + @VisibleForTesting + protected View mDialogView; + + private InternetDialogFactory mInternetDialogFactory; + private SubscriptionManager mSubscriptionManager; + private TelephonyManager mTelephonyManager; + private AlertDialog mAlertDialog; + private UiEventLogger mUiEventLogger; + private Context mContext; + private InternetDialogController mInternetDialogController; + private TextView mInternetDialogTitle; + private TextView mInternetDialogSubTitle; + private ProgressBar mProgressBar; + private LinearLayout mInternetListLayout; + private LinearLayout mConnectedWifListLayout; + private LinearLayout mConnectedWifList; + private LinearLayout mMobileNetworkLayout; + private LinearLayout mMobileNetworkList; + private LinearLayout mTurnWifiOnLayout; + private LinearLayout mSeeAllLayout; + private Space mSpace; + private RecyclerView mWifiRecyclerView; + private ImageView mConnectedWifiIcon; + private ImageView mWifiSettingsIcon; + private TextView mConnectedWifiTitleText; + private TextView mConnectedWifiSummaryText; + private ImageView mSignalIcon; + private TextView mMobileTitleText; + private TextView mMobileSummaryText; + private Switch mMobileDataToggle; + private Switch mWiFiToggle; + private Button mDoneButton; + private Drawable mBackgroundOn; + private WifiEntry mConnectedWifiEntry; + private int mListMaxHeight; + private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + private boolean mIsProgressBarVisible; + + private final ViewTreeObserver.OnGlobalLayoutListener mInternetListLayoutListener = () -> { + // Set max height for list + if (mInternetListLayout.getHeight() > mListMaxHeight) { + ViewGroup.LayoutParams params = mInternetListLayout.getLayoutParams(); + params.height = mListMaxHeight; + mInternetListLayout.setLayoutParams(params); + } + }; + + public InternetDialog(Context context, InternetDialogFactory internetDialogFactory, + InternetDialogController internetDialogController, + boolean aboveStatusBar, UiEventLogger uiEventLogger, @Main Handler handler) { + super(context, R.style.Theme_SystemUI_Dialog_Internet); + if (DEBUG) { + Log.d(TAG, "Init InternetDialog"); + } + mContext = context; + mHandler = handler; + mInternetDialogFactory = internetDialogFactory; + mInternetDialogController = internetDialogController; + mSubscriptionManager = mInternetDialogController.getSubscriptionManager(); + mDefaultDataSubId = mInternetDialogController.getDefaultDataSubscriptionId(); + mTelephonyManager = mInternetDialogController.getTelephonyManager(); + mWifiManager = mInternetDialogController.getWifiManager(); + + mLayoutManager = new LinearLayoutManager(mContext) { + @Override + public boolean canScrollVertically() { + return false; + } + }; + mListMaxHeight = context.getResources().getDimensionPixelSize( + R.dimen.internet_dialog_list_max_height); + mUiEventLogger = uiEventLogger; + mAdapter = new InternetAdapter(mInternetDialogController); + if (!aboveStatusBar) { + getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); + } + show(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (DEBUG) { + Log.d(TAG, "onCreate"); + } + mUiEventLogger.log(InternetDialogEvent.INTERNET_DIALOG_SHOW); + mDialogView = LayoutInflater.from(mContext).inflate(R.layout.internet_connectivity_dialog, + null); + final Window window = getWindow(); + final WindowManager.LayoutParams lp = window.getAttributes(); + lp.gravity = Gravity.BOTTOM; + lp.setFitInsetsTypes(statusBars() | navigationBars()); + lp.setFitInsetsSides(WindowInsets.Side.all()); + lp.setFitInsetsIgnoringVisibility(true); + window.setAttributes(lp); + window.setContentView(mDialogView); + window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + window.setWindowAnimations(R.style.Animation_InternetDialog); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + + mInternetDialogTitle = mDialogView.requireViewById(R.id.internet_dialog_title); + mInternetDialogSubTitle = mDialogView.requireViewById(R.id.internet_dialog_subtitle); + mProgressBar = mDialogView.requireViewById(R.id.wifi_searching_progress); + mInternetListLayout = mDialogView.requireViewById(R.id.internet_list); + mMobileNetworkLayout = mDialogView.requireViewById(R.id.mobile_network_layout); + mMobileNetworkList = mDialogView.requireViewById(R.id.mobile_network_list); + mTurnWifiOnLayout = mDialogView.requireViewById(R.id.turn_on_wifi_layout); + mConnectedWifListLayout = mDialogView.requireViewById(R.id.wifi_connected_layout); + mConnectedWifList = mDialogView.requireViewById(R.id.wifi_connected_list); + mConnectedWifiIcon = mDialogView.requireViewById(R.id.wifi_connected_icon); + mConnectedWifiTitleText = mDialogView.requireViewById(R.id.wifi_connected_title); + mConnectedWifiSummaryText = mDialogView.requireViewById(R.id.wifi_connected_summary); + mWifiSettingsIcon = mDialogView.requireViewById(R.id.wifi_settings_icon); + mWifiRecyclerView = mDialogView.requireViewById(R.id.wifi_list_layout); + mSeeAllLayout = mDialogView.requireViewById(R.id.see_all_layout); + mSpace = mDialogView.requireViewById(R.id.space); + mDoneButton = mDialogView.requireViewById(R.id.done); + mSignalIcon = mDialogView.requireViewById(R.id.signal_icon); + mMobileTitleText = mDialogView.requireViewById(R.id.mobile_title); + mMobileSummaryText = mDialogView.requireViewById(R.id.mobile_summary); + mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_toggle); + mWiFiToggle = mDialogView.requireViewById(R.id.wifi_toggle); + mBackgroundOn = mContext.getDrawable(R.drawable.settingslib_switch_bar_bg_on); + mInternetListLayout.getViewTreeObserver().addOnGlobalLayoutListener( + mInternetListLayoutListener); + mInternetDialogTitle.setText(getDialogTitleText()); + mInternetDialogTitle.setGravity(Gravity.START | Gravity.CENTER_VERTICAL); + + setOnClickListener(); + mTurnWifiOnLayout.setBackground(null); + mWifiRecyclerView.setLayoutManager(mLayoutManager); + mWifiRecyclerView.setAdapter(mAdapter); + } + + @Override + public void onStart() { + super.onStart(); + if (DEBUG) { + Log.d(TAG, "onStart"); + } + mInternetDialogController.onStart(this); + } + + @Override + public void onStop() { + super.onStop(); + if (DEBUG) { + Log.d(TAG, "onStop"); + } + mHandler.removeCallbacks(mHideProgressBarRunnable); + mMobileNetworkLayout.setOnClickListener(null); + mMobileDataToggle.setOnCheckedChangeListener(null); + mConnectedWifListLayout.setOnClickListener(null); + mSeeAllLayout.setOnClickListener(null); + mWiFiToggle.setOnCheckedChangeListener(null); + mDoneButton.setOnClickListener(null); + mInternetDialogController.onStop(); + mInternetDialogFactory.destroyDialog(); + } + + @Override + public void dismissDialog() { + if (DEBUG) { + Log.d(TAG, "dismissDialog"); + } + mInternetDialogFactory.destroyDialog(); + dismiss(); + } + + void updateDialog() { + if (DEBUG) { + Log.d(TAG, "updateDialog"); + } + if (mInternetDialogController.isAirplaneModeEnabled()) { + mInternetDialogSubTitle.setVisibility(View.GONE); + } else { + mInternetDialogSubTitle.setText(getSubtitleText()); + } + showProgressBar(); + setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular()); + setConnectedWifiLayout(); + boolean isWifiEnabled = mWifiManager.isWifiEnabled(); + mWiFiToggle.setChecked(isWifiEnabled); + int visible = isWifiEnabled ? View.VISIBLE : View.GONE; + mWifiRecyclerView.setVisibility(visible); + mAdapter.notifyDataSetChanged(); + mSeeAllLayout.setVisibility(visible); + mSpace.setVisibility(isWifiEnabled ? View.GONE : View.VISIBLE); + } + + private void setOnClickListener() { + mMobileNetworkLayout.setOnClickListener(v -> { + if (mInternetDialogController.isMobileDataEnabled()) { + if (!mInternetDialogController.activeNetworkIsCellular()) { + mInternetDialogController.connectCarrierNetwork(); + } + } + }); + mMobileDataToggle.setOnCheckedChangeListener( + (buttonView, isChecked) -> { + if (!isChecked && shouldShowMobileDialog()) { + showTurnOffMobileDialog(); + } else if (!shouldShowMobileDialog()) { + mInternetDialogController.setMobileDataEnabled(mContext, mDefaultDataSubId, + isChecked, false); + } + }); + mConnectedWifListLayout.setOnClickListener(v -> { + // TODO(b/191475923): Need to launch the detailed page of Wi-Fi entry. + }); + mSeeAllLayout.setOnClickListener(v -> onClickSeeMoreButton()); + mWiFiToggle.setOnCheckedChangeListener( + (buttonView, isChecked) -> { + buttonView.setChecked(isChecked); + mWifiManager.setWifiEnabled(isChecked); + mSpace.setVisibility(isChecked ? View.GONE : View.VISIBLE); + }); + mDoneButton.setOnClickListener(v -> dismiss()); + } + + private void setMobileDataLayout(boolean isCellularNetwork) { + if (mInternetDialogController.isAirplaneModeEnabled() + || !mInternetDialogController.hasCarrier()) { + mMobileNetworkLayout.setVisibility(View.GONE); + } else { + mMobileDataToggle.setChecked(mInternetDialogController.isMobileDataEnabled()); + mMobileNetworkLayout.setVisibility(View.VISIBLE); + mMobileTitleText.setText(getMobileNetworkTitle()); + mMobileSummaryText.setText( + Html.fromHtml(getMobileNetworkSummary(), Html.FROM_HTML_MODE_LEGACY)); + mSignalIcon.setImageDrawable(getSignalStrengthDrawable()); + int titleColor = isCellularNetwork ? mContext.getColor( + R.color.connected_network_primary_color) : Utils.getColorAttrDefaultColor( + mContext, android.R.attr.textColorPrimary); + int summaryColor = isCellularNetwork ? mContext.getColor( + R.color.connected_network_tertiary_color) : Utils.getColorAttrDefaultColor( + mContext, android.R.attr.textColorTertiary); + mMobileTitleText.setTextColor(titleColor); + mMobileSummaryText.setTextColor(summaryColor); + mMobileNetworkLayout.setBackground(isCellularNetwork ? mBackgroundOn : null); + } + } + + private void setConnectedWifiLayout() { + if (!mWifiManager.isWifiEnabled() + || mInternetDialogController.getConnectedWifiEntry() == null) { + mConnectedWifListLayout.setBackground(null); + mConnectedWifListLayout.setVisibility(View.GONE); + return; + } + mConnectedWifListLayout.setVisibility(View.VISIBLE); + mConnectedWifiTitleText.setText(getConnectedWifiTitle()); + mConnectedWifiSummaryText.setText(getConnectedWifiSummary()); + mConnectedWifiIcon.setImageDrawable(getConnectedWifiDrawable()); + mConnectedWifiTitleText.setTextColor( + mContext.getColor(R.color.connected_network_primary_color)); + mConnectedWifiSummaryText.setTextColor( + mContext.getColor(R.color.connected_network_tertiary_color)); + mWifiSettingsIcon.setColorFilter( + mContext.getColor(R.color.connected_network_primary_color)); + mConnectedWifListLayout.setBackground(mBackgroundOn); + } + + void onClickSeeMoreButton() { + mInternetDialogController.launchNetworkSetting(); + } + + CharSequence getDialogTitleText() { + return mInternetDialogController.getDialogTitleText(); + } + + CharSequence getSubtitleText() { + return mInternetDialogController.getSubtitleText(mIsProgressBarVisible); + } + + private Drawable getConnectedWifiDrawable() { + try { + return mInternetDialogController.getWifiConnectedDrawable(mConnectedWifiEntry); + } catch (Throwable e) { + e.printStackTrace(); + } + return null; + } + + private Drawable getSignalStrengthDrawable() { + return mInternetDialogController.getSignalStrengthDrawable(); + } + + CharSequence getMobileNetworkTitle() { + return mInternetDialogController.getMobileNetworkTitle(); + } + + String getMobileNetworkSummary() { + return mInternetDialogController.getMobileNetworkSummary(); + } + + String getConnectedWifiTitle() { + return mInternetDialogController.getConnectedWifiTitle(); + } + + String getConnectedWifiSummary() { + return mInternetDialogController.getConnectedWifiSummary(); + } + + private void showProgressBar() { + if (mWifiManager == null || !mWifiManager.isWifiEnabled()) { + setProgressBarVisible(false); + return; + } + setProgressBarVisible(true); + List<ScanResult> wifiScanResults = mWifiManager.getScanResults(); + if (wifiScanResults != null && wifiScanResults.size() > 0) { + mContext.getMainThreadHandler().postDelayed(mHideProgressBarRunnable, + 2000 /* delay millis */); + } + } + + private void setProgressBarVisible(boolean visible) { + if (mWifiManager.isWifiEnabled() && mAdapter.mHolderView != null + && mAdapter.mHolderView.isAttachedToWindow()) { + mIsProgressBarVisible = true; + } + mIsProgressBarVisible = visible; + mProgressBar.setVisibility(mIsProgressBarVisible ? View.VISIBLE : View.INVISIBLE); + mInternetDialogSubTitle.setText(getSubtitleText()); + } + + private boolean shouldShowMobileDialog() { + boolean flag = Prefs.getBoolean(mContext, QS_HAS_TURNED_OFF_MOBILE_DATA, + false); + if (mInternetDialogController.isMobileDataEnabled() && !flag) { + return true; + } + return false; + } + + private void showTurnOffMobileDialog() { + CharSequence carrierName = + mSubscriptionManager.getDefaultDataSubscriptionInfo().getCarrierName(); + boolean isInService = mInternetDialogController.isVoiceStateInService(); + if (TextUtils.isEmpty(carrierName) || !isInService) { + carrierName = mContext.getString(R.string.mobile_data_disable_message_default_carrier); + } + mAlertDialog = new Builder(mContext) + .setTitle(R.string.mobile_data_disable_title) + .setMessage(mContext.getString(R.string.mobile_data_disable_message, carrierName)) + .setNegativeButton(android.R.string.cancel, (d, w) -> { + mMobileDataToggle.setChecked(true); + }) + .setPositiveButton( + com.android.internal.R.string.alert_windows_notification_turn_off_action, + (d, w) -> { + mInternetDialogController.setMobileDataEnabled(mContext, + mDefaultDataSubId, false, false); + mMobileDataToggle.setChecked(false); + Prefs.putBoolean(mContext, QS_HAS_TURNED_OFF_MOBILE_DATA, true); + }) + .create(); + mAlertDialog.setOnCancelListener(dialog -> mMobileDataToggle.setChecked(true)); + mAlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + SystemUIDialog.setShowForAllUsers(mAlertDialog, true); + SystemUIDialog.registerDismissListener(mAlertDialog); + SystemUIDialog.setWindowOnTop(mAlertDialog); + mAlertDialog.show(); + } + + @Override + public void onRefreshCarrierInfo() { + mHandler.post(() -> updateDialog()); + } + + @Override + public void onSimStateChanged() { + mHandler.post(() -> updateDialog()); + } + + @Override + public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { + mHandler.post(() -> updateDialog()); + } + + @Override + public void onSubscriptionsChanged(int defaultDataSubId) { + mDefaultDataSubId = defaultDataSubId; + mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId); + mHandler.post(() -> updateDialog()); + } + + @Override + public void onServiceStateChanged(ServiceState serviceState) { + mHandler.post(() -> updateDialog()); + } + + @Override + public void onDataConnectionStateChanged(int state, int networkType) { + mAdapter.notifyDataSetChanged(); + mHandler.post(() -> updateDialog()); + } + + @Override + public void onSignalStrengthsChanged(SignalStrength signalStrength) { + mHandler.post(() -> updateDialog()); + } + + @Override + public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) { + mHandler.post(() -> updateDialog()); + } + + @Override + public void onAccessPointsChanged(List<WifiEntry> wifiEntryList, WifiEntry connectedEntry) { + mConnectedWifiEntry = connectedEntry; + mAdapter.notifyDataSetChanged(); + mHandler.post(() -> updateDialog()); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if (mAlertDialog != null && !mAlertDialog.isShowing()) { + if (!hasFocus && isShowing()) { + dismiss(); + } + } + } + + @Override + public void onWifiStateReceived(Context context, Intent intent) { + if (intent == null) { + return; + } + + String action = intent.getAction(); + if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { + mInternetDialogController.scanWifiAccessPoints(); + showProgressBar(); + return; + } + + if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { + mHandler.post(() -> updateDialog()); + } + } + + public enum InternetDialogEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "The Internet dialog became visible on the screen.") + INTERNET_DIALOG_SHOW(843); + + private final int mId; + + InternetDialogEvent(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt new file mode 100644 index 000000000000..d68ad4ba48e3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.qs.tiles.dialog + +import android.content.Context +import android.os.Handler +import android.util.Log +import com.android.internal.logging.UiEventLogger +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Main +import javax.inject.Inject + +private const val TAG = "InternetDialogFactory" +private val DEBUG = Log.isLoggable(TAG, Log.DEBUG) + +/** + * Factory to create [InternetDialog] objects. + */ +@SysUISingleton +class InternetDialogFactory @Inject constructor( + @Main private val handler: Handler, + private val internetDialogController: InternetDialogController, + private val context: Context, + private val uiEventLogger: UiEventLogger +) { + companion object { + var internetDialog: InternetDialog? = null + } + + /** Creates a [InternetDialog]. */ + fun create(aboveStatusBar: Boolean) { + if (internetDialog != null) { + if (DEBUG) { + Log.d(TAG, "InternetDialog is showing, do not create it twice.") + } + return + } else { + internetDialog = InternetDialog(context, this, internetDialogController, aboveStatusBar, + uiEventLogger, handler) + } + } + + fun destroyDialog() { + if (DEBUG) { + Log.d(TAG, "destroyDialog") + } + internetDialog = null + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index c49de7ab0e5d..075fa174067c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -68,9 +68,12 @@ import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.demomode.DemoMode; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; +import com.android.systemui.qs.tiles.dialog.InternetDialogFactory; +import com.android.systemui.qs.tiles.dialog.InternetDialogUtil; import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; @@ -191,6 +194,8 @@ public class NetworkControllerImpl extends BroadcastReceiver private boolean mUserSetup; private boolean mSimDetected; private boolean mForceCellularValidated; + private InternetDialogFactory mInternetDialogFactory; + private Handler mMainHandler; private ConfigurationController.ConfigurationListener mConfigurationListener = new ConfigurationController.ConfigurationListener() { @@ -221,7 +226,9 @@ public class NetworkControllerImpl extends BroadcastReceiver DemoModeController demoModeController, CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags, - DumpManager dumpManager) { + DumpManager dumpManager, + @Main Handler handler, + InternetDialogFactory internetDialogFactory) { this(context, connectivityManager, telephonyManager, telephonyListenerManager, @@ -242,6 +249,8 @@ public class NetworkControllerImpl extends BroadcastReceiver featureFlags, dumpManager); mReceiverHandler.post(mRegisterListeners); + mMainHandler = handler; + mInternetDialogFactory = internetDialogFactory; } @VisibleForTesting @@ -480,6 +489,9 @@ public class NetworkControllerImpl extends BroadcastReceiver filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); + if (InternetDialogUtil.isProviderModelEnabled(mContext)) { + filter.addAction(Settings.Panel.ACTION_INTERNET_CONNECTIVITY); + } mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler); mListening = true; @@ -788,6 +800,9 @@ public class NetworkControllerImpl extends BroadcastReceiver mConfig = Config.readConfig(mContext); mReceiverHandler.post(this::handleConfigurationChanged); break; + case Settings.Panel.ACTION_INTERNET_CONNECTIVITY: + mMainHandler.post(() -> mInternetDialogFactory.create(true)); + break; default: int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, SubscriptionManager.INVALID_SUBSCRIPTION_ID); |