1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.qs.tiles; 16 17 import android.content.Intent; 18 import android.os.Handler; 19 import android.os.Looper; 20 import android.provider.Settings; 21 import android.service.quicksettings.Tile; 22 import android.view.View; 23 import android.widget.Switch; 24 25 import androidx.annotation.Nullable; 26 27 import com.android.internal.jank.InteractionJankMonitor; 28 import com.android.internal.logging.MetricsLogger; 29 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 30 import com.android.systemui.Prefs; 31 import com.android.systemui.R; 32 import com.android.systemui.animation.DialogCuj; 33 import com.android.systemui.animation.DialogLaunchAnimator; 34 import com.android.systemui.dagger.qualifiers.Background; 35 import com.android.systemui.dagger.qualifiers.Main; 36 import com.android.systemui.plugins.ActivityStarter; 37 import com.android.systemui.plugins.FalsingManager; 38 import com.android.systemui.plugins.qs.QSTile.BooleanState; 39 import com.android.systemui.plugins.statusbar.StatusBarStateController; 40 import com.android.systemui.qs.QSHost; 41 import com.android.systemui.qs.QsEventLogger; 42 import com.android.systemui.qs.logging.QSLogger; 43 import com.android.systemui.qs.tileimpl.QSTileImpl; 44 import com.android.systemui.statusbar.phone.SystemUIDialog; 45 import com.android.systemui.statusbar.policy.DataSaverController; 46 47 import javax.inject.Inject; 48 49 public class DataSaverTile extends QSTileImpl<BooleanState> implements 50 DataSaverController.Listener{ 51 52 public static final String TILE_SPEC = "saver"; 53 54 private static final String INTERACTION_JANK_TAG = "start_data_saver"; 55 56 private final DataSaverController mDataSaverController; 57 private final DialogLaunchAnimator mDialogLaunchAnimator; 58 59 @Inject DataSaverTile( QSHost host, QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, MetricsLogger metricsLogger, StatusBarStateController statusBarStateController, ActivityStarter activityStarter, QSLogger qsLogger, DataSaverController dataSaverController, DialogLaunchAnimator dialogLaunchAnimator )60 public DataSaverTile( 61 QSHost host, 62 QsEventLogger uiEventLogger, 63 @Background Looper backgroundLooper, 64 @Main Handler mainHandler, 65 FalsingManager falsingManager, 66 MetricsLogger metricsLogger, 67 StatusBarStateController statusBarStateController, 68 ActivityStarter activityStarter, 69 QSLogger qsLogger, 70 DataSaverController dataSaverController, 71 DialogLaunchAnimator dialogLaunchAnimator 72 ) { 73 super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, 74 statusBarStateController, activityStarter, qsLogger); 75 mDataSaverController = dataSaverController; 76 mDialogLaunchAnimator = dialogLaunchAnimator; 77 mDataSaverController.observe(getLifecycle(), this); 78 } 79 80 @Override newTileState()81 public BooleanState newTileState() { 82 return new BooleanState(); 83 } 84 85 @Override getLongClickIntent()86 public Intent getLongClickIntent() { 87 return new Intent(Settings.ACTION_DATA_SAVER_SETTINGS); 88 } 89 @Override handleClick(@ullable View view)90 protected void handleClick(@Nullable View view) { 91 if (mState.value 92 || Prefs.getBoolean(mContext, Prefs.Key.QS_DATA_SAVER_DIALOG_SHOWN, false)) { 93 // Do it right away. 94 toggleDataSaver(); 95 return; 96 } 97 98 // Show a dialog to confirm first. Dialogs shown by the DialogLaunchAnimator must be created 99 // and shown on the main thread, so we post it to the UI handler. 100 mUiHandler.post(() -> { 101 SystemUIDialog dialog = new SystemUIDialog(mContext); 102 dialog.setTitle(com.android.internal.R.string.data_saver_enable_title); 103 dialog.setMessage(com.android.internal.R.string.data_saver_description); 104 dialog.setPositiveButton(com.android.internal.R.string.data_saver_enable_button, 105 (dialogInterface, which) -> { 106 toggleDataSaver(); 107 Prefs.putBoolean(mContext, Prefs.Key.QS_DATA_SAVER_DIALOG_SHOWN, true); 108 }); 109 dialog.setNeutralButton(com.android.internal.R.string.cancel, null); 110 dialog.setShowForAllUsers(true); 111 112 if (view != null) { 113 mDialogLaunchAnimator.showFromView(dialog, view, new DialogCuj( 114 InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, 115 INTERACTION_JANK_TAG)); 116 } else { 117 dialog.show(); 118 } 119 }); 120 } 121 toggleDataSaver()122 private void toggleDataSaver() { 123 mState.value = !mDataSaverController.isDataSaverEnabled(); 124 mDataSaverController.setDataSaverEnabled(mState.value); 125 refreshState(mState.value); 126 } 127 128 @Override getTileLabel()129 public CharSequence getTileLabel() { 130 return mContext.getString(R.string.data_saver); 131 } 132 133 @Override handleUpdateState(BooleanState state, Object arg)134 protected void handleUpdateState(BooleanState state, Object arg) { 135 state.value = arg instanceof Boolean ? ((Boolean) arg).booleanValue() 136 : mDataSaverController.isDataSaverEnabled(); 137 state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; 138 state.label = mContext.getString(R.string.data_saver); 139 state.contentDescription = state.label; 140 state.icon = ResourceIcon.get(state.value ? R.drawable.qs_data_saver_icon_on 141 : R.drawable.qs_data_saver_icon_off); 142 state.expandedAccessibilityClassName = Switch.class.getName(); 143 } 144 145 @Override getMetricsCategory()146 public int getMetricsCategory() { 147 return MetricsEvent.QS_DATA_SAVER; 148 } 149 150 @Override onDataSaverChanged(boolean isDataSaving)151 public void onDataSaverChanged(boolean isDataSaving) { 152 refreshState(isDataSaving); 153 } 154 } 155