blob: 001e09406e3ae012722476805a627e55bbee7a3a [file] [log] [blame]
John Spurlockaf8d6c42014-05-07 17:49:08 -04001/*
2 * Copyright (C) 2014 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
17package com.android.systemui.qs.tiles;
18
Rohan Shahe4071122018-01-22 15:16:09 -080019import android.annotation.Nullable;
Jake Whatleyac7c5d22017-02-02 20:25:12 -050020import android.content.ComponentName;
Jason Monk76c67aa2016-02-19 14:49:42 -050021import android.content.Intent;
Sudheer Shankab6fc9312016-01-27 19:59:03 +000022import android.os.UserManager;
jackqdyulei76471a52016-12-05 15:03:56 -080023import android.service.quicksettings.Tile;
Julia Reynolds20aef8a2016-05-04 16:44:08 -040024import android.widget.Switch;
25
Tamas Berghammer383db5eb2016-06-22 15:21:38 +010026import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
John Spurlockaf8d6c42014-05-07 17:49:08 -040027import com.android.systemui.R;
Salvador Martinez1c2c3372019-03-08 16:11:23 -080028import com.android.systemui.plugins.qs.QSTile.BooleanState;
Jason Monk702e2eb2017-03-03 16:53:44 -050029import com.android.systemui.qs.QSHost;
Jason Monk702e2eb2017-03-03 16:53:44 -050030import com.android.systemui.qs.tileimpl.QSTileImpl;
Rohan Shah815fa982018-03-01 13:15:13 -080031import com.android.systemui.statusbar.policy.DataSaverController;
Jason Monk51e4dc02014-07-22 12:00:47 -040032import com.android.systemui.statusbar.policy.HotspotController;
John Spurlockaf8d6c42014-05-07 17:49:08 -040033
Jason Monk5d577202018-12-26 15:43:06 -050034import javax.inject.Inject;
35
John Spurlockaf8d6c42014-05-07 17:49:08 -040036/** Quick settings tile: Hotspot **/
Salvador Martinez1c2c3372019-03-08 16:11:23 -080037public class HotspotTile extends QSTileImpl<BooleanState> {
Rohan Shah815fa982018-03-01 13:15:13 -080038 private static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
Rohan Shahe4071122018-01-22 15:16:09 -080039 "com.android.settings", "com.android.settings.TetherSettings"));
Jake Whatleyac7c5d22017-02-02 20:25:12 -050040
Evan Lairdbcdd0462017-05-15 12:51:34 -040041 private final Icon mEnabledStatic = ResourceIcon.get(R.drawable.ic_hotspot);
Jason Monkab17c982016-06-20 12:39:38 -040042
Rohan Shah815fa982018-03-01 13:15:13 -080043 private final HotspotController mHotspotController;
44 private final DataSaverController mDataSaverController;
45
46 private final HotspotAndDataSaverCallbacks mCallbacks = new HotspotAndDataSaverCallbacks();
Jason Monk49a27962016-05-25 14:22:01 -040047 private boolean mListening;
John Spurlockaf8d6c42014-05-07 17:49:08 -040048
Jason Monk5d577202018-12-26 15:43:06 -050049 @Inject
Jason Monkc0e0e2b2018-12-26 16:47:41 -050050 public HotspotTile(QSHost host, HotspotController hotspotController,
51 DataSaverController dataSaverController) {
John Spurlockaf8d6c42014-05-07 17:49:08 -040052 super(host);
Jason Monkc0e0e2b2018-12-26 16:47:41 -050053 mHotspotController = hotspotController;
54 mDataSaverController = dataSaverController;
Jason Monkfa452ef2018-12-26 17:26:10 -050055 mHotspotController.observe(this, mCallbacks);
56 mDataSaverController.observe(this, mCallbacks);
John Spurlockbceed062014-08-10 18:04:16 -040057 }
58
59 @Override
Jason Monk28680c62016-04-19 09:31:20 -040060 public boolean isAvailable() {
Rohan Shah815fa982018-03-01 13:15:13 -080061 return mHotspotController.isHotspotSupported();
Jason Monk28680c62016-04-19 09:31:20 -040062 }
63
64 @Override
John Spurlockbceed062014-08-10 18:04:16 -040065 protected void handleDestroy() {
66 super.handleDestroy();
John Spurlockaf8d6c42014-05-07 17:49:08 -040067 }
68
69 @Override
Jason Monk1c6116c2017-09-06 17:33:01 -040070 public void handleSetListening(boolean listening) {
Jason Monk49a27962016-05-25 14:22:01 -040071 if (mListening == listening) return;
72 mListening = listening;
Jason Monk51e4dc02014-07-22 12:00:47 -040073 if (listening) {
Jason Monk94f682e2016-06-23 13:23:01 -040074 refreshState();
Jason Monk51e4dc02014-07-22 12:00:47 -040075 }
John Spurlockaf8d6c42014-05-07 17:49:08 -040076 }
77
78 @Override
Jason Monk76c67aa2016-02-19 14:49:42 -050079 public Intent getLongClickIntent() {
Jake Whatleyac7c5d22017-02-02 20:25:12 -050080 return new Intent(TETHER_SETTINGS);
Jason Monk76c67aa2016-02-19 14:49:42 -050081 }
82
83 @Override
Salvador Martinez1c2c3372019-03-08 16:11:23 -080084 public BooleanState newTileState() {
85 return new BooleanState();
86 }
87
88 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -040089 protected void handleClick() {
Amin Shaikhd03a7432018-03-01 15:46:55 -050090 final boolean isEnabled = mState.value;
Salvador Martinez1c2c3372019-03-08 16:11:23 -080091 if (!isEnabled && mDataSaverController.isDataSaverEnabled()) {
Jason Monk49a27962016-05-25 14:22:01 -040092 return;
93 }
Amin Shaikhd03a7432018-03-01 15:46:55 -050094 // Immediately enter transient enabling state when turning hotspot on.
95 refreshState(isEnabled ? null : ARG_SHOW_TRANSIENT_ENABLING);
Rohan Shah815fa982018-03-01 13:15:13 -080096 mHotspotController.setHotspotEnabled(!isEnabled);
John Spurlockaf8d6c42014-05-07 17:49:08 -040097 }
98
99 @Override
Jason Monk39c98e62016-03-16 09:18:35 -0400100 public CharSequence getTileLabel() {
101 return mContext.getString(R.string.quick_settings_hotspot_label);
102 }
103
104 @Override
Salvador Martinez1c2c3372019-03-08 16:11:23 -0800105 protected void handleUpdateState(BooleanState state, Object arg) {
Amin Shaikhd03a7432018-03-01 15:46:55 -0500106 final boolean transientEnabling = arg == ARG_SHOW_TRANSIENT_ENABLING;
Jason Monk395617f2017-05-05 14:07:58 -0400107 if (state.slash == null) {
108 state.slash = new SlashState();
109 }
Rohan Shahe4071122018-01-22 15:16:09 -0800110
111 final int numConnectedDevices;
Rohan Shah815fa982018-03-01 13:15:13 -0800112 final boolean isTransient = transientEnabling || mHotspotController.isHotspotTransient();
113 final boolean isDataSaverEnabled;
Rohan Shah1b497b02018-01-24 11:28:37 -0800114
115 checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_TETHERING);
Rohan Shah815fa982018-03-01 13:15:13 -0800116
Rohan Shahe4071122018-01-22 15:16:09 -0800117 if (arg instanceof CallbackInfo) {
Rohan Shah815fa982018-03-01 13:15:13 -0800118 final CallbackInfo info = (CallbackInfo) arg;
119 state.value = transientEnabling || info.isHotspotEnabled;
Rohan Shahe4071122018-01-22 15:16:09 -0800120 numConnectedDevices = info.numConnectedDevices;
Rohan Shah815fa982018-03-01 13:15:13 -0800121 isDataSaverEnabled = info.isDataSaverEnabled;
Julia Reynoldsb8a46a62015-07-14 13:36:30 -0400122 } else {
Rohan Shah815fa982018-03-01 13:15:13 -0800123 state.value = transientEnabling || mHotspotController.isHotspotEnabled();
124 numConnectedDevices = mHotspotController.getNumConnectedDevices();
125 isDataSaverEnabled = mDataSaverController.isDataSaverEnabled();
Julia Reynoldsb8a46a62015-07-14 13:36:30 -0400126 }
Rohan Shahe4071122018-01-22 15:16:09 -0800127
Jason Monk395617f2017-05-05 14:07:58 -0400128 state.icon = mEnabledStatic;
Rohan Shah1b497b02018-01-24 11:28:37 -0800129 state.label = mContext.getString(R.string.quick_settings_hotspot_label);
Rohan Shah1b497b02018-01-24 11:28:37 -0800130 state.isTransient = isTransient;
Jason Monk395617f2017-05-05 14:07:58 -0400131 state.slash.isSlashed = !state.value && !state.isTransient;
Jason Monke645aee2017-03-31 13:19:26 -0400132 if (state.isTransient) {
Amin Shaikh2cea8792019-04-30 09:19:01 -0400133 state.icon = ResourceIcon.get(
134 com.android.internal.R.drawable.ic_hotspot_transient_animation);
Jason Monk49a27962016-05-25 14:22:01 -0400135 }
Jason Monk702e2eb2017-03-03 16:53:44 -0500136 state.expandedAccessibilityClassName = Switch.class.getName();
Julia Reynolds20aef8a2016-05-04 16:44:08 -0400137 state.contentDescription = state.label;
Rohan Shah815fa982018-03-01 13:15:13 -0800138
Salvador Martinez1c2c3372019-03-08 16:11:23 -0800139 final boolean isTileUnavailable = isDataSaverEnabled;
Rohan Shah815fa982018-03-01 13:15:13 -0800140 final boolean isTileActive = (state.value || state.isTransient);
Rohan Shah2c23b132018-03-09 13:41:11 -0800141
142 if (isTileUnavailable) {
143 state.state = Tile.STATE_UNAVAILABLE;
144 } else {
145 state.state = isTileActive ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
146 }
147
148 state.secondaryLabel = getSecondaryLabel(
149 isTileActive, isTransient, isDataSaverEnabled, numConnectedDevices);
Jason Monk51e4dc02014-07-22 12:00:47 -0400150 }
151
Rohan Shahe4071122018-01-22 15:16:09 -0800152 @Nullable
Rohan Shah2c23b132018-03-09 13:41:11 -0800153 private String getSecondaryLabel(boolean isActive, boolean isTransient,
154 boolean isDataSaverEnabled, int numConnectedDevices) {
Rohan Shah1b497b02018-01-24 11:28:37 -0800155 if (isTransient) {
156 return mContext.getString(R.string.quick_settings_hotspot_secondary_label_transient);
Rohan Shah2c23b132018-03-09 13:41:11 -0800157 } else if (isDataSaverEnabled) {
158 return mContext.getString(
159 R.string.quick_settings_hotspot_secondary_label_data_saver_enabled);
160 } else if (numConnectedDevices > 0 && isActive) {
Rohan Shahe4071122018-01-22 15:16:09 -0800161 return mContext.getResources().getQuantityString(
Rohan Shah1b497b02018-01-24 11:28:37 -0800162 R.plurals.quick_settings_hotspot_secondary_label_num_devices,
Rohan Shahe4071122018-01-22 15:16:09 -0800163 numConnectedDevices,
164 numConnectedDevices);
165 }
166
167 return null;
168 }
169
Selim Cinek4fda7b22014-08-18 22:07:25 +0200170 @Override
Chris Wren457a21c2015-05-06 17:50:34 -0400171 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500172 return MetricsEvent.QS_HOTSPOT;
Chris Wren457a21c2015-05-06 17:50:34 -0400173 }
174
175 @Override
Selim Cinek4fda7b22014-08-18 22:07:25 +0200176 protected String composeChangeAnnouncement() {
177 if (mState.value) {
178 return mContext.getString(R.string.accessibility_quick_settings_hotspot_changed_on);
179 } else {
180 return mContext.getString(R.string.accessibility_quick_settings_hotspot_changed_off);
181 }
182 }
183
Rohan Shah815fa982018-03-01 13:15:13 -0800184 /**
185 * Listens to changes made to hotspot and data saver states (to toggle tile availability).
186 */
187 private final class HotspotAndDataSaverCallbacks implements HotspotController.Callback,
188 DataSaverController.Listener {
189 CallbackInfo mCallbackInfo = new CallbackInfo();
Rohan Shahe4071122018-01-22 15:16:09 -0800190
Jason Monk51e4dc02014-07-22 12:00:47 -0400191 @Override
Rohan Shah815fa982018-03-01 13:15:13 -0800192 public void onDataSaverChanged(boolean isDataSaving) {
193 mCallbackInfo.isDataSaverEnabled = isDataSaving;
194 refreshState(mCallbackInfo);
195 }
196
197 @Override
198 public void onHotspotChanged(boolean enabled, int numDevices) {
199 mCallbackInfo.isHotspotEnabled = enabled;
200 mCallbackInfo.numConnectedDevices = numDevices;
Rohan Shahe4071122018-01-22 15:16:09 -0800201 refreshState(mCallbackInfo);
Jason Monk51e4dc02014-07-22 12:00:47 -0400202 }
Rohan Shahe4071122018-01-22 15:16:09 -0800203 }
204
205 /**
206 * Holder for any hotspot state info that needs to passed from the callback to
207 * {@link #handleUpdateState(State, Object)}.
208 */
209 protected static final class CallbackInfo {
Rohan Shah815fa982018-03-01 13:15:13 -0800210 boolean isHotspotEnabled;
Rohan Shahe4071122018-01-22 15:16:09 -0800211 int numConnectedDevices;
Rohan Shah815fa982018-03-01 13:15:13 -0800212 boolean isDataSaverEnabled;
Rohan Shahe4071122018-01-22 15:16:09 -0800213
214 @Override
215 public String toString() {
216 return new StringBuilder("CallbackInfo[")
Rohan Shah815fa982018-03-01 13:15:13 -0800217 .append("isHotspotEnabled=").append(isHotspotEnabled)
Rohan Shahe4071122018-01-22 15:16:09 -0800218 .append(",numConnectedDevices=").append(numConnectedDevices)
Rohan Shah815fa982018-03-01 13:15:13 -0800219 .append(",isDataSaverEnabled=").append(isDataSaverEnabled)
Rohan Shahe4071122018-01-22 15:16:09 -0800220 .append(']').toString();
221 }
222 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400223}