ParanoidSystemUI: Restore Wifi and Cellular tiles

- taken from f64485029f

Change-Id: I80820b233adcb7ad1961272ad3c8d4c3dcaf387c
Signed-off-by: Omkar Chandorkar <gotenksIN@aospa.co>
This commit is contained in:
Omkar Chandorkar 2023-06-18 17:33:42 +05:30
parent e7404f9b96
commit 10ac660448
No known key found for this signature in database
3 changed files with 601 additions and 0 deletions

View File

@ -21,10 +21,12 @@ import com.android.systemui.qs.tileimpl.QSTileImpl
import co.aospa.systemui.qs.tiles.AlwaysOnDisplayTile; import co.aospa.systemui.qs.tiles.AlwaysOnDisplayTile;
import co.aospa.systemui.qs.tiles.BluetoothDialogTile; import co.aospa.systemui.qs.tiles.BluetoothDialogTile;
import co.aospa.systemui.qs.tiles.CaffeineTile; import co.aospa.systemui.qs.tiles.CaffeineTile;
import co.aospa.systemui.qs.tiles.CellularTile
import co.aospa.systemui.qs.tiles.DataSwitchTile; import co.aospa.systemui.qs.tiles.DataSwitchTile;
import co.aospa.systemui.qs.tiles.DcDimmingTile; import co.aospa.systemui.qs.tiles.DcDimmingTile;
import co.aospa.systemui.qs.tiles.HeadsUpTile; import co.aospa.systemui.qs.tiles.HeadsUpTile;
import co.aospa.systemui.qs.tiles.PowerShareTile; import co.aospa.systemui.qs.tiles.PowerShareTile;
import co.aospa.systemui.qs.tiles.WifiTile
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap
@ -51,6 +53,12 @@ interface ParanoidQSModule {
@StringKey(CaffeineTile.TILE_SPEC) @StringKey(CaffeineTile.TILE_SPEC)
fun bindCaffeineTile(caffeineTile: CaffeineTile): QSTileImpl<*> fun bindCaffeineTile(caffeineTile: CaffeineTile): QSTileImpl<*>
/** Inject CellularTile into tileMap in QSModule */
@Binds
@IntoMap
@StringKey(CellularTile.TILE_SPEC)
fun bindCellularTile(cellularTile: CellularTile): QSTileImpl<*>
/** Inject DataSwitchTile into tileMap in QSModule */ /** Inject DataSwitchTile into tileMap in QSModule */
@Binds @Binds
@IntoMap @IntoMap
@ -75,4 +83,10 @@ interface ParanoidQSModule {
@StringKey(PowerShareTile.TILE_SPEC) @StringKey(PowerShareTile.TILE_SPEC)
fun bindPowerShareTile(powerShareTile: PowerShareTile): QSTileImpl<*> fun bindPowerShareTile(powerShareTile: PowerShareTile): QSTileImpl<*>
/** Inject WifiTile into tileMap in QSModule */
@Binds
@IntoMap
@StringKey(WifiTile.TILE_SPEC)
fun bindWifiTile(wifiTile: WifiTile): QSTileImpl<*>
} }

View File

