Merge "Creates Dream Tile." into tm-qpr-dev am: 31e221dfb4
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17874521 Change-Id: Ib0d78db66b5d5d73567b9cca2186bbd9495d5149 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -87,7 +87,7 @@
|
|||||||
|
|
||||||
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
|
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
|
||||||
<string name="quick_settings_tiles_stock" translatable="false">
|
<string name="quick_settings_tiles_stock" translatable="false">
|
||||||
internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,color_correction
|
internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,color_correction,dream
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
<!-- The tiles to display in QuickSettings -->
|
<!-- The tiles to display in QuickSettings -->
|
||||||
|
|||||||
@@ -578,6 +578,8 @@
|
|||||||
<!-- QuickSettings: Location [CHAR LIMIT=NONE] -->
|
<!-- QuickSettings: Location [CHAR LIMIT=NONE] -->
|
||||||
<string name="quick_settings_location_label">Location</string>
|
<string name="quick_settings_location_label">Location</string>
|
||||||
<!-- QuickSettings: Location (Off) [CHAR LIMIT=NONE] -->
|
<!-- QuickSettings: Location (Off) [CHAR LIMIT=NONE] -->
|
||||||
|
<!-- QuickSettings: Screen saver [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="quick_settings_screensaver_label">Screen saver</string>
|
||||||
<!-- QuickSettings: Camera [CHAR LIMIT=NONE] -->
|
<!-- QuickSettings: Camera [CHAR LIMIT=NONE] -->
|
||||||
<string name="quick_settings_camera_label">Camera access</string>
|
<string name="quick_settings_camera_label">Camera access</string>
|
||||||
<!-- QuickSettings: Microphone [CHAR LIMIT=NONE] -->
|
<!-- QuickSettings: Microphone [CHAR LIMIT=NONE] -->
|
||||||
|
|||||||
@@ -308,4 +308,14 @@
|
|||||||
<item>Off</item>
|
<item>Off</item>
|
||||||
<item>On</item>
|
<item>On</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- State names for dream (screensaver) tile: unavailable, off, on.
|
||||||
|
This subtitle is shown when the tile is in that particular state but does not set its own
|
||||||
|
subtitle, so some of these may never appear on screen. They should still be translated as
|
||||||
|
if they could appear. [CHAR LIMIT=32] -->
|
||||||
|
<string-array name="tile_states_dream">
|
||||||
|
<item>Unavailable</item>
|
||||||
|
<item>Off</item>
|
||||||
|
<item>On</item>
|
||||||
|
</string-array>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -39,6 +39,7 @@ import com.android.systemui.qs.tiles.ColorInversionTile;
|
|||||||
import com.android.systemui.qs.tiles.DataSaverTile;
|
import com.android.systemui.qs.tiles.DataSaverTile;
|
||||||
import com.android.systemui.qs.tiles.DeviceControlsTile;
|
import com.android.systemui.qs.tiles.DeviceControlsTile;
|
||||||
import com.android.systemui.qs.tiles.DndTile;
|
import com.android.systemui.qs.tiles.DndTile;
|
||||||
|
import com.android.systemui.qs.tiles.DreamTile;
|
||||||
import com.android.systemui.qs.tiles.FlashlightTile;
|
import com.android.systemui.qs.tiles.FlashlightTile;
|
||||||
import com.android.systemui.qs.tiles.HotspotTile;
|
import com.android.systemui.qs.tiles.HotspotTile;
|
||||||
import com.android.systemui.qs.tiles.InternetTile;
|
import com.android.systemui.qs.tiles.InternetTile;
|
||||||
@@ -96,6 +97,7 @@ public class QSFactoryImpl implements QSFactory {
|
|||||||
private final Provider<QuickAccessWalletTile> mQuickAccessWalletTileProvider;
|
private final Provider<QuickAccessWalletTile> mQuickAccessWalletTileProvider;
|
||||||
private final Provider<QRCodeScannerTile> mQRCodeScannerTileProvider;
|
private final Provider<QRCodeScannerTile> mQRCodeScannerTileProvider;
|
||||||
private final Provider<OneHandedModeTile> mOneHandedModeTileProvider;
|
private final Provider<OneHandedModeTile> mOneHandedModeTileProvider;
|
||||||
|
private final Provider<DreamTile> mDreamTileProvider;
|
||||||
|
|
||||||
private final Lazy<QSHost> mQsHostLazy;
|
private final Lazy<QSHost> mQsHostLazy;
|
||||||
private final Provider<CustomTile.Builder> mCustomTileBuilderProvider;
|
private final Provider<CustomTile.Builder> mCustomTileBuilderProvider;
|
||||||
@@ -132,7 +134,8 @@ public class QSFactoryImpl implements QSFactory {
|
|||||||
Provider<QuickAccessWalletTile> quickAccessWalletTileProvider,
|
Provider<QuickAccessWalletTile> quickAccessWalletTileProvider,
|
||||||
Provider<QRCodeScannerTile> qrCodeScannerTileProvider,
|
Provider<QRCodeScannerTile> qrCodeScannerTileProvider,
|
||||||
Provider<OneHandedModeTile> oneHandedModeTileProvider,
|
Provider<OneHandedModeTile> oneHandedModeTileProvider,
|
||||||
Provider<ColorCorrectionTile> colorCorrectionTileProvider) {
|
Provider<ColorCorrectionTile> colorCorrectionTileProvider,
|
||||||
|
Provider<DreamTile> dreamTileProvider) {
|
||||||
mQsHostLazy = qsHostLazy;
|
mQsHostLazy = qsHostLazy;
|
||||||
mCustomTileBuilderProvider = customTileBuilderProvider;
|
mCustomTileBuilderProvider = customTileBuilderProvider;
|
||||||
|
|
||||||
@@ -165,6 +168,7 @@ public class QSFactoryImpl implements QSFactory {
|
|||||||
mQRCodeScannerTileProvider = qrCodeScannerTileProvider;
|
mQRCodeScannerTileProvider = qrCodeScannerTileProvider;
|
||||||
mOneHandedModeTileProvider = oneHandedModeTileProvider;
|
mOneHandedModeTileProvider = oneHandedModeTileProvider;
|
||||||
mColorCorrectionTileProvider = colorCorrectionTileProvider;
|
mColorCorrectionTileProvider = colorCorrectionTileProvider;
|
||||||
|
mDreamTileProvider = dreamTileProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a tile with a type based on {@code tileSpec} */
|
/** Creates a tile with a type based on {@code tileSpec} */
|
||||||
@@ -238,6 +242,8 @@ public class QSFactoryImpl implements QSFactory {
|
|||||||
return mOneHandedModeTileProvider.get();
|
return mOneHandedModeTileProvider.get();
|
||||||
case "color_correction":
|
case "color_correction":
|
||||||
return mColorCorrectionTileProvider.get();
|
return mColorCorrectionTileProvider.get();
|
||||||
|
case "dream":
|
||||||
|
return mDreamTileProvider.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom tiles
|
// Custom tiles
|
||||||
|
|||||||
@@ -670,7 +670,8 @@ internal object SubtitleArrayMapping {
|
|||||||
"qr_code_scanner" to R.array.tile_states_qr_code_scanner,
|
"qr_code_scanner" to R.array.tile_states_qr_code_scanner,
|
||||||
"alarm" to R.array.tile_states_alarm,
|
"alarm" to R.array.tile_states_alarm,
|
||||||
"onehanded" to R.array.tile_states_onehanded,
|
"onehanded" to R.array.tile_states_onehanded,
|
||||||
"color_correction" to R.array.tile_states_color_correction
|
"color_correction" to R.array.tile_states_color_correction,
|
||||||
|
"dream" to R.array.tile_states_dream
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getSubtitleId(spec: String?): Int {
|
fun getSubtitleId(spec: String?): Int {
|
||||||
|
|||||||
@@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ServiceInfo;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.service.dreams.IDreamManager;
|
||||||
|
import android.service.quicksettings.Tile;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
|
import com.android.internal.logging.MetricsLogger;
|
||||||
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||||
|
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.QSTile;
|
||||||
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
|
import com.android.systemui.qs.QSHost;
|
||||||
|
import com.android.systemui.qs.SettingObserver;
|
||||||
|
import com.android.systemui.qs.logging.QSLogger;
|
||||||
|
import com.android.systemui.qs.tileimpl.QSTileImpl;
|
||||||
|
import com.android.systemui.util.settings.SecureSettings;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
/** Quick settings tile: Screensaver (dream) **/
|
||||||
|
public class DreamTile extends QSTileImpl<QSTile.BooleanState> {
|
||||||
|
|
||||||
|
private static final String LOG_TAG = "QSDream";
|
||||||
|
private final IDreamManager mDreamManager;
|
||||||
|
private final SecureSettings mSecureSettings;
|
||||||
|
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||||
|
private final SettingObserver mEnabledSettingObserver;
|
||||||
|
private final SettingObserver mDreamSettingObserver;
|
||||||
|
|
||||||
|
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
refreshState();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public DreamTile(
|
||||||
|
QSHost host,
|
||||||
|
@Background Looper backgroundLooper,
|
||||||
|
@Main Handler mainHandler,
|
||||||
|
FalsingManager falsingManager,
|
||||||
|
MetricsLogger metricsLogger,
|
||||||
|
StatusBarStateController statusBarStateController,
|
||||||
|
ActivityStarter activityStarter,
|
||||||
|
QSLogger qsLogger,
|
||||||
|
IDreamManager dreamManager,
|
||||||
|
SecureSettings secureSettings,
|
||||||
|
BroadcastDispatcher broadcastDispatcher
|
||||||
|
) {
|
||||||
|
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
|
||||||
|
statusBarStateController, activityStarter, qsLogger);
|
||||||
|
mDreamManager = dreamManager;
|
||||||
|
mSecureSettings = secureSettings;
|
||||||
|
mBroadcastDispatcher = broadcastDispatcher;
|
||||||
|
mEnabledSettingObserver = new SettingObserver(secureSettings, mHandler,
|
||||||
|
Settings.Secure.SCREENSAVER_ENABLED) {
|
||||||
|
@Override
|
||||||
|
protected void handleValueChanged(int value, boolean observedChange) {
|
||||||
|
refreshState();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mDreamSettingObserver = new SettingObserver(secureSettings, mHandler,
|
||||||
|
Settings.Secure.SCREENSAVER_COMPONENTS) {
|
||||||
|
@Override
|
||||||
|
protected void handleValueChanged(int value, boolean observedChange) {
|
||||||
|
refreshState();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleSetListening(boolean listening) {
|
||||||
|
super.handleSetListening(listening);
|
||||||
|
|
||||||
|
if (listening) {
|
||||||
|
final IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(Intent.ACTION_DREAMING_STARTED);
|
||||||
|
filter.addAction(Intent.ACTION_DREAMING_STOPPED);
|
||||||
|
mBroadcastDispatcher.registerReceiver(mReceiver, filter);
|
||||||
|
} else {
|
||||||
|
mBroadcastDispatcher.unregisterReceiver(mReceiver);
|
||||||
|
}
|
||||||
|
mEnabledSettingObserver.setListening(listening);
|
||||||
|
mDreamSettingObserver.setListening(listening);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BooleanState newTileState() {
|
||||||
|
return new BooleanState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleClick(@Nullable View view) {
|
||||||
|
try {
|
||||||
|
if (mDreamManager.isDreaming()) {
|
||||||
|
mDreamManager.awaken();
|
||||||
|
} else {
|
||||||
|
mDreamManager.dream();
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(LOG_TAG, "Can't dream", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleLongClick(@Nullable View view) {
|
||||||
|
try {
|
||||||
|
// Need to wake on long click so bouncer->settings works.
|
||||||
|
mDreamManager.awaken();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(LOG_TAG, "Can't awaken", e);
|
||||||
|
}
|
||||||
|
super.handleLongClick(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleUpdateState(BooleanState state, Object arg) {
|
||||||
|
state.label = getTileLabel();
|
||||||
|
state.secondaryLabel = getActiveDreamName();
|
||||||
|
state.contentDescription = getContentDescription(state.secondaryLabel);
|
||||||
|
|
||||||
|
if (getActiveDream() == null || !isScreensaverEnabled()) {
|
||||||
|
state.state = Tile.STATE_UNAVAILABLE;
|
||||||
|
} else {
|
||||||
|
state.state = isDreaming() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Intent getLongClickIntent() {
|
||||||
|
return new Intent(Settings.ACTION_DREAM_SETTINGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getTileLabel() {
|
||||||
|
return mContext.getString(R.string.quick_settings_screensaver_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
// For now, only present on userdebug devices.
|
||||||
|
return Build.isDebuggable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
protected CharSequence getContentDescription(CharSequence dreamName) {
|
||||||
|
return !TextUtils.isEmpty(dreamName)
|
||||||
|
? getTileLabel() + ", " + dreamName : getTileLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDreaming() {
|
||||||
|
try {
|
||||||
|
return mDreamManager.isDreaming();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(LOG_TAG, "Can't check if dreaming", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ComponentName getActiveDream() {
|
||||||
|
try {
|
||||||
|
final ComponentName[] dreams = mDreamManager.getDreamComponents();
|
||||||
|
return dreams != null && dreams.length > 0 ? dreams[0] : null;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "Failed to get active dream", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CharSequence getActiveDreamName() {
|
||||||
|
final ComponentName componentName = getActiveDream();
|
||||||
|
if (componentName != null) {
|
||||||
|
PackageManager pm = mContext.getPackageManager();
|
||||||
|
try {
|
||||||
|
ServiceInfo ri = pm.getServiceInfo(componentName, 0);
|
||||||
|
if (ri != null) {
|
||||||
|
return ri.loadLabel(pm);
|
||||||
|
}
|
||||||
|
} catch (PackageManager.NameNotFoundException exc) {
|
||||||
|
return null; // uninstalled?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isScreensaverEnabled() {
|
||||||
|
return mEnabledSettingObserver.getValue() == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,7 @@ import com.android.systemui.qs.tiles.ColorInversionTile
|
|||||||
import com.android.systemui.qs.tiles.DataSaverTile
|
import com.android.systemui.qs.tiles.DataSaverTile
|
||||||
import com.android.systemui.qs.tiles.DeviceControlsTile
|
import com.android.systemui.qs.tiles.DeviceControlsTile
|
||||||
import com.android.systemui.qs.tiles.DndTile
|
import com.android.systemui.qs.tiles.DndTile
|
||||||
|
import com.android.systemui.qs.tiles.DreamTile
|
||||||
import com.android.systemui.qs.tiles.FlashlightTile
|
import com.android.systemui.qs.tiles.FlashlightTile
|
||||||
import com.android.systemui.qs.tiles.HotspotTile
|
import com.android.systemui.qs.tiles.HotspotTile
|
||||||
import com.android.systemui.qs.tiles.InternetTile
|
import com.android.systemui.qs.tiles.InternetTile
|
||||||
@@ -89,7 +90,8 @@ private val specMap = mapOf(
|
|||||||
"wallet" to QuickAccessWalletTile::class.java,
|
"wallet" to QuickAccessWalletTile::class.java,
|
||||||
"qr_code_scanner" to QRCodeScannerTile::class.java,
|
"qr_code_scanner" to QRCodeScannerTile::class.java,
|
||||||
"onehanded" to OneHandedModeTile::class.java,
|
"onehanded" to OneHandedModeTile::class.java,
|
||||||
"color_correction" to ColorCorrectionTile::class.java
|
"color_correction" to ColorCorrectionTile::class.java,
|
||||||
|
"dream" to DreamTile::class.java
|
||||||
)
|
)
|
||||||
|
|
||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@@ -129,6 +131,7 @@ class QSFactoryImplTest : SysuiTestCase() {
|
|||||||
@Mock private lateinit var qrCodeScannerTile: QRCodeScannerTile
|
@Mock private lateinit var qrCodeScannerTile: QRCodeScannerTile
|
||||||
@Mock private lateinit var oneHandedModeTile: OneHandedModeTile
|
@Mock private lateinit var oneHandedModeTile: OneHandedModeTile
|
||||||
@Mock private lateinit var colorCorrectionTile: ColorCorrectionTile
|
@Mock private lateinit var colorCorrectionTile: ColorCorrectionTile
|
||||||
|
@Mock private lateinit var dreamTile: DreamTile
|
||||||
|
|
||||||
private lateinit var factory: QSFactoryImpl
|
private lateinit var factory: QSFactoryImpl
|
||||||
|
|
||||||
@@ -171,7 +174,8 @@ class QSFactoryImplTest : SysuiTestCase() {
|
|||||||
{ quickAccessWalletTile },
|
{ quickAccessWalletTile },
|
||||||
{ qrCodeScannerTile },
|
{ qrCodeScannerTile },
|
||||||
{ oneHandedModeTile },
|
{ oneHandedModeTile },
|
||||||
{ colorCorrectionTile }
|
{ colorCorrectionTile },
|
||||||
|
{ dreamTile }
|
||||||
)
|
)
|
||||||
// When adding/removing tiles, fix also [specMap]
|
// When adding/removing tiles, fix also [specMap]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertEquals;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.service.dreams.IDreamManager;
|
||||||
|
import android.service.quicksettings.Tile;
|
||||||
|
import android.testing.AndroidTestingRunner;
|
||||||
|
import android.testing.TestableLooper;
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.internal.logging.MetricsLogger;
|
||||||
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||||
|
import com.android.systemui.classifier.FalsingManagerFake;
|
||||||
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
|
import com.android.systemui.qs.QSTileHost;
|
||||||
|
import com.android.systemui.qs.logging.QSLogger;
|
||||||
|
import com.android.systemui.util.settings.FakeSettings;
|
||||||
|
import com.android.systemui.util.settings.SecureSettings;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
@RunWith(AndroidTestingRunner.class)
|
||||||
|
@TestableLooper.RunWithLooper(setAsMainLooper = true)
|
||||||
|
@SmallTest
|
||||||
|
public class DreamTileTest extends SysuiTestCase {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ActivityStarter mActivityStarter;
|
||||||
|
@Mock
|
||||||
|
private QSTileHost mHost;
|
||||||
|
@Mock
|
||||||
|
private MetricsLogger mMetricsLogger;
|
||||||
|
@Mock
|
||||||
|
private QSLogger mQSLogger;
|
||||||
|
@Mock
|
||||||
|
private StatusBarStateController mStatusBarStateController;
|
||||||
|
@Mock
|
||||||
|
private IDreamManager mDreamManager;
|
||||||
|
@Mock
|
||||||
|
private BroadcastDispatcher mBroadcastDispatcher;
|
||||||
|
|
||||||
|
private TestableLooper mTestableLooper;
|
||||||
|
|
||||||
|
private DreamTile mTile;
|
||||||
|
|
||||||
|
private SecureSettings mSecureSettings;
|
||||||
|
|
||||||
|
private static final ComponentName COLORS_DREAM_COMPONENT_NAME = new ComponentName(
|
||||||
|
"com.android.dreams", ".Colors");
|
||||||
|
|
||||||
|
private static final int DEFAULT_USER = 0;
|
||||||
|
|
||||||
|
private final String mExpectedTileLabel = mContext.getResources().getString(
|
||||||
|
R.string.quick_settings_screensaver_label);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mSecureSettings = new FakeSettings();
|
||||||
|
mTestableLooper = TestableLooper.get(this);
|
||||||
|
|
||||||
|
when(mHost.getUserId()).thenReturn(DEFAULT_USER);
|
||||||
|
when(mHost.getContext()).thenReturn(mContext);
|
||||||
|
|
||||||
|
mTile = spy(new DreamTile(
|
||||||
|
mHost,
|
||||||
|
mTestableLooper.getLooper(),
|
||||||
|
new Handler(mTestableLooper.getLooper()),
|
||||||
|
new FalsingManagerFake(),
|
||||||
|
mMetricsLogger,
|
||||||
|
mStatusBarStateController,
|
||||||
|
mActivityStarter,
|
||||||
|
mQSLogger,
|
||||||
|
mDreamManager,
|
||||||
|
mSecureSettings,
|
||||||
|
mBroadcastDispatcher));
|
||||||
|
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
mTile.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNotAvailable() throws RemoteException {
|
||||||
|
// Should not be available if screensaver is disabled
|
||||||
|
setScreensaverEnabled(false);
|
||||||
|
|
||||||
|
mTile.refreshState();
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
assertEquals(Tile.STATE_UNAVAILABLE, mTile.getState().state);
|
||||||
|
|
||||||
|
// Should not be available if component is not set
|
||||||
|
mSecureSettings.putInt(Settings.Secure.SCREENSAVER_ENABLED, 1);
|
||||||
|
when(mDreamManager.getDreamComponents()).thenReturn(null);
|
||||||
|
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
assertEquals(Tile.STATE_UNAVAILABLE, mTile.getState().state);
|
||||||
|
assertEquals(mExpectedTileLabel, mTile.getState().contentDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInactiveWhenDreaming() throws RemoteException {
|
||||||
|
setScreensaverEnabled(true);
|
||||||
|
|
||||||
|
when(mDreamManager.getDreamComponents()).thenReturn(new ComponentName[]{
|
||||||
|
COLORS_DREAM_COMPONENT_NAME
|
||||||
|
});
|
||||||
|
when(mDreamManager.isDreaming()).thenReturn(false);
|
||||||
|
|
||||||
|
mTile.refreshState();
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
assertEquals(Tile.STATE_INACTIVE, mTile.getState().state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testActive() throws RemoteException {
|
||||||
|
setScreensaverEnabled(true);
|
||||||
|
|
||||||
|
when(mDreamManager.getDreamComponents()).thenReturn(new ComponentName[]{
|
||||||
|
COLORS_DREAM_COMPONENT_NAME
|
||||||
|
});
|
||||||
|
when(mDreamManager.isDreaming()).thenReturn(true);
|
||||||
|
|
||||||
|
mTile.refreshState();
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
assertEquals(Tile.STATE_ACTIVE, mTile.getState().state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClick() throws RemoteException {
|
||||||
|
// Set the AOSP dream enabled as the base setup.
|
||||||
|
setScreensaverEnabled(true);
|
||||||
|
when(mDreamManager.getDreamComponents()).thenReturn(new ComponentName[]{
|
||||||
|
COLORS_DREAM_COMPONENT_NAME
|
||||||
|
});
|
||||||
|
when(mDreamManager.isDreaming()).thenReturn(false);
|
||||||
|
|
||||||
|
mTile.refreshState();
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
assertEquals(Tile.STATE_INACTIVE, mTile.getState().state);
|
||||||
|
|
||||||
|
// Now click
|
||||||
|
mTile.handleClick(null /* view */);
|
||||||
|
|
||||||
|
verify(mDreamManager).dream();
|
||||||
|
|
||||||
|
when(mDreamManager.isDreaming()).thenReturn(true);
|
||||||
|
mTile.refreshState();
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
assertEquals(Tile.STATE_ACTIVE, mTile.getState().state);
|
||||||
|
|
||||||
|
// Click again to see that other method is called
|
||||||
|
mTile.handleClick(null /* view */);
|
||||||
|
|
||||||
|
verify(mDreamManager).awaken();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testContentDescription() {
|
||||||
|
assertEquals(mExpectedTileLabel, mTile.getContentDescription(null));
|
||||||
|
|
||||||
|
final String testDreamName = "MyDream";
|
||||||
|
assertEquals(mExpectedTileLabel + ", " + testDreamName,
|
||||||
|
mTile.getContentDescription(testDreamName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setScreensaverEnabled(boolean enabled) {
|
||||||
|
mSecureSettings.putIntForUser(Settings.Secure.SCREENSAVER_ENABLED, enabled ? 1 : 0,
|
||||||
|
DEFAULT_USER);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user