1 /*
2  * Copyright (C) 2015 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;
17 
18 import android.content.Intent;
19 import android.os.Handler;
20 import android.os.Looper;
21 import android.provider.Settings;
22 import android.provider.Settings.Secure;
23 import android.service.quicksettings.Tile;
24 import android.view.View;
25 import android.widget.Switch;
26 
27 import androidx.annotation.Nullable;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 import com.android.internal.logging.MetricsLogger;
31 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
32 import com.android.systemui.R;
33 import com.android.systemui.dagger.qualifiers.Background;
34 import com.android.systemui.dagger.qualifiers.Main;
35 import com.android.systemui.plugins.ActivityStarter;
36 import com.android.systemui.plugins.FalsingManager;
37 import com.android.systemui.plugins.qs.QSTile.BooleanState;
38 import com.android.systemui.plugins.statusbar.StatusBarStateController;
39 import com.android.systemui.qs.QSHost;
40 import com.android.systemui.qs.QsEventLogger;
41 import com.android.systemui.qs.SettingObserver;
42 import com.android.systemui.qs.logging.QSLogger;
43 import com.android.systemui.qs.tileimpl.QSTileImpl;
44 import com.android.systemui.statusbar.policy.BatteryController;
45 import com.android.systemui.util.settings.SecureSettings;
46 
47 import javax.inject.Inject;
48 
49 public class BatterySaverTile extends QSTileImpl<BooleanState> implements
50         BatteryController.BatteryStateChangeCallback {
51 
52     public static final String TILE_SPEC = "battery";
53 
54     private final BatteryController mBatteryController;
55     @VisibleForTesting
56     protected final SettingObserver mSetting;
57 
58     private int mLevel;
59     private boolean mPowerSave;
60     private boolean mCharging;
61     private boolean mPluggedIn;
62 
63     @Inject
BatterySaverTile( QSHost host, QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, MetricsLogger metricsLogger, StatusBarStateController statusBarStateController, ActivityStarter activityStarter, QSLogger qsLogger, BatteryController batteryController, SecureSettings secureSettings )64     public BatterySaverTile(
65             QSHost host,
66             QsEventLogger uiEventLogger,
67             @Background Looper backgroundLooper,
68             @Main Handler mainHandler,
69             FalsingManager falsingManager,
70             MetricsLogger metricsLogger,
71             StatusBarStateController statusBarStateController,
72             ActivityStarter activityStarter,
73             QSLogger qsLogger,
74             BatteryController batteryController,
75             SecureSettings secureSettings
76     ) {
77         super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
78                 statusBarStateController, activityStarter, qsLogger);
79         mBatteryController = batteryController;
80         mBatteryController.observe(getLifecycle(), this);
81         int currentUser = host.getUserContext().getUserId();
82         mSetting = new SettingObserver(
83                 secureSettings,
84                 mHandler,
85                 Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
86                 currentUser
87         ) {
88             @Override
89             protected void handleValueChanged(int value, boolean observedChange) {
90                 // mHandler is the background handler so calling this is OK
91                 handleRefreshState(null);
92             }
93         };
94     }
95 
96     @Override
newTileState()97     public BooleanState newTileState() {
98         return new BooleanState();
99     }
100 
101     @Override
handleDestroy()102     protected void handleDestroy() {
103         super.handleDestroy();
104         mSetting.setListening(false);
105     }
106 
107     @Override
handleUserSwitch(int newUserId)108     protected void handleUserSwitch(int newUserId) {
109         mSetting.setUserId(newUserId);
110     }
111 
112     @Override
getMetricsCategory()113     public int getMetricsCategory() {
114         return MetricsEvent.QS_BATTERY_TILE;
115     }
116 
117     @Override
handleSetListening(boolean listening)118     public void handleSetListening(boolean listening) {
119         super.handleSetListening(listening);
120         mSetting.setListening(listening);
121         if (!listening) {
122             // If we stopped listening, it means that the tile is not visible. In that case, we
123             // don't need to save the view anymore
124             mBatteryController.clearLastPowerSaverStartView();
125         }
126     }
127 
128     @Override
getLongClickIntent()129     public Intent getLongClickIntent() {
130         return new Intent(Settings.ACTION_BATTERY_SAVER_SETTINGS);
131     }
132 
133     @Override
handleClick(@ullable View view)134     protected void handleClick(@Nullable View view) {
135         if (getState().state == Tile.STATE_UNAVAILABLE) {
136             return;
137         }
138         mBatteryController.setPowerSaveMode(!mPowerSave, view);
139     }
140 
141     @Override
getTileLabel()142     public CharSequence getTileLabel() {
143         return mContext.getString(R.string.battery_detail_switch_title);
144     }
145 
146     @Override
handleUpdateState(BooleanState state, Object arg)147     protected void handleUpdateState(BooleanState state, Object arg) {
148         state.state = mPluggedIn ? Tile.STATE_UNAVAILABLE
149                 : mPowerSave ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
150         state.icon = ResourceIcon.get(mPowerSave
151                 ? R.drawable.qs_battery_saver_icon_on
152                 : R.drawable.qs_battery_saver_icon_off);
153         state.label = mContext.getString(R.string.battery_detail_switch_title);
154         state.secondaryLabel = "";
155         state.contentDescription = state.label;
156         state.value = mPowerSave;
157         state.expandedAccessibilityClassName = Switch.class.getName();
158     }
159 
160     @Override
onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging)161     public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
162         mLevel = level;
163         mPluggedIn = pluggedIn;
164         mCharging = charging;
165         refreshState(level);
166     }
167 
168     @Override
onPowerSaveChanged(boolean isPowerSave)169     public void onPowerSaveChanged(boolean isPowerSave) {
170         mPowerSave = isPowerSave;
171         refreshState(null);
172     }
173 }
174