@ -0,0 +1,301 @@
/*
* Copyright (C) 2014 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 co.aospa.systemui.qs.tiles;
import static com.android.systemui.Prefs.Key.QS_HAS_TURNED_OFF_MOBILE_DATA;
import android.annotation.NonNull;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.telephony.SubscriptionManager;
import android.text.Html;
import android.text.TextUtils;
import android.view.View;
import android.view.WindowManager.LayoutParams;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile.SignalState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.SignalTileView;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.connectivity.IconState;
import com.android.systemui.statusbar.connectivity.MobileDataIndicators;
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.SignalCallback;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import javax.inject.Inject;
/** Quick settings tile: Cellular **/
public class CellularTile extends QSTileImpl<SignalState> {
private static final String ENABLE_SETTINGS_DATA_PLAN = "enable.settings.data.plan";
private final NetworkController mController;
private final DataUsageController mDataController;
private final KeyguardStateController mKeyguard;
private final CellSignalCallback mSignalCallback = new CellSignalCallback();
@Inject
public CellularTile(
QSHost host,
@Background Looper backgroundLooper,
@Main Handler mainHandler,
FalsingManager falsingManager,
MetricsLogger metricsLogger,
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
QSLogger qsLogger,
NetworkController networkController,
KeyguardStateController keyguardStateController
) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
mController = networkController;
mKeyguard = keyguardStateController;
mDataController = mController.getMobileDataController();
mController.observe(getLifecycle(), mSignalCallback);
}
@Override
public SignalState newTileState() {
return new SignalState();
}
@Override
public QSIconView createTileView(Context context) {
return new SignalTileView(context);
}
@Override
public Intent getLongClickIntent() {
if (getState().state == Tile.STATE_UNAVAILABLE) {
return new Intent(Settings.ACTION_WIRELESS_SETTINGS);
}
return getCellularSettingIntent();
}
@Override
protected void handleClick(@Nullable View view) {
if (getState().state == Tile.STATE_UNAVAILABLE) {
return;
}
if (mDataController.isMobileDataEnabled()) {
maybeShowDisableDialog();
} else {
mDataController.setMobileDataEnabled(true);
}
}
private void maybeShowDisableDialog() {
if (Prefs.getBoolean(mContext, QS_HAS_TURNED_OFF_MOBILE_DATA, false)) {
// Directly turn off mobile data if the user has seen the dialog before.
mDataController.setMobileDataEnabled(false);
return;
}
String carrierName = mController.getMobileDataNetworkName();
boolean isInService = mController.isMobileDataNetworkInService();
if (TextUtils.isEmpty(carrierName) || !isInService) {
carrierName = mContext.getString(R.string.mobile_data_disable_message_default_carrier);
}
AlertDialog dialog = 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, null)
.setPositiveButton(
com.android.internal.R.string.alert_windows_notification_turn_off_action,
(d, w) -> {
mDataController.setMobileDataEnabled(false);
Prefs.putBoolean(mContext, QS_HAS_TURNED_OFF_MOBILE_DATA, true);
})
.create();
dialog.getWindow().setType(LayoutParams.TYPE_KEYGUARD_DIALOG);
SystemUIDialog.setShowForAllUsers(dialog, true);
SystemUIDialog.registerDismissListener(dialog);
SystemUIDialog.setWindowOnTop(dialog, mKeyguard.isShowing());
dialog.show();
}
@Override
protected void handleSecondaryClick(@Nullable View view) {
handleLongClick(view);
}
@Override
public CharSequence getTileLabel() {
return mContext.getString(R.string.quick_settings_cellular_detail_title);
}
@Override
protected void handleUpdateState(SignalState state, Object arg) {
CallbackInfo cb = (CallbackInfo) arg;
if (cb == null) {
cb = mSignalCallback.mInfo;
}
final Resources r = mContext.getResources();
state.label = r.getString(R.string.mobile_data);
boolean mobileDataEnabled = mDataController.isMobileDataSupported()
&& mDataController.isMobileDataEnabled();
state.value = mobileDataEnabled;
state.activityIn = mobileDataEnabled && cb.activityIn;
state.activityOut = mobileDataEnabled && cb.activityOut;
state.expandedAccessibilityClassName = Switch.class.getName();
if (cb.noSim) {
state.icon = ResourceIcon.get(R.drawable.ic_qs_no_sim);
} else {
state.icon = ResourceIcon.get(R.drawable.ic_swap_vert);
}
if (cb.noSim) {
state.state = Tile.STATE_UNAVAILABLE;
state.secondaryLabel = r.getString(R.string.keyguard_missing_sim_message_short);
} else if (cb.airplaneModeEnabled) {
state.state = Tile.STATE_UNAVAILABLE;
state.secondaryLabel = r.getString(R.string.status_bar_airplane);
} else if (mobileDataEnabled) {
state.state = Tile.STATE_ACTIVE;
state.secondaryLabel = appendMobileDataType(
// Only show carrier name if there are more than 1 subscription
cb.multipleSubs ? cb.dataSubscriptionName : "",
getMobileDataContentName(cb));
} else {
state.state = Tile.STATE_INACTIVE;
state.secondaryLabel = r.getString(R.string.cell_data_off);
}
state.contentDescription = state.label;
if (state.state == Tile.STATE_INACTIVE) {
// This information is appended later by converting the Tile.STATE_INACTIVE state.
state.stateDescription = "";
} else {
state.stateDescription = state.secondaryLabel;
}
}
private CharSequence appendMobileDataType(CharSequence current, CharSequence dataType) {
if (TextUtils.isEmpty(dataType)) {
return Html.fromHtml(current.toString(), 0);
}
if (TextUtils.isEmpty(current)) {
return Html.fromHtml(dataType.toString(), 0);
}
String concat = mContext.getString(R.string.mobile_carrier_text_format, current, dataType);
return Html.fromHtml(concat, 0);
}
private CharSequence getMobileDataContentName(CallbackInfo cb) {
if (cb.roaming && !TextUtils.isEmpty(cb.dataContentDescription)) {
String roaming = mContext.getString(R.string.data_connection_roaming);
String dataDescription = cb.dataContentDescription.toString();
return mContext.getString(R.string.mobile_data_text_format, roaming, dataDescription);
}
if (cb.roaming) {
return mContext.getString(R.string.data_connection_roaming);
}
return cb.dataContentDescription;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.QS_CELLULAR;
}
@Override
public boolean isAvailable() {
return mController.hasMobileDataFeature()
&& mHost.getUserContext().getUserId() == UserHandle.USER_SYSTEM;
}
private static final class CallbackInfo {
boolean airplaneModeEnabled;
@Nullable
CharSequence dataSubscriptionName;
@Nullable
CharSequence dataContentDescription;
boolean activityIn;
boolean activityOut;
boolean noSim;
boolean roaming;
boolean multipleSubs;
}
private final class CellSignalCallback implements SignalCallback {
private final CallbackInfo mInfo = new CallbackInfo();
@Override
public void setMobileDataIndicators(@NonNull MobileDataIndicators indicators) {
if (indicators.qsIcon == null) {
// Not data sim, don't display.
return;
}
mInfo.dataSubscriptionName = mController.getMobileDataNetworkName();
mInfo.dataContentDescription = indicators.qsDescription != null
? indicators.typeContentDescriptionHtml : null;
mInfo.activityIn = indicators.activityIn;
mInfo.activityOut = indicators.activityOut;
mInfo.roaming = indicators.roaming;
mInfo.multipleSubs = mController.getNumberSubscriptions() > 1;
refreshState(mInfo);
}
@Override
public void setNoSims(boolean show, boolean simDetected) {
mInfo.noSim = show;
refreshState(mInfo);
}
@Override
public void setIsAirplaneMode(@NonNull IconState icon) {
mInfo.airplaneModeEnabled = icon.visible;
refreshState(mInfo);
}
}
static Intent getCellularSettingIntent() {
Intent intent = new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS);
int dataSub = SubscriptionManager.getDefaultDataSubscriptionId();
if (dataSub != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
intent.putExtra(Settings.EXTRA_SUB_ID,
SubscriptionManager.getDefaultDataSubscriptionId());
}
return intent;
}
}

View File

@ -0,0 +1,286 @@
/*
* Copyright (C) 2014 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 co.aospa.systemui.qs.tiles;
import android.annotation.NonNull;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.SignalState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
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.QSIconViewImpl;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.connectivity.AccessPointController;
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.SignalCallback;
import com.android.systemui.statusbar.connectivity.WifiIcons;
import com.android.systemui.statusbar.connectivity.WifiIndicators;
import javax.inject.Inject;
/** Quick settings tile: Wifi **/
public class WifiTile extends QSTileImpl<SignalState> {
private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
protected final NetworkController mController;
private final AccessPointController mWifiController;
private final QSTile.SignalState mStateBeforeClick = newTileState();
protected final WifiSignalCallback mSignalCallback = new WifiSignalCallback();
private boolean mExpectDisabled;
@Inject
public WifiTile(
QSHost host,
@Background Looper backgroundLooper,
@Main Handler mainHandler,
FalsingManager falsingManager,
MetricsLogger metricsLogger,
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
QSLogger qsLogger,
NetworkController networkController,
AccessPointController accessPointController
) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
mController = networkController;
mWifiController = accessPointController;
mController.observe(getLifecycle(), mSignalCallback);
mStateBeforeClick.spec = "wifi";
}
@Override
public SignalState newTileState() {
return new SignalState();
}
@Override
public QSIconView createTileView(Context context) {
return new AlphaControlledSignalTileView(context);
}
@Override
public Intent getLongClickIntent() {
return WIFI_SETTINGS;
}
@Override
protected void handleClick(@Nullable View view) {
// Secondary clicks are header clicks, just toggle.
mState.copyTo(mStateBeforeClick);
boolean wifiEnabled = mState.value;
// Immediately enter transient state when turning on wifi.
refreshState(wifiEnabled ? null : ARG_SHOW_TRANSIENT_ENABLING);
mController.setWifiEnabled(!wifiEnabled);
mExpectDisabled = wifiEnabled;
if (mExpectDisabled) {
mHandler.postDelayed(() -> {
if (mExpectDisabled) {
mExpectDisabled = false;
refreshState();
}
}, QSIconViewImpl.QS_ANIM_LENGTH);
}
}
@Override
protected void handleSecondaryClick(@Nullable View view) {
if (!mWifiController.canConfigWifi()) {
mActivityStarter.postStartActivityDismissingKeyguard(
new Intent(Settings.ACTION_WIFI_SETTINGS), 0);
return;
}
if (!mState.value) {
mController.setWifiEnabled(true);
}
}
@Override
public CharSequence getTileLabel() {
return mContext.getString(R.string.quick_settings_wifi_label);
}
@Override
protected void handleUpdateState(SignalState state, Object arg) {
if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg);
final CallbackInfo cb = mSignalCallback.mInfo;
if (mExpectDisabled) {
if (cb.enabled) {
return; // Ignore updates until disabled event occurs.
} else {
mExpectDisabled = false;
}
}
boolean transientEnabling = arg == ARG_SHOW_TRANSIENT_ENABLING;
boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0)
&& (cb.ssid != null || cb.wifiSignalIconId != WifiIcons.QS_WIFI_NO_NETWORK);
boolean wifiNotConnected = (cb.ssid == null)
&& (cb.wifiSignalIconId == WifiIcons.QS_WIFI_NO_NETWORK);
if (state.slash == null) {
state.slash = new SlashState();
state.slash.rotation = 6;
}
state.slash.isSlashed = false;
boolean isTransient = transientEnabling || cb.isTransient;
state.secondaryLabel = getSecondaryLabel(isTransient, cb.statusLabel);
state.state = Tile.STATE_ACTIVE;
state.dualTarget = true;
state.value = transientEnabling || cb.enabled;
state.activityIn = cb.enabled && cb.activityIn;
state.activityOut = cb.enabled && cb.activityOut;
final StringBuffer minimalContentDescription = new StringBuffer();
final StringBuffer minimalStateDescription = new StringBuffer();
final Resources r = mContext.getResources();
if (isTransient) {
state.icon = ResourceIcon.get(
com.android.internal.R.drawable.ic_signal_wifi_transient_animation);
state.label = r.getString(R.string.quick_settings_wifi_label);
} else if (!state.value) {
state.slash.isSlashed = true;
state.state = Tile.STATE_INACTIVE;
state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_DISABLED);
state.label = r.getString(R.string.quick_settings_wifi_label);
} else if (wifiConnected) {
state.icon = ResourceIcon.get(cb.wifiSignalIconId);
state.label = cb.ssid != null ? removeDoubleQuotes(cb.ssid) : getTileLabel();
} else if (wifiNotConnected) {
state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_NO_NETWORK);
state.label = r.getString(R.string.quick_settings_wifi_label);
} else {
state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_NO_NETWORK);
state.label = r.getString(R.string.quick_settings_wifi_label);
}
minimalContentDescription.append(
mContext.getString(R.string.quick_settings_wifi_label)).append(",");
if (state.value) {
if (wifiConnected) {
minimalStateDescription.append(cb.wifiSignalContentDescription);
minimalContentDescription.append(removeDoubleQuotes(cb.ssid));
if (!TextUtils.isEmpty(state.secondaryLabel)) {
minimalContentDescription.append(",").append(state.secondaryLabel);
}
}
}
state.stateDescription = minimalStateDescription.toString();
state.contentDescription = minimalContentDescription.toString();
state.dualLabelContentDescription = r.getString(
R.string.accessibility_quick_settings_open_settings, getTileLabel());
state.expandedAccessibilityClassName = Switch.class.getName();
}
private CharSequence getSecondaryLabel(boolean isTransient, String statusLabel) {
return isTransient
? mContext.getString(R.string.quick_settings_wifi_secondary_label_transient)
: statusLabel;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.QS_WIFI;
}
@Override
public boolean isAvailable() {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
}
@Nullable
private static String removeDoubleQuotes(String string) {
if (string == null) return null;
final int length = string.length();
if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
return string.substring(1, length - 1);
}
return string;
}
protected static final class CallbackInfo {
boolean enabled;
boolean connected;
int wifiSignalIconId;
@Nullable
String ssid;
boolean activityIn;
boolean activityOut;
@Nullable
String wifiSignalContentDescription;
boolean isTransient;
@Nullable
public String statusLabel;
@Override
public String toString() {
return new StringBuilder("CallbackInfo[")
.append("enabled=").append(enabled)
.append(",connected=").append(connected)
.append(",wifiSignalIconId=").append(wifiSignalIconId)
.append(",ssid=").append(ssid)
.append(",activityIn=").append(activityIn)
.append(",activityOut=").append(activityOut)
.append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
.append(",isTransient=").append(isTransient)
.append(']').toString();
}
}
protected final class WifiSignalCallback implements SignalCallback {
final CallbackInfo mInfo = new CallbackInfo();
@Override
public void setWifiIndicators(@NonNull WifiIndicators indicators) {
if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + indicators.enabled);
if (indicators.qsIcon == null) {
return;
}
mInfo.enabled = indicators.enabled;
mInfo.connected = indicators.qsIcon.visible;
mInfo.wifiSignalIconId = indicators.qsIcon.icon;
mInfo.ssid = indicators.description;
mInfo.activityIn = indicators.activityIn;
mInfo.activityOut = indicators.activityOut;
mInfo.wifiSignalContentDescription = indicators.qsIcon.contentDescription;
mInfo.isTransient = indicators.isTransient;
mInfo.statusLabel = indicators.statusLabel;
refreshState();
}
}
}