Create a DemoMode controller

Pull Demo Mode out of StatusBar.java and create a subscription /
callback model. This reduces the number of broadcasts needed by
StatusBar and also enables for demo mode:

- clean state tracking (dumpsys DemoModeController)
- We can fix bugs like state initialization (entering demo mode on in
dev options has a different effect than entering via broadcast, etc).
- We can more easily implement it as a command line interface (available
for preorder today!)

Bug: 163393864
Test: atest SystemUITests; manual demo mode testing
Change-Id: I70535aeca3478a42b1ebb668822346e23854379f
This commit is contained in:
Evan Laird
2020-07-29 13:52:23 -04:00
parent 9ecdf744ca
commit 4a05f9ca49
56 changed files with 1325 additions and 579 deletions

View File

@@ -35,6 +35,7 @@ import com.android.systemui.car.volume.CarVolumeDialogComponent;
import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
import com.android.systemui.doze.DozeHost;
@@ -172,10 +173,11 @@ abstract class CarSystemUIModule {
@Singleton
static BatteryController provideBatteryController(Context context,
EnhancedEstimates enhancedEstimates, PowerManager powerManager,
BroadcastDispatcher broadcastDispatcher, @Main Handler mainHandler,
BroadcastDispatcher broadcastDispatcher, DemoModeController demoModeController,
@Main Handler mainHandler,
@Background Handler bgHandler) {
BatteryController bC = new BatteryControllerImpl(context, enhancedEstimates, powerManager,
broadcastDispatcher, mainHandler, bgHandler);
broadcastDispatcher, demoModeController, mainHandler, bgHandler);
bC.init();
return bC;
}

View File

@@ -19,6 +19,7 @@ package com.android.systemui.car.volume;
import android.content.Context;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.VolumeDialog;
import com.android.systemui.volume.VolumeDialogComponent;
@@ -38,8 +39,9 @@ public class CarVolumeDialogComponent extends VolumeDialogComponent {
@Inject
public CarVolumeDialogComponent(Context context, KeyguardViewMediator keyguardViewMediator,
VolumeDialogControllerImpl volumeDialogController,
DemoModeController demoModeController,
CarServiceProvider carServiceProvider) {
super(context, keyguardViewMediator, volumeDialogController);
super(context, keyguardViewMediator, volumeDialogController, demoModeController);
mCarVolumeDialog.setCarServiceProvider(carServiceProvider);
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright (C) 2013 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;
import android.os.Bundle;
public interface DemoMode {
public static final String DEMO_MODE_ALLOWED = "sysui_demo_allowed";
void dispatchDemoCommand(String command, Bundle args);
public static final String ACTION_DEMO = "com.android.systemui.demo";
public static final String EXTRA_COMMAND = "command";
public static final String COMMAND_ENTER = "enter";
public static final String COMMAND_EXIT = "exit";
public static final String COMMAND_CLOCK = "clock";
public static final String COMMAND_BATTERY = "battery";
public static final String COMMAND_NETWORK = "network";
public static final String COMMAND_BARS = "bars";
public static final String COMMAND_STATUS = "status";
public static final String COMMAND_NOTIFICATIONS = "notifications";
public static final String COMMAND_VOLUME = "volume";
public static final String COMMAND_OPERATOR = "operator";
}

View File

@@ -32,6 +32,7 @@ import com.android.systemui.dagger.DaggerGlobalRootComponent;
import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dagger.WMComponent;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -151,12 +152,14 @@ public class SystemUIFactory {
StatusBar statusBar,
NotificationWakeUpCoordinator wakeUpCoordinator,
KeyguardBypassController keyguardBypassController,
StatusBarStateController statusBarStateController) {
StatusBarStateController statusBarStateController,
DemoModeController demoModeController) {
return new NotificationIconAreaController(context, statusBar, statusBarStateController,
wakeUpCoordinator, keyguardBypassController,
Dependency.get(NotificationMediaManager.class),
Dependency.get(NotificationListener.class),
Dependency.get(DozeParameters.class),
Dependency.get(BubbleController.class));
Dependency.get(BubbleController.class),
demoModeController);
}
}

View File

@@ -29,6 +29,7 @@ import com.android.keyguard.KeyguardViewController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
import com.android.systemui.doze.DozeHost;
@@ -99,12 +100,22 @@ public abstract class SystemUIDefaultModule {
@Provides
@Singleton
static BatteryController provideBatteryController(Context context,
EnhancedEstimates enhancedEstimates, PowerManager powerManager,
BroadcastDispatcher broadcastDispatcher, @Main Handler mainHandler,
static BatteryController provideBatteryController(
Context context,
EnhancedEstimates enhancedEstimates,
PowerManager powerManager,
BroadcastDispatcher broadcastDispatcher,
DemoModeController demoModeController,
@Main Handler mainHandler,
@Background Handler bgHandler) {
BatteryController bC = new BatteryControllerImpl(context, enhancedEstimates, powerManager,
broadcastDispatcher, mainHandler, bgHandler);
BatteryController bC = new BatteryControllerImpl(
context,
enhancedEstimates,
powerManager,
broadcastDispatcher,
demoModeController,
mainHandler,
bgHandler);
bC.init();
return bC;
}

View File

@@ -24,6 +24,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.BootCompleteCacheImpl;
import com.android.systemui.assist.AssistModule;
import com.android.systemui.demomode.dagger.DemoModeModule;
import com.android.systemui.doze.dagger.DozeComponent;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.fragments.FragmentService;
@@ -65,6 +66,7 @@ import dagger.Provides;
@Module(includes = {
AssistModule.class,
ConcurrencyModule.class,
DemoModeModule.class,
LogModule.class,
PeopleHubModule.class,
SensorModule.class,

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2020 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.demomode;
import com.google.android.collect.Lists;
import java.util.ArrayList;
import java.util.List;
/**
* Interface defining what it means to implement DemoMode. A DemoMode implementation should
* register with DemoModeController, providing a list of commands for wish to listen.
*
* If you only need to listen to commands, but *do not* care about demo mode state changes, you
* can implement DemoModeCommandReceiver instead
*/
public interface DemoMode extends DemoModeCommandReceiver {
List<String> NO_COMMANDS = new ArrayList<>();
/** Provide a set of commands to listen to, only acceptable values are the COMMAND_* keys */
default List<String> demoCommands() {
return NO_COMMANDS;
}
String ACTION_DEMO = "com.android.systemui.demo";
String EXTRA_COMMAND = "command";
/** Enter and exit are non-register-able; override started/finished to observe these states */
String COMMAND_ENTER = "enter";
String COMMAND_EXIT = "exit";
/** Observable commands to register a listener for */
String COMMAND_CLOCK = "clock";
String COMMAND_BATTERY = "battery";
String COMMAND_NETWORK = "network";
String COMMAND_BARS = "bars";
String COMMAND_STATUS = "status";
String COMMAND_NOTIFICATIONS = "notifications";
String COMMAND_VOLUME = "volume";
String COMMAND_OPERATOR = "operator";
/** New keys need to be added here */
List<String> COMMANDS = Lists.newArrayList(
COMMAND_BARS,
COMMAND_BATTERY,
COMMAND_CLOCK,
COMMAND_NETWORK,
COMMAND_NOTIFICATIONS,
COMMAND_OPERATOR,
COMMAND_STATUS,
COMMAND_VOLUME
);
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2020 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.demomode
import android.content.Context
import android.database.ContentObserver
import android.os.Handler
import android.os.Looper
import android.provider.Settings
/**
* Class to track the availability of [DemoMode]. Use this class to track the availability and
* on/off state for DemoMode
*
* This class works by wrapping a content observer for the relevant keys related to DemoMode
* availability and current on/off state, and triggering callbacks.
*/
abstract class DemoModeAvailabilityTracker(val context: Context) {
var isInDemoMode = false
var isDemoModeAvailable = false
init {
isInDemoMode = checkIsDemoModeOn()
isDemoModeAvailable = checkIsDemoModeAllowed()
}
fun startTracking() {
val resolver = context.contentResolver
resolver.registerContentObserver(
Settings.Global.getUriFor(DEMO_MODE_ALLOWED), false, allowedObserver)
resolver.registerContentObserver(
Settings.Global.getUriFor(DEMO_MODE_ON), false, onObserver)
}
fun stopTracking() {
val resolver = context.contentResolver
resolver.unregisterContentObserver(allowedObserver)
resolver.unregisterContentObserver(onObserver)
}
abstract fun onDemoModeAvailabilityChanged()
abstract fun onDemoModeStarted()
abstract fun onDemoModeFinished()
private fun checkIsDemoModeAllowed(): Boolean {
return Settings.Global
.getInt(context.contentResolver, DEMO_MODE_ALLOWED, 0) != 0
}
private fun checkIsDemoModeOn(): Boolean {
return Settings.Global.getInt(context.contentResolver, DEMO_MODE_ON, 0) != 0
}
private val allowedObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
override fun onChange(selfChange: Boolean) {
val allowed = checkIsDemoModeAllowed()
if (DEBUG) {
android.util.Log.d(TAG, "onChange: DEMO_MODE_ALLOWED changed: $allowed")
}
if (isDemoModeAvailable == allowed) {
return
}
isDemoModeAvailable = allowed
onDemoModeAvailabilityChanged()
}
}
private val onObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
override fun onChange(selfChange: Boolean) {
val on = checkIsDemoModeOn()
if (DEBUG) {
android.util.Log.d(TAG, "onChange: DEMO_MODE_ON changed: $on")
}
if (isInDemoMode == on) {
return
}
isInDemoMode = on
if (on) {
onDemoModeStarted()
} else {
onDemoModeFinished()
}
}
}
}
private const val TAG = "DemoModeAvailabilityTracker"
private const val DEMO_MODE_ALLOWED = "sysui_demo_allowed"
private const val DEMO_MODE_ON = "sysui_tuner_demo_on"
private const val DEBUG = false

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2020 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.demomode;
import android.os.Bundle;
/** Defines the basic DemoMode command interface */
public interface DemoModeCommandReceiver {
/** Override point to observe demo mode commands */
void dispatchDemoCommand(String command, Bundle args);
/**
* Demo mode starts due to receiving [COMMAND_ENTER] or receiving any other demo mode command
* while [DEMO_MODE_ALLOWED] is true but demo mode is off
*/
default void onDemoModeStarted() {}
/** Demo mode exited */
default void onDemoModeFinished() {}
}

View File

@@ -0,0 +1,249 @@
/*
* Copyright (C) 2020 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.demomode
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.os.UserHandle
import android.util.Log
import com.android.systemui.Dumpable
import com.android.systemui.demomode.DemoMode.ACTION_DEMO
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.policy.CallbackController
import com.android.systemui.util.Assert
import com.android.systemui.util.settings.GlobalSettings
import java.io.FileDescriptor
import java.io.PrintWriter
/**
* Handles system broadcasts for [DemoMode]
*
* Injected via [DemoModeModule]
*/
class DemoModeController constructor(
private val context: Context,
private val dumpManager: DumpManager,
private val globalSettings: GlobalSettings
) : CallbackController<DemoMode>, Dumpable {
// Var updated when the availability tracker changes, or when we enter/exit demo mode in-process
var isInDemoMode = false
var isAvailable = false
get() = tracker.isDemoModeAvailable
private var initialized = false
private val receivers = mutableListOf<DemoMode>()
private val receiverMap: Map<String, MutableList<DemoMode>>
init {
val m = mutableMapOf<String, MutableList<DemoMode>>()
DemoMode.COMMANDS.map { command ->
m.put(command, mutableListOf())
}
receiverMap = m
}
fun initialize() {
if (initialized) {
throw IllegalStateException("Already initialized")
}
initialized = true
dumpManager.registerDumpable(TAG, this)
// Due to DemoModeFragment running in systemui:tuner process, we have to observe for
// content changes to know if the setting turned on or off
tracker.startTracking()
// TODO: We should probably exit demo mode if we booted up with it on
isInDemoMode = tracker.isInDemoMode
val demoFilter = IntentFilter()
demoFilter.addAction(ACTION_DEMO)
context.registerReceiverAsUser(broadcastReceiver, UserHandle.ALL, demoFilter,
android.Manifest.permission.DUMP, null)
}
override fun addCallback(listener: DemoMode) {
Assert.isMainThread()
// Register this listener for its commands
val commands = listener.demoCommands()
commands.forEach { command ->
if (!receiverMap.containsKey(command)) {
throw IllegalStateException("Command ($command) not recognized. " +
"See DemoMode.java for valid commands")
}
receiverMap[command]!!.add(listener)
}
receivers.add(listener)
if (isInDemoMode) {
listener.onDemoModeStarted()
}
}
override fun removeCallback(listener: DemoMode) {
Assert.isMainThread()
listener.demoCommands().forEach { command ->
receiverMap[command]!!.remove(listener)
}
receivers.remove(listener)
}
private fun setIsDemoModeAllowed(enabled: Boolean) {
// Turn off demo mode if it was on
if (isInDemoMode && !enabled) {
requestFinishDemoMode()
}
}
private fun enterDemoMode() {
isInDemoMode = true
Assert.isMainThread()
receivers.forEach { r ->
r.onDemoModeStarted()
}
}
private fun exitDemoMode() {
isInDemoMode = false
Assert.isMainThread()
receivers.forEach { r ->
r.onDemoModeFinished()
}
}
fun dispatchDemoCommand(command: String, args: Bundle) {
Assert.isMainThread()
if (DEBUG) {
Log.d(TAG, "dispatchDemoCommand: $command, args=$args")
}
if (!isAvailable) {
return
}
if (command == DemoMode.COMMAND_ENTER) {
enterDemoMode()
} else if (command == DemoMode.COMMAND_EXIT) {
exitDemoMode()
} else if (!isInDemoMode) {
enterDemoMode()
}
// See? demo mode is easy now, you just notify the listeners when their command is called
receiverMap[command]!!.forEach { receiver ->
receiver.dispatchDemoCommand(command, args)
}
}
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
pw.println("DemoModeController state -")
pw.println(" isInDemoMode=$isInDemoMode")
pw.println(" isDemoModeAllowed=$isAvailable")
pw.print(" receivers=[")
receivers.forEach { recv ->
pw.print(" ${recv.javaClass.simpleName}")
}
pw.println(" ]")
pw.println(" receiverMap= [")
receiverMap.keys.forEach { command ->
pw.print(" $command : [")
val recvs = receiverMap[command]!!.map { receiver ->
receiver.javaClass.simpleName
}.joinToString(",")
pw.println("$recvs ]")
}
}
private val tracker = object : DemoModeAvailabilityTracker(context) {
override fun onDemoModeAvailabilityChanged() {
setIsDemoModeAllowed(isDemoModeAvailable)
}
override fun onDemoModeStarted() {
if (this@DemoModeController.isInDemoMode != isInDemoMode) {
enterDemoMode()
}
}
override fun onDemoModeFinished() {
if (this@DemoModeController.isInDemoMode != isInDemoMode) {
exitDemoMode()
}
}
}
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (DEBUG) {
Log.v(TAG, "onReceive: $intent")
}
val action = intent.action
if (!ACTION_DEMO.equals(action)) {
return
}
val bundle = intent.extras ?: return
val command = bundle.getString("command", "").trim().toLowerCase()
if (command.length == 0) {
return
}
try {
dispatchDemoCommand(command, bundle)
} catch (t: Throwable) {
Log.w(TAG, "Error running demo command, intent=$intent $t")
}
}
}
fun requestSetDemoModeAllowed(allowed: Boolean) {
setGlobal(DEMO_MODE_ALLOWED, if (allowed) 1 else 0)
}
fun requestStartDemoMode() {
setGlobal(DEMO_MODE_ON, 1)
}
fun requestFinishDemoMode() {
setGlobal(DEMO_MODE_ON, 0)
}
private fun setGlobal(key: String, value: Int) {
globalSettings.putInt(key, value)
}
}
private const val TAG = "DemoModeController"
private const val DEMO_MODE_ALLOWED = "sysui_demo_allowed"
private const val DEMO_MODE_ON = "sysui_tuner_demo_on"
private const val DEBUG = false

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2020 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.demomode.dagger;
import android.content.Context;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.util.settings.GlobalSettings;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
/**
* Dagger module providing {@link DemoModeController}
*/
@Module
public abstract class DemoModeModule {
/** Provides DemoModeController */
@Provides
@Singleton
static DemoModeController provideDemoModeController(
Context context,
DumpManager dumpManager,
GlobalSettings globalSettings) {
DemoModeController dmc = new DemoModeController(context, dumpManager, globalSettings);
dmc.initialize();
return /*run*/dmc;
}
}

View File

@@ -61,12 +61,18 @@ import android.view.MotionEvent;
import android.view.Surface;
import android.view.accessibility.AccessibilityManager;
import androidx.annotation.NonNull;
import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.util.ScreenshotHelper;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationBar;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.onehanded.OneHandedUI;
import com.android.systemui.pip.PipAnimationController;
import com.android.systemui.pip.PipUI;
@@ -81,10 +87,6 @@ import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationBar;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
@@ -808,7 +810,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
@Override
public void addCallback(OverviewProxyListener listener) {
public void addCallback(@NonNull OverviewProxyListener listener) {
if (!mConnectionCallbacks.contains(listener)) {
mConnectionCallbacks.add(listener);
}
@@ -817,7 +819,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
@Override
public void removeCallback(OverviewProxyListener listener) {
public void removeCallback(@NonNull OverviewProxyListener listener) {
mConnectionCallbacks.remove(listener);
}

View File

@@ -26,6 +26,8 @@ import android.os.CountDownTimer;
import android.os.UserHandle;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.policy.CallbackController;
@@ -191,12 +193,12 @@ public class RecordingController
}
@Override
public void addCallback(RecordingStateChangeCallback listener) {
public void addCallback(@NonNull RecordingStateChangeCallback listener) {
mListeners.add(listener);
}
@Override
public void removeCallback(RecordingStateChangeCallback listener) {
public void removeCallback(@NonNull RecordingStateChangeCallback listener) {
mListeners.remove(listener);
}

View File

@@ -49,6 +49,8 @@ import android.util.SparseArray;
import android.view.InsetsState.InternalInsetsType;
import android.view.WindowInsetsController.Appearance;
import androidx.annotation.NonNull;
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
@@ -391,7 +393,8 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
&& !ONLY_CORE_APPS;
}
public void addCallback(Callbacks callbacks) {
@Override
public void addCallback(@NonNull Callbacks callbacks) {
mCallbacks.add(callbacks);
// TODO(b/117478341): find a better way to pass disable flags by display.
for (int i = 0; i < mDisplayDisabled.size(); i++) {
@@ -402,7 +405,8 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
}
public void removeCallback(Callbacks callbacks) {
@Override
public void removeCallback(@NonNull Callbacks callbacks) {
mCallbacks.remove(callbacks);
}

View File

@@ -28,8 +28,8 @@ import android.widget.TextView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.settingslib.WirelessUtils;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.demomode.DemoModeCommandReceiver;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.policy.NetworkController;
@@ -40,7 +40,8 @@ import com.android.systemui.tuner.TunerService.Tunable;
import java.util.List;
public class OperatorNameView extends TextView implements DemoMode, DarkReceiver,
/** Shows the operator name */
public class OperatorNameView extends TextView implements DemoModeCommandReceiver, DarkReceiver,
SignalCallback, Tunable {
private static final String KEY_SHOW_OPERATOR_NAME = "show_operator_name";
@@ -103,14 +104,18 @@ public class OperatorNameView extends TextView implements DemoMode, DarkReceiver
@Override
public void dispatchDemoCommand(String command, Bundle args) {
if (!mDemoMode && command.equals(COMMAND_ENTER)) {
mDemoMode = true;
} else if (mDemoMode && command.equals(COMMAND_EXIT)) {
mDemoMode = false;
update();
} else if (mDemoMode && command.equals(COMMAND_OPERATOR)) {
setText(args.getString("name"));
}
setText(args.getString("name"));
}
@Override
public void onDemoModeStarted() {
mDemoMode = true;
}
@Override
public void onDemoModeFinished() {
mDemoMode = false;
update();
}
private void update() {

View File

@@ -23,6 +23,8 @@ import android.util.FloatProperty;
import android.util.Log;
import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.DejankUtils;
@@ -276,7 +278,7 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll
}
@Override
public void addCallback(StateListener listener) {
public void addCallback(@NonNull StateListener listener) {
synchronized (mListeners) {
addListenerInternalLocked(listener, Integer.MAX_VALUE);
}
@@ -316,7 +318,7 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll
@Override
public void removeCallback(StateListener listener) {
public void removeCallback(@NonNull StateListener listener) {
synchronized (mListeners) {
mListeners.removeIf((it) -> it.mListener.equals(listener));
}

View File

@@ -27,8 +27,8 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.StatusBarIconView;
@@ -39,7 +39,9 @@ import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconStat
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import java.util.ArrayList;
import java.util.List;
//TODO: This should be a controller, not its own view
public class DemoStatusIcons extends StatusIconContainer implements DemoMode, DarkReceiver {
private static final String TAG = "DemoStatusIcons";
@@ -89,74 +91,85 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
}
}
@Override
public List<String> demoCommands() {
List<String> commands = new ArrayList<>();
commands.add(COMMAND_STATUS);
return commands;
}
@Override
public void onDemoModeStarted() {
mDemoMode = true;
mStatusIcons.setVisibility(View.GONE);
setVisibility(View.VISIBLE);
}
@Override
public void onDemoModeFinished() {
mDemoMode = false;
mStatusIcons.setVisibility(View.VISIBLE);
setVisibility(View.GONE);
}
@Override
public void dispatchDemoCommand(String command, Bundle args) {
if (!mDemoMode && command.equals(COMMAND_ENTER)) {
mDemoMode = true;
mStatusIcons.setVisibility(View.GONE);
setVisibility(View.VISIBLE);
} else if (mDemoMode && command.equals(COMMAND_EXIT)) {
mDemoMode = false;
mStatusIcons.setVisibility(View.VISIBLE);
setVisibility(View.GONE);
} else if (mDemoMode && command.equals(COMMAND_STATUS)) {
String volume = args.getString("volume");
if (volume != null) {
int iconId = volume.equals("vibrate") ? R.drawable.stat_sys_ringer_vibrate
: 0;
updateSlot("volume", null, iconId);
}
String zen = args.getString("zen");
if (zen != null) {
int iconId = zen.equals("dnd") ? R.drawable.stat_sys_dnd : 0;
updateSlot("zen", null, iconId);
}
String bt = args.getString("bluetooth");
if (bt != null) {
int iconId = bt.equals("connected")
? R.drawable.stat_sys_data_bluetooth_connected : 0;
updateSlot("bluetooth", null, iconId);
}
String location = args.getString("location");
if (location != null) {
int iconId = location.equals("show") ? PhoneStatusBarPolicy.LOCATION_STATUS_ICON_ID
: 0;
updateSlot("location", null, iconId);
}
String alarm = args.getString("alarm");
if (alarm != null) {
int iconId = alarm.equals("show") ? R.drawable.stat_sys_alarm
: 0;
updateSlot("alarm_clock", null, iconId);
}
String tty = args.getString("tty");
if (tty != null) {
int iconId = tty.equals("show") ? R.drawable.stat_sys_tty_mode
: 0;
updateSlot("tty", null, iconId);
}
String mute = args.getString("mute");
if (mute != null) {
int iconId = mute.equals("show") ? android.R.drawable.stat_notify_call_mute
: 0;
updateSlot("mute", null, iconId);
}
String speakerphone = args.getString("speakerphone");
if (speakerphone != null) {
int iconId = speakerphone.equals("show") ? android.R.drawable.stat_sys_speakerphone
: 0;
updateSlot("speakerphone", null, iconId);
}
String cast = args.getString("cast");
if (cast != null) {
int iconId = cast.equals("show") ? R.drawable.stat_sys_cast : 0;
updateSlot("cast", null, iconId);
}
String hotspot = args.getString("hotspot");
if (hotspot != null) {
int iconId = hotspot.equals("show") ? R.drawable.stat_sys_hotspot : 0;
updateSlot("hotspot", null, iconId);
}
String volume = args.getString("volume");
if (volume != null) {
int iconId = volume.equals("vibrate") ? R.drawable.stat_sys_ringer_vibrate
: 0;
updateSlot("volume", null, iconId);
}
String zen = args.getString("zen");
if (zen != null) {
int iconId = zen.equals("dnd") ? R.drawable.stat_sys_dnd : 0;
updateSlot("zen", null, iconId);
}
String bt = args.getString("bluetooth");
if (bt != null) {
int iconId = bt.equals("connected")
? R.drawable.stat_sys_data_bluetooth_connected : 0;
updateSlot("bluetooth", null, iconId);
}
String location = args.getString("location");
if (location != null) {
int iconId = location.equals("show") ? PhoneStatusBarPolicy.LOCATION_STATUS_ICON_ID
: 0;
updateSlot("location", null, iconId);
}
String alarm = args.getString("alarm");
if (alarm != null) {
int iconId = alarm.equals("show") ? R.drawable.stat_sys_alarm
: 0;
updateSlot("alarm_clock", null, iconId);
}
String tty = args.getString("tty");
if (tty != null) {
int iconId = tty.equals("show") ? R.drawable.stat_sys_tty_mode
: 0;
updateSlot("tty", null, iconId);
}
String mute = args.getString("mute");
if (mute != null) {
int iconId = mute.equals("show") ? android.R.drawable.stat_notify_call_mute
: 0;
updateSlot("mute", null, iconId);
}
String speakerphone = args.getString("speakerphone");
if (speakerphone != null) {
int iconId = speakerphone.equals("show") ? android.R.drawable.stat_sys_speakerphone
: 0;
updateSlot("speakerphone", null, iconId);
}
String cast = args.getString("cast");
if (cast != null) {
int iconId = cast.equals("show") ? R.drawable.stat_sys_cast : 0;
updateSlot("cast", null, iconId);
}
String hotspot = args.getString("hotspot");
if (hotspot != null) {
int iconId = hotspot.equals("show") ? R.drawable.stat_sys_hotspot : 0;
updateSlot("hotspot", null, iconId);
}
}

View File

@@ -24,6 +24,8 @@ import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.annotation.NonNull;
import com.android.systemui.broadcast.BroadcastDispatcher;
import java.util.ArrayList;
@@ -57,7 +59,8 @@ public class ManagedProfileControllerImpl implements ManagedProfileController {
mProfiles = new LinkedList<UserInfo>();
}
public void addCallback(Callback callback) {
@Override
public void addCallback(@NonNull Callback callback) {
mCallbacks.add(callback);
if (mCallbacks.size() == 1) {
setListening(true);
@@ -65,7 +68,8 @@ public class ManagedProfileControllerImpl implements ManagedProfileController {
callback.onManagedProfileChanged();
}
public void removeCallback(Callback callback) {
@Override
public void removeCallback(@NonNull Callback callback) {
if (mCallbacks.remove(callback) && mCallbacks.size() == 0) {
setListening(false);
}

View File

@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -20,6 +21,8 @@ import com.android.settingslib.Utils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -35,6 +38,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
@@ -44,7 +48,8 @@ import java.util.function.Function;
*/
public class NotificationIconAreaController implements DarkReceiver,
StatusBarStateController.StateListener,
NotificationWakeUpCoordinator.WakeUpListener {
NotificationWakeUpCoordinator.WakeUpListener,
DemoMode {
public static final String HIGH_PRIORITY = "high_priority";
private static final long AOD_ICONS_APPEAR_DURATION = 200;
@@ -74,6 +79,8 @@ public class NotificationIconAreaController implements DarkReceiver,
private final Rect mTintArea = new Rect();
private ViewGroup mNotificationScrollLayout;
private Context mContext;
private final DemoModeController mDemoModeController;
private int mAodIconAppearTranslation;
private boolean mAnimationsEnabled;
@@ -104,7 +111,8 @@ public class NotificationIconAreaController implements DarkReceiver,
NotificationMediaManager notificationMediaManager,
NotificationListener notificationListener,
DozeParameters dozeParameters,
BubbleController bubbleController) {
BubbleController bubbleController,
DemoModeController demoModeController) {
mStatusBar = statusBar;
mContrastColorUtil = ContrastColorUtil.getInstance(context);
mContext = context;
@@ -117,6 +125,8 @@ public class NotificationIconAreaController implements DarkReceiver,
mBypassController = keyguardBypassController;
mBubbleController = bubbleController;
notificationListener.addNotificationSettingsListener(mSettingsListener);
mDemoModeController = demoModeController;
mDemoModeController.addCallback(this);
initializeNotificationAreaViews(context);
reloadAodColor();
@@ -666,4 +676,27 @@ public class NotificationIconAreaController implements DarkReceiver,
}
}
}
@Override
public List<String> demoCommands() {
ArrayList<String> commands = new ArrayList<>();
commands.add(DemoMode.COMMAND_NOTIFICATIONS);
return commands;
}
@Override
public void dispatchDemoCommand(String command, Bundle args) {
if (mNotificationIconArea != null) {
String visible = args.getString("visible");
int vis = "false".equals(visible) ? View.INVISIBLE : View.VISIBLE;
mNotificationIconArea.setVisibility(vis);
}
}
@Override
public void onDemoModeFinished() {
if (mNotificationIconArea != null) {
mNotificationIconArea.setVisibility(View.VISIBLE);
}
}
}

View File

@@ -138,7 +138,6 @@ import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.AutoReinflateContainer;
import com.android.systemui.DejankUtils;
import com.android.systemui.DemoMode;
import com.android.systemui.Dumpable;
import com.android.systemui.EventLogTags;
import com.android.systemui.InitController;
@@ -153,12 +152,16 @@ import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeCommandReceiver;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.fragments.ExtensionFragmentListener;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
@@ -183,7 +186,6 @@ import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.KeyboardShortcuts;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
@@ -233,6 +235,8 @@ import com.android.systemui.volume.VolumeComponent;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -397,6 +401,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final ExtensionController mExtensionController;
private final UserInfoControllerImpl mUserInfoControllerImpl;
private final DismissCallbackRegistry mDismissCallbackRegistry;
private final DemoModeController mDemoModeController;
private NotificationsController mNotificationsController;
// expanded notifications
@@ -734,6 +739,7 @@ public class StatusBar extends SystemUI implements DemoMode,
PhoneStatusBarPolicy phoneStatusBarPolicy,
KeyguardIndicationController keyguardIndicationController,
DismissCallbackRegistry dismissCallbackRegistry,
DemoModeController demoModeController,
Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
super(context);
@@ -812,6 +818,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mUserInfoControllerImpl = userInfoControllerImpl;
mIconPolicy = phoneStatusBarPolicy;
mDismissCallbackRegistry = dismissCallbackRegistry;
mDemoModeController = demoModeController;
mBubbleExpandListener =
(isExpanding, key) -> {
@@ -866,6 +873,9 @@ public class StatusBar extends SystemUI implements DemoMode,
// Connect in to the status bar manager service
mCommandQueue.addCallback(this);
// Listen for demo mode changes
mDemoModeController.addCallback(this);
RegisterStatusBarResult result = null;
try {
result = mBarService.registerStatusBar(mCommandQueue);
@@ -1031,7 +1041,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationIconAreaController = SystemUIFactory.getInstance()
.createNotificationIconAreaController(context, this,
mWakeUpCoordinator, mKeyguardBypassController,
mStatusBarStateController);
mStatusBarStateController, mDemoModeController);
mWakeUpCoordinator.setIconAreaController(mNotificationIconAreaController);
inflateShelf();
mNotificationIconAreaController.setupShelf(mNotificationShelfController);
@@ -1254,7 +1264,6 @@ public class StatusBar extends SystemUI implements DemoMode,
if (DEBUG_MEDIA_FAKE_ARTWORK) {
demoFilter.addAction(ACTION_FAKE_ARTWORK);
}
demoFilter.addAction(ACTION_DEMO);
context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
android.Manifest.permission.DUMP, null);
@@ -2440,7 +2449,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public void checkBarModes() {
if (mDemoMode) return;
if (mDemoModeController.isInDemoMode()) return;
if (mNotificationShadeWindowViewController != null && getStatusBarTransitions() != null) {
checkBarMode(mStatusBarMode, mStatusBarWindowState, getStatusBarTransitions());
}
@@ -2813,19 +2822,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.v(TAG, "onReceive: " + intent);
String action = intent.getAction();
if (ACTION_DEMO.equals(action)) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
String command = bundle.getString("command", "").trim().toLowerCase();
if (command.length() > 0) {
try {
dispatchDemoCommand(command, bundle);
} catch (Throwable t) {
Log.w(TAG, "Error running demo command, intent=" + intent, t);
}
}
}
} else if (ACTION_FAKE_ARTWORK.equals(action)) {
if (ACTION_FAKE_ARTWORK.equals(action)) {
if (DEBUG_MEDIA_FAKE_ARTWORK) {
mPresenter.updateMediaMetaData(true, true);
}
@@ -3089,50 +3086,34 @@ public class StatusBar extends SystemUI implements DemoMode,
startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */);
}
private boolean mDemoModeAllowed;
private boolean mDemoMode;
@Override
public List<String> demoCommands() {
List<String> s = new ArrayList<>();
s.add(DemoMode.COMMAND_BARS);
s.add(DemoMode.COMMAND_CLOCK);
s.add(DemoMode.COMMAND_OPERATOR);
return s;
}
@Override
public void dispatchDemoCommand(String command, Bundle args) {
if (!mDemoModeAllowed) {
mDemoModeAllowed = Settings.Global.getInt(mContext.getContentResolver(),
DEMO_MODE_ALLOWED, 0) != 0;
}
if (!mDemoModeAllowed) return;
if (command.equals(COMMAND_ENTER)) {
mDemoMode = true;
} else if (command.equals(COMMAND_EXIT)) {
mDemoMode = false;
checkBarModes();
} else if (!mDemoMode) {
// automatically enter demo mode on first demo command
dispatchDemoCommand(COMMAND_ENTER, new Bundle());
}
boolean modeChange = command.equals(COMMAND_ENTER) || command.equals(COMMAND_EXIT);
if ((modeChange || command.equals(COMMAND_VOLUME)) && mVolumeComponent != null) {
mVolumeComponent.dispatchDemoCommand(command, args);
}
if (modeChange || command.equals(COMMAND_CLOCK)) {
public void onDemoModeStarted() {
// Must send this message to any view that we delegate to via dispatchDemoCommandToView
dispatchDemoModeStartedToView(R.id.clock);
dispatchDemoModeStartedToView(R.id.operator_name);
}
@Override
public void onDemoModeFinished() {
dispatchDemoModeFinishedToView(R.id.clock);
dispatchDemoModeFinishedToView(R.id.operator_name);
checkBarModes();
}
@Override
public void dispatchDemoCommand(String command, @NonNull Bundle args) {
if (command.equals(COMMAND_CLOCK)) {
dispatchDemoCommandToView(command, args, R.id.clock);
}
if (modeChange || command.equals(COMMAND_BATTERY)) {
mBatteryController.dispatchDemoCommand(command, args);
}
if (modeChange || command.equals(COMMAND_STATUS)) {
((StatusBarIconControllerImpl) mIconController).dispatchDemoCommand(command, args);
}
if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) {
mNetworkController.dispatchDemoCommand(command, args);
}
if (modeChange || command.equals(COMMAND_NOTIFICATIONS)) {
View notifications = mStatusBarView == null ? null
: mStatusBarView.findViewById(R.id.notification_icon_area);
if (notifications != null) {
String visible = args.getString("visible");
int vis = mDemoMode && "false".equals(visible) ? View.INVISIBLE : View.VISIBLE;
notifications.setVisibility(vis);
}
}
if (command.equals(COMMAND_BARS)) {
String mode = args.getString("mode");
int barMode = "opaque".equals(mode) ? MODE_OPAQUE :
@@ -3151,16 +3132,33 @@ public class StatusBar extends SystemUI implements DemoMode,
mNavigationBarController.transitionTo(mDisplayId, barMode, animate);
}
}
if (modeChange || command.equals(COMMAND_OPERATOR)) {
if (command.equals(COMMAND_OPERATOR)) {
dispatchDemoCommandToView(command, args, R.id.operator_name);
}
}
//TODO: these should have controllers, and this method should be removed
private void dispatchDemoCommandToView(String command, Bundle args, int id) {
if (mStatusBarView == null) return;
View v = mStatusBarView.findViewById(id);
if (v instanceof DemoMode) {
((DemoMode)v).dispatchDemoCommand(command, args);
if (v instanceof DemoModeCommandReceiver) {
((DemoModeCommandReceiver) v).dispatchDemoCommand(command, args);
}
}
private void dispatchDemoModeStartedToView(int id) {
if (mStatusBarView == null) return;
View v = mStatusBarView.findViewById(id);
if (v instanceof DemoModeCommandReceiver) {
((DemoModeCommandReceiver) v).onDemoModeStarted();
}
}
private void dispatchDemoModeFinishedToView(int id) {
if (mStatusBarView == null) return;
View v = mStatusBarView.findViewById(id);
if (v instanceof DemoModeCommandReceiver) {
((DemoModeCommandReceiver) v).onDemoModeFinished();
}
}

View File

@@ -32,9 +32,9 @@ import android.widget.LinearLayout.LayoutParams;
import androidx.annotation.VisibleForTesting;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.demomode.DemoModeCommandReceiver;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.CommandQueue;
@@ -198,7 +198,7 @@ public interface StatusBarIconController {
/**
* Turns info from StatusBarIconController into ImageViews in a ViewGroup.
*/
public static class IconManager implements DemoMode {
class IconManager implements DemoModeCommandReceiver {
protected final ViewGroup mGroup;
protected final Context mContext;
protected final int mIconSize;
@@ -390,18 +390,24 @@ public interface StatusBarIconController {
return;
}
if (command.equals(COMMAND_EXIT)) {
if (mDemoStatusIcons != null) {
mDemoStatusIcons.dispatchDemoCommand(command, args);
exitDemoMode();
}
mDemoStatusIcons.dispatchDemoCommand(command, args);
}
@Override
public void onDemoModeStarted() {
mIsInDemoMode = true;
if (mDemoStatusIcons == null) {
mDemoStatusIcons = createDemoStatusIcons();
}
mDemoStatusIcons.onDemoModeStarted();
}
@Override
public void onDemoModeFinished() {
if (mDemoStatusIcons != null) {
mDemoStatusIcons.onDemoModeFinished();
exitDemoMode();
mIsInDemoMode = false;
} else {
if (mDemoStatusIcons == null) {
mIsInDemoMode = true;
mDemoStatusIcons = createDemoStatusIcons();
}
mDemoStatusIcons.dispatchDemoCommand(command, args);
}
}

View File

@@ -29,6 +29,8 @@ import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
@@ -54,22 +56,20 @@ import javax.inject.Singleton;
*/
@Singleton
public class StatusBarIconControllerImpl extends StatusBarIconList implements Tunable,
ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController {
ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController, DemoMode {
private static final String TAG = "StatusBarIconController";
private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
private final ArraySet<String> mIconHideList = new ArraySet<>();
// Points to light or dark context depending on the... context?
private Context mContext;
private Context mLightContext;
private Context mDarkContext;
private boolean mIsDark = false;
@Inject
public StatusBarIconControllerImpl(Context context, CommandQueue commandQueue) {
public StatusBarIconControllerImpl(
Context context,
CommandQueue commandQueue,
DemoModeController demoModeController) {
super(context.getResources().getStringArray(
com.android.internal.R.array.config_statusBarIcons));
Dependency.get(ConfigurationController.class).addCallback(this);
@@ -80,6 +80,7 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
commandQueue.addCallback(this);
Dependency.get(TunerService.class).addTunable(this, ICON_HIDE_LIST);
demoModeController.addCallback(this);
}
@Override
@@ -339,6 +340,25 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
super.dump(pw);
}
@Override
public void onDemoModeStarted() {
for (IconManager manager : mIconGroups) {
if (manager.isDemoable()) {
manager.onDemoModeStarted();
}
}
}
@Override
public void onDemoModeFinished() {
for (IconManager manager : mIconGroups) {
if (manager.isDemoable()) {
manager.onDemoModeFinished();
}
}
}
@Override
public void dispatchDemoCommand(String command, Bundle args) {
for (IconManager manager : mIconGroups) {
if (manager.isDemoable()) {
@@ -347,6 +367,13 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
}
}
@Override
public List<String> demoCommands() {
List<String> s = new ArrayList<>();
s.add(DemoMode.COMMAND_STATUS);
return s;
}
@Override
public void onDensityOrFontScaleChanged() {
loadDimens();

View File

@@ -34,10 +34,12 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginDependencyProvider;
@@ -47,7 +49,6 @@ import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -196,6 +197,7 @@ public interface StatusBarPhoneModule {
UserInfoControllerImpl userInfoControllerImpl,
PhoneStatusBarPolicy phoneStatusBarPolicy,
KeyguardIndicationController keyguardIndicationController,
DemoModeController demoModeController,
Lazy<NotificationShadeDepthController> notificationShadeDepthController,
DismissCallbackRegistry dismissCallbackRegistry,
StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
@@ -275,6 +277,7 @@ public interface StatusBarPhoneModule {
phoneStatusBarPolicy,
keyguardIndicationController,
dismissCallbackRegistry,
demoModeController,
notificationShadeDepthController,
statusBarTouchableRegionManager);
}

View File

@@ -19,6 +19,8 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
import androidx.annotation.NonNull;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -37,12 +39,12 @@ public class AccessibilityManagerWrapper implements
}
@Override
public void addCallback(AccessibilityServicesStateChangeListener listener) {
public void addCallback(@NonNull AccessibilityServicesStateChangeListener listener) {
mAccessibilityManager.addAccessibilityServicesStateChangeListener(listener, null);
}
@Override
public void removeCallback(AccessibilityServicesStateChangeListener listener) {
public void removeCallback(@NonNull AccessibilityServicesStateChangeListener listener) {
mAccessibilityManager.removeAccessibilityServicesStateChangeListener(listener);
}

View File

@@ -18,8 +18,8 @@ package com.android.systemui.statusbar.policy;
import android.annotation.Nullable;
import com.android.systemui.DemoMode;
import com.android.systemui.Dumpable;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import java.io.FileDescriptor;

View File

@@ -27,6 +27,7 @@ import android.os.PowerManager;
import android.os.PowerSaveState;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
@@ -36,11 +37,14 @@ import com.android.settingslib.utils.PowerUtil;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.power.EnhancedEstimates;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -63,6 +67,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
mChangeCallbacks = new ArrayList<>();
private final ArrayList<EstimateFetchCompletion> mFetchCallbacks = new ArrayList<>();
private final PowerManager mPowerManager;
private final DemoModeController mDemoModeController;
private final Handler mMainHandler;
private final Handler mBgHandler;
protected final Context mContext;
@@ -82,15 +87,21 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
@VisibleForTesting
@Inject
public BatteryControllerImpl(Context context, EnhancedEstimates enhancedEstimates,
PowerManager powerManager, BroadcastDispatcher broadcastDispatcher,
@Main Handler mainHandler, @Background Handler bgHandler) {
public BatteryControllerImpl(
Context context,
EnhancedEstimates enhancedEstimates,
PowerManager powerManager,
BroadcastDispatcher broadcastDispatcher,
DemoModeController demoModeController,
@Main Handler mainHandler,
@Background Handler bgHandler) {
mContext = context;
mMainHandler = mainHandler;
mBgHandler = bgHandler;
mPowerManager = powerManager;
mEstimates = enhancedEstimates;
mBroadcastDispatcher = broadcastDispatcher;
mDemoModeController = demoModeController;
}
private void registerReceiver() {
@@ -114,6 +125,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
onReceive(mContext, intent);
}
}
mDemoModeController.addCallback(this);
updatePowerSave();
updateEstimate();
}
@@ -134,7 +146,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
}
@Override
public void addCallback(BatteryController.BatteryStateChangeCallback cb) {
public void addCallback(@NonNull BatteryController.BatteryStateChangeCallback cb) {
synchronized (mChangeCallbacks) {
mChangeCallbacks.add(cb);
}
@@ -144,7 +156,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
}
@Override
public void removeCallback(BatteryController.BatteryStateChangeCallback cb) {
public void removeCallback(@NonNull BatteryController.BatteryStateChangeCallback cb) {
synchronized (mChangeCallbacks) {
mChangeCallbacks.remove(cb);
}
@@ -325,32 +337,43 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
}
}
private boolean mDemoMode;
@Override
public void dispatchDemoCommand(String command, Bundle args) {
if (!mDemoMode && command.equals(COMMAND_ENTER)) {
mDemoMode = true;
mBroadcastDispatcher.unregisterReceiver(this);
} else if (mDemoMode && command.equals(COMMAND_EXIT)) {
mDemoMode = false;
registerReceiver();
updatePowerSave();
} else if (mDemoMode && command.equals(COMMAND_BATTERY)) {
String level = args.getString("level");
String plugged = args.getString("plugged");
String powerSave = args.getString("powersave");
if (level != null) {
mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
}
if (plugged != null) {
mPluggedIn = Boolean.parseBoolean(plugged);
}
if (powerSave != null) {
mPowerSave = powerSave.equals("true");
firePowerSaveChanged();
}
fireBatteryLevelChanged();
if (!mDemoModeController.isInDemoMode()) {
return;
}
String level = args.getString("level");
String plugged = args.getString("plugged");
String powerSave = args.getString("powersave");
if (level != null) {
mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
}
if (plugged != null) {
mPluggedIn = Boolean.parseBoolean(plugged);
}
if (powerSave != null) {
mPowerSave = powerSave.equals("true");
firePowerSaveChanged();
}
fireBatteryLevelChanged();
}
@Override
public List<String> demoCommands() {
List<String> s = new ArrayList<>();
s.add(DemoMode.COMMAND_BATTERY);
return s;
}
@Override
public void onDemoModeStarted() {
mBroadcastDispatcher.unregisterReceiver(this);
}
@Override
public void onDemoModeFinished() {
registerReceiver();
updatePowerSave();
}
}

View File

@@ -29,6 +29,8 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -150,13 +152,13 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
}
@Override
public void addCallback(Callback cb) {
public void addCallback(@NonNull Callback cb) {
mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget();
mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
}
@Override
public void removeCallback(Callback cb) {
public void removeCallback(@NonNull Callback cb) {
mHandler.obtainMessage(H.MSG_REMOVE_CALLBACK, cb).sendToTarget();
}

View File

@@ -123,13 +123,13 @@ public class BrightnessMirrorController
}
@Override
public void addCallback(BrightnessMirrorListener listener) {
public void addCallback(@NonNull BrightnessMirrorListener listener) {
Objects.requireNonNull(listener);
mBrightnessMirrorListeners.add(listener);
}
@Override
public void removeCallback(BrightnessMirrorListener listener) {
public void removeCallback(@NonNull BrightnessMirrorListener listener) {
mBrightnessMirrorListeners.remove(listener);
}

View File

@@ -15,14 +15,19 @@
package com.android.systemui.statusbar.policy;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.Lifecycle.Event;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;
public interface CallbackController<T> {
void addCallback(T listener);
void removeCallback(T listener);
/** Add a callback */
void addCallback(@NonNull T listener);
/** Remove a callback */
void removeCallback(@NonNull T listener);
/**
* Wrapper to {@link #addCallback(Object)} when a lifecycle is in the resumed state

View File

@@ -31,6 +31,7 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.internal.annotations.GuardedBy;
@@ -95,7 +96,7 @@ public class CastControllerImpl implements CastController {
}
@Override
public void addCallback(Callback callback) {
public void addCallback(@NonNull Callback callback) {
synchronized (mCallbacks) {
mCallbacks.add(callback);
}
@@ -106,7 +107,7 @@ public class CastControllerImpl implements CastController {
}
@Override
public void removeCallback(Callback callback) {
public void removeCallback(@NonNull Callback callback) {
synchronized (mCallbacks) {
mCallbacks.remove(callback);
}

View File

@@ -40,11 +40,11 @@ import android.view.View;
import android.widget.TextView;
import com.android.settingslib.Utils;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.demomode.DemoModeCommandReceiver;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.settings.CurrentUserTracker;
@@ -62,7 +62,10 @@ import java.util.TimeZone;
/**
* Digital clock for the status bar.
*/
public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.Callbacks,
public class Clock extends TextView implements
DemoModeCommandReceiver,
Tunable,
CommandQueue.Callbacks,
DarkReceiver, ConfigurationListener {
public static final String CLOCK_SECONDS = "clock_seconds";
@@ -467,30 +470,35 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C
@Override
public void dispatchDemoCommand(String command, Bundle args) {
if (!mDemoMode && command.equals(COMMAND_ENTER)) {
mDemoMode = true;
} else if (mDemoMode && command.equals(COMMAND_EXIT)) {
mDemoMode = false;
updateClock();
} else if (mDemoMode && command.equals(COMMAND_CLOCK)) {
String millis = args.getString("millis");
String hhmm = args.getString("hhmm");
if (millis != null) {
mCalendar.setTimeInMillis(Long.parseLong(millis));
} else if (hhmm != null && hhmm.length() == 4) {
int hh = Integer.parseInt(hhmm.substring(0, 2));
int mm = Integer.parseInt(hhmm.substring(2));
boolean is24 = DateFormat.is24HourFormat(getContext(), mCurrentUserId);
if (is24) {
mCalendar.set(Calendar.HOUR_OF_DAY, hh);
} else {
mCalendar.set(Calendar.HOUR, hh);
}
mCalendar.set(Calendar.MINUTE, mm);
// Only registered for COMMAND_CLOCK
String millis = args.getString("millis");
String hhmm = args.getString("hhmm");
if (millis != null) {
mCalendar.setTimeInMillis(Long.parseLong(millis));
} else if (hhmm != null && hhmm.length() == 4) {
int hh = Integer.parseInt(hhmm.substring(0, 2));
int mm = Integer.parseInt(hhmm.substring(2));
boolean is24 = DateFormat.is24HourFormat(getContext(), mCurrentUserId);
if (is24) {
mCalendar.set(Calendar.HOUR_OF_DAY, hh);
} else {
mCalendar.set(Calendar.HOUR, hh);
}
setText(getSmallTime());
setContentDescription(mContentDescriptionFormat.format(mCalendar.getTime()));
mCalendar.set(Calendar.MINUTE, mm);
}
setText(getSmallTime());
setContentDescription(mContentDescriptionFormat.format(mCalendar.getTime()));
}
@Override
public void onDemoModeStarted() {
mDemoMode = true;
}
@Override
public void onDemoModeFinished() {
mDemoMode = false;
updateClock();
}
private final BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {

View File

@@ -21,6 +21,8 @@ import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import androidx.annotation.NonNull;
import java.util.ArrayList;
public class DataSaverControllerImpl implements DataSaverController {
@@ -41,7 +43,8 @@ public class DataSaverControllerImpl implements DataSaverController {
}
}
public void addCallback(Listener listener) {
@Override
public void addCallback(@NonNull Listener listener) {
synchronized (mListeners) {
mListeners.add(listener);
if (mListeners.size() == 1) {
@@ -51,7 +54,8 @@ public class DataSaverControllerImpl implements DataSaverController {
listener.onDataSaverChanged(isDataSaverEnabled());
}
public void removeCallback(Listener listener) {
@Override
public void removeCallback(@NonNull Listener listener) {
synchronized (mListeners) {
mListeners.remove(listener);
if (mListeners.size() == 0) {

View File

@@ -24,6 +24,8 @@ import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.settings.CurrentUserTracker;
@@ -87,7 +89,7 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
}
@Override
public void addCallback(DeviceProvisionedListener listener) {
public void addCallback(@NonNull DeviceProvisionedListener listener) {
mListeners.add(listener);
if (mListeners.size() == 1) {
startListening(getCurrentUser());
@@ -97,7 +99,7 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
}
@Override
public void removeCallback(DeviceProvisionedListener listener) {
public void removeCallback(@NonNull DeviceProvisionedListener listener) {
mListeners.remove(listener);
if (mListeners.size() == 0) {
stopListening();

View File

@@ -30,6 +30,8 @@ import android.provider.Settings.Secure;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -123,7 +125,8 @@ public class FlashlightControllerImpl implements FlashlightController {
return mTorchAvailable;
}
public void addCallback(FlashlightListener l) {
@Override
public void addCallback(@NonNull FlashlightListener l) {
synchronized (mListeners) {
if (mCameraId == null) {
tryInitCamera();
@@ -135,7 +138,8 @@ public class FlashlightControllerImpl implements FlashlightController {
}
}
public void removeCallback(FlashlightListener l) {
@Override
public void removeCallback(@NonNull FlashlightListener l) {
synchronized (mListeners) {
cleanUpListenersLocked(l);
}

View File

@@ -30,6 +30,8 @@ import android.os.HandlerExecutor;
import android.os.UserManager;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.internal.util.ConcurrentUtils;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
@@ -143,7 +145,7 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof
* changes. It will immediately trigger the callback added to notify current state.
*/
@Override
public void addCallback(Callback callback) {
public void addCallback(@NonNull Callback callback) {
synchronized (mCallbacks) {
if (callback == null || mCallbacks.contains(callback)) return;
if (DEBUG) Log.d(TAG, "addCallback " + callback);
@@ -163,7 +165,7 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof
}
@Override
public void removeCallback(Callback callback) {
public void removeCallback(@NonNull Callback callback) {
if (callback == null) return;
if (DEBUG) Log.d(TAG, "removeCallback " + callback);
synchronized (mCallbacks) {

View File

@@ -33,6 +33,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.systemui.BootCompleteCache;
@@ -87,12 +88,14 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
/**
* Add a callback to listen for changes in location settings.
*/
public void addCallback(LocationChangeCallback cb) {
@Override
public void addCallback(@NonNull LocationChangeCallback cb) {
mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget();
mHandler.sendEmptyMessage(H.MSG_LOCATION_SETTINGS_CHANGED);
}
public void removeCallback(LocationChangeCallback cb) {
@Override
public void removeCallback(@NonNull LocationChangeCallback cb) {
mHandler.obtainMessage(H.MSG_REMOVE_CALLBACK, cb).sendToTarget();
}

View File

@@ -22,7 +22,7 @@ import android.telephony.SubscriptionInfo;
import com.android.settingslib.net.DataUsageController;
import com.android.settingslib.wifi.AccessPoint;
import com.android.systemui.DemoMode;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.util.List;
@@ -30,8 +30,6 @@ import java.util.List;
public interface NetworkController extends CallbackController<SignalCallback>, DemoMode {
boolean hasMobileDataFeature();
void addCallback(SignalCallback cb);
void removeCallback(SignalCallback cb);
void setWifiEnabled(boolean enabled);
AccessPointController getAccessPointController();
DataUsageController getMobileDataController();

View File

@@ -55,14 +55,17 @@ import android.util.Log;
import android.util.MathUtils;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.DemoMode;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
@@ -104,6 +107,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
private final DataSaverController mDataSaverController;
private final CurrentUserTracker mUserTracker;
private final BroadcastDispatcher mBroadcastDispatcher;
private final DemoModeController mDemoModeController;
private final Object mLock = new Object();
private Config mConfig;
@@ -173,11 +177,16 @@ public class NetworkControllerImpl extends BroadcastReceiver
* Construct this controller object and register for updates.
*/
@Inject
public NetworkControllerImpl(Context context, @Background Looper bgLooper,
public NetworkControllerImpl(
Context context,
@Background Looper bgLooper,
DeviceProvisionedController deviceProvisionedController,
BroadcastDispatcher broadcastDispatcher, ConnectivityManager connectivityManager,
TelephonyManager telephonyManager, @Nullable WifiManager wifiManager,
NetworkScoreManager networkScoreManager) {
BroadcastDispatcher broadcastDispatcher,
ConnectivityManager connectivityManager,
TelephonyManager telephonyManager,
@Nullable WifiManager wifiManager,
NetworkScoreManager networkScoreManager,
DemoModeController demoModeController) {
this(context, connectivityManager,
telephonyManager,
wifiManager,
@@ -188,7 +197,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
new DataUsageController(context),
new SubscriptionDefaults(),
deviceProvisionedController,
broadcastDispatcher);
broadcastDispatcher,
demoModeController);
mReceiverHandler.post(mRegisterListeners);
}
@@ -202,7 +212,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
DataUsageController dataUsageController,
SubscriptionDefaults defaultsHandler,
DeviceProvisionedController deviceProvisionedController,
BroadcastDispatcher broadcastDispatcher) {
BroadcastDispatcher broadcastDispatcher,
DemoModeController demoModeController) {
mContext = context;
mConfig = config;
mReceiverHandler = new Handler(bgLooper);
@@ -215,6 +226,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
mConnectivityManager = connectivityManager;
mHasMobileDataFeature =
mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
mDemoModeController = demoModeController;
// telephony
mPhone = telephonyManager;
@@ -306,6 +318,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
doUpdateMobileControllers();
}
};
mDemoModeController.addCallback(this);
}
private final Runnable mClearForceValidated = () -> {
@@ -514,7 +528,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
mCallbackHandler.setEmergencyCallsOnly(mIsEmergency);
}
public void addCallback(SignalCallback cb) {
@Override
public void addCallback(@NonNull SignalCallback cb) {
cb.setSubs(mCurrentSubscriptions);
cb.setIsAirplaneMode(new IconState(mAirplaneMode,
TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
@@ -529,7 +544,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
@Override
public void removeCallback(SignalCallback cb) {
public void removeCallback(@NonNull SignalCallback cb) {
mCallbackHandler.setListening(cb, false);
}
@@ -932,203 +947,215 @@ public class NetworkControllerImpl extends BroadcastReceiver
return "UNKNOWN_SOURCE";
}
private boolean mDemoMode;
private boolean mDemoInetCondition;
private WifiSignalController.WifiState mDemoWifiState;
@Override
public void onDemoModeStarted() {
if (DEBUG) Log.d(TAG, "Entering demo mode");
unregisterListeners();
mDemoInetCondition = mInetCondition;
mDemoWifiState = mWifiSignalController.getState();
mDemoWifiState.ssid = "DemoMode";
}
@Override
public void onDemoModeFinished() {
if (DEBUG) Log.d(TAG, "Exiting demo mode");
// Update what MobileSignalControllers, because they may change
// to set the number of sim slots.
updateMobileControllers();
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
MobileSignalController controller = mMobileSignalControllers.valueAt(i);
controller.resetLastState();
}
mWifiSignalController.resetLastState();
mReceiverHandler.post(mRegisterListeners);
notifyAllListeners();
}
@Override
public void dispatchDemoCommand(String command, Bundle args) {
if (!mDemoMode && command.equals(COMMAND_ENTER)) {
if (DEBUG) Log.d(TAG, "Entering demo mode");
unregisterListeners();
mDemoMode = true;
mDemoInetCondition = mInetCondition;
mDemoWifiState = mWifiSignalController.getState();
mDemoWifiState.ssid = "DemoMode";
} else if (mDemoMode && command.equals(COMMAND_EXIT)) {
if (DEBUG) Log.d(TAG, "Exiting demo mode");
mDemoMode = false;
// Update what MobileSignalControllers, because they may change
// to set the number of sim slots.
updateMobileControllers();
if (!mDemoModeController.isInDemoMode()) {
return;
}
String airplane = args.getString("airplane");
if (airplane != null) {
boolean show = airplane.equals("show");
mCallbackHandler.setIsAirplaneMode(new IconState(show,
TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode,
mContext));
}
String fully = args.getString("fully");
if (fully != null) {
mDemoInetCondition = Boolean.parseBoolean(fully);
BitSet connected = new BitSet();
if (mDemoInetCondition) {
connected.set(mWifiSignalController.mTransportType);
}
mWifiSignalController.updateConnectivity(connected, connected);
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
MobileSignalController controller = mMobileSignalControllers.valueAt(i);
controller.resetLastState();
}
mWifiSignalController.resetLastState();
mReceiverHandler.post(mRegisterListeners);
notifyAllListeners();
} else if (mDemoMode && command.equals(COMMAND_NETWORK)) {
String airplane = args.getString("airplane");
if (airplane != null) {
boolean show = airplane.equals("show");
mCallbackHandler.setIsAirplaneMode(new IconState(show,
TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode,
mContext));
}
String fully = args.getString("fully");
if (fully != null) {
mDemoInetCondition = Boolean.parseBoolean(fully);
BitSet connected = new BitSet();
if (mDemoInetCondition) {
connected.set(mWifiSignalController.mTransportType);
connected.set(controller.mTransportType);
}
mWifiSignalController.updateConnectivity(connected, connected);
controller.updateConnectivity(connected, connected);
}
}
String wifi = args.getString("wifi");
if (wifi != null) {
boolean show = wifi.equals("show");
String level = args.getString("level");
if (level != null) {
mDemoWifiState.level = level.equals("null") ? -1
: Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
mDemoWifiState.connected = mDemoWifiState.level >= 0;
}
String activity = args.getString("activity");
if (activity != null) {
switch (activity) {
case "inout":
mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT);
break;
case "in":
mWifiSignalController.setActivity(DATA_ACTIVITY_IN);
break;
case "out":
mWifiSignalController.setActivity(DATA_ACTIVITY_OUT);
break;
default:
mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
break;
}
} else {
mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
}
String ssid = args.getString("ssid");
if (ssid != null) {
mDemoWifiState.ssid = ssid;
}
mDemoWifiState.enabled = show;
mWifiSignalController.notifyListeners();
}
String sims = args.getString("sims");
if (sims != null) {
int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8);
List<SubscriptionInfo> subs = new ArrayList<>();
if (num != mMobileSignalControllers.size()) {
mMobileSignalControllers.clear();
int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
for (int i = start /* get out of normal index range */; i < start + num; i++) {
subs.add(addSignalController(i, i));
}
mCallbackHandler.setSubs(subs);
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
MobileSignalController controller = mMobileSignalControllers.valueAt(i);
if (mDemoInetCondition) {
connected.set(controller.mTransportType);
}
controller.updateConnectivity(connected, connected);
}
}
String wifi = args.getString("wifi");
if (wifi != null) {
boolean show = wifi.equals("show");
String level = args.getString("level");
if (level != null) {
mDemoWifiState.level = level.equals("null") ? -1
: Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
mDemoWifiState.connected = mDemoWifiState.level >= 0;
}
String activity = args.getString("activity");
if (activity != null) {
switch (activity) {
case "inout":
mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT);
break;
case "in":
mWifiSignalController.setActivity(DATA_ACTIVITY_IN);
break;
case "out":
mWifiSignalController.setActivity(DATA_ACTIVITY_OUT);
break;
default:
mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
break;
}
} else {
mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
}
String ssid = args.getString("ssid");
if (ssid != null) {
mDemoWifiState.ssid = ssid;
}
mDemoWifiState.enabled = show;
mWifiSignalController.notifyListeners();
}
String sims = args.getString("sims");
if (sims != null) {
int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8);
List<SubscriptionInfo> subs = new ArrayList<>();
if (num != mMobileSignalControllers.size()) {
mMobileSignalControllers.clear();
int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
for (int i = start /* get out of normal index range */; i < start + num; i++) {
subs.add(addSignalController(i, i));
}
mCallbackHandler.setSubs(subs);
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
int key = mMobileSignalControllers.keyAt(i);
MobileSignalController controller = mMobileSignalControllers.get(key);
controller.notifyListeners();
}
}
}
String nosim = args.getString("nosim");
if (nosim != null) {
mHasNoSubs = nosim.equals("show");
mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
}
String mobile = args.getString("mobile");
if (mobile != null) {
boolean show = mobile.equals("show");
String datatype = args.getString("datatype");
String slotString = args.getString("slot");
int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString);
slot = MathUtils.constrain(slot, 0, 8);
// Ensure we have enough sim slots
List<SubscriptionInfo> subs = new ArrayList<>();
while (mMobileSignalControllers.size() <= slot) {
int nextSlot = mMobileSignalControllers.size();
subs.add(addSignalController(nextSlot, nextSlot));
}
if (!subs.isEmpty()) {
mCallbackHandler.setSubs(subs);
}
// Hack to index linearly for easy use.
MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
controller.getState().dataSim = datatype != null;
controller.getState().isDefault = datatype != null;
controller.getState().dataConnected = datatype != null;
if (datatype != null) {
controller.getState().iconGroup =
datatype.equals("1x") ? TelephonyIcons.ONE_X :
datatype.equals("3g") ? TelephonyIcons.THREE_G :
datatype.equals("4g") ? TelephonyIcons.FOUR_G :
datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS :
datatype.equals("5g") ? TelephonyIcons.NR_5G :
datatype.equals("5ge") ? TelephonyIcons.LTE_CA_5G_E :
datatype.equals("5g+") ? TelephonyIcons.NR_5G_PLUS :
datatype.equals("e") ? TelephonyIcons.E :
datatype.equals("g") ? TelephonyIcons.G :
datatype.equals("h") ? TelephonyIcons.H :
datatype.equals("h+") ? TelephonyIcons.H_PLUS :
datatype.equals("lte") ? TelephonyIcons.LTE :
datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
datatype.equals("not") ? TelephonyIcons.NOT_DEFAULT_DATA :
TelephonyIcons.UNKNOWN;
}
if (args.containsKey("roam")) {
controller.getState().roaming = "show".equals(args.getString("roam"));
}
String level = args.getString("level");
if (level != null) {
controller.getState().level = level.equals("null") ? -1
: Math.min(Integer.parseInt(level),
CellSignalStrength.getNumSignalStrengthLevels());
controller.getState().connected = controller.getState().level >= 0;
}
if (args.containsKey("inflate")) {
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
mMobileSignalControllers.valueAt(i).mInflateSignalStrengths =
"true".equals(args.getString("inflate"));
}
}
String activity = args.getString("activity");
if (activity != null) {
controller.getState().dataConnected = true;
switch (activity) {
case "inout":
controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
break;
case "in":
controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN);
break;
case "out":
controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT);
break;
default:
controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
break;
}
} else {
controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
}
controller.getState().enabled = show;
controller.notifyListeners();
}
String carrierNetworkChange = args.getString("carriernetworkchange");
if (carrierNetworkChange != null) {
boolean show = carrierNetworkChange.equals("show");
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
MobileSignalController controller = mMobileSignalControllers.valueAt(i);
controller.setCarrierNetworkChangeMode(show);
int key = mMobileSignalControllers.keyAt(i);
MobileSignalController controller = mMobileSignalControllers.get(key);
controller.notifyListeners();
}
}
}
String nosim = args.getString("nosim");
if (nosim != null) {
mHasNoSubs = nosim.equals("show");
mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
}
String mobile = args.getString("mobile");
if (mobile != null) {
boolean show = mobile.equals("show");
String datatype = args.getString("datatype");
String slotString = args.getString("slot");
int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString);
slot = MathUtils.constrain(slot, 0, 8);
// Ensure we have enough sim slots
List<SubscriptionInfo> subs = new ArrayList<>();
while (mMobileSignalControllers.size() <= slot) {
int nextSlot = mMobileSignalControllers.size();
subs.add(addSignalController(nextSlot, nextSlot));
}
if (!subs.isEmpty()) {
mCallbackHandler.setSubs(subs);
}
// Hack to index linearly for easy use.
MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
controller.getState().dataSim = datatype != null;
controller.getState().isDefault = datatype != null;
controller.getState().dataConnected = datatype != null;
if (datatype != null) {
controller.getState().iconGroup =
datatype.equals("1x") ? TelephonyIcons.ONE_X :
datatype.equals("3g") ? TelephonyIcons.THREE_G :
datatype.equals("4g") ? TelephonyIcons.FOUR_G :
datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS :
datatype.equals("5g") ? TelephonyIcons.NR_5G :
datatype.equals("5ge") ? TelephonyIcons.LTE_CA_5G_E :
datatype.equals("5g+") ? TelephonyIcons.NR_5G_PLUS :
datatype.equals("e") ? TelephonyIcons.E :
datatype.equals("g") ? TelephonyIcons.G :
datatype.equals("h") ? TelephonyIcons.H :
datatype.equals("h+") ? TelephonyIcons.H_PLUS :
datatype.equals("lte") ? TelephonyIcons.LTE :
datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
datatype.equals("not") ? TelephonyIcons.NOT_DEFAULT_DATA :
TelephonyIcons.UNKNOWN;
}
if (args.containsKey("roam")) {
controller.getState().roaming = "show".equals(args.getString("roam"));
}
String level = args.getString("level");
if (level != null) {
controller.getState().level = level.equals("null") ? -1
: Math.min(Integer.parseInt(level),
CellSignalStrength.getNumSignalStrengthLevels());
controller.getState().connected = controller.getState().level >= 0;
}
if (args.containsKey("inflate")) {
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
mMobileSignalControllers.valueAt(i).mInflateSignalStrengths =
"true".equals(args.getString("inflate"));
}
}
String activity = args.getString("activity");
if (activity != null) {
controller.getState().dataConnected = true;
switch (activity) {
case "inout":
controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
break;
case "in":
controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN);
break;
case "out":
controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT);
break;
default:
controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
break;
}
} else {
controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
}
controller.getState().enabled = show;
controller.notifyListeners();
}
String carrierNetworkChange = args.getString("carriernetworkchange");
if (carrierNetworkChange != null) {
boolean show = carrierNetworkChange.equals("show");
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
MobileSignalController controller = mMobileSignalControllers.valueAt(i);
controller.setCarrierNetworkChangeMode(show);
}
}
}
@Override
public List<String> demoCommands() {
List<String> s = new ArrayList<>();
s.add(DemoMode.COMMAND_NETWORK);
return s;
}
private SubscriptionInfo addSignalController(int id, int simSlotIndex) {

View File

@@ -23,6 +23,8 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.UserHandle;
import androidx.annotation.NonNull;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -59,12 +61,14 @@ public class NextAlarmControllerImpl extends BroadcastReceiver
pw.print(" mNextAlarm="); pw.println(mNextAlarm);
}
public void addCallback(NextAlarmChangeCallback cb) {
@Override
public void addCallback(@NonNull NextAlarmChangeCallback cb) {
mChangeCallbacks.add(cb);
cb.onNextAlarmChanged(mNextAlarm);
}
public void removeCallback(NextAlarmChangeCallback cb) {
@Override
public void removeCallback(@NonNull NextAlarmChangeCallback cb) {
mChangeCallbacks.remove(cb);
}

View File

@@ -19,6 +19,8 @@ package com.android.systemui.statusbar.policy;
import android.content.Context;
import android.os.UserHandle;
import androidx.annotation.NonNull;
import com.android.internal.view.RotationPolicy;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -47,12 +49,14 @@ public final class RotationLockControllerImpl implements RotationLockController
setListening(true);
}
public void addCallback(RotationLockControllerCallback callback) {
@Override
public void addCallback(@NonNull RotationLockControllerCallback callback) {
mCallbacks.add(callback);
notifyChanged(callback);
}
public void removeCallback(RotationLockControllerCallback callback) {
@Override
public void removeCallback(@NonNull RotationLockControllerCallback callback) {
mCallbacks.remove(callback);
}

View File

@@ -42,6 +42,8 @@ import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
@@ -274,7 +276,7 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi
}
@Override
public void removeCallback(SecurityControllerCallback callback) {
public void removeCallback(@NonNull SecurityControllerCallback callback) {
synchronized (mCallbacks) {
if (callback == null) return;
if (DEBUG) Log.d(TAG, "removeCallback " + callback);
@@ -283,7 +285,7 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi
}
@Override
public void addCallback(SecurityControllerCallback callback) {
public void addCallback(@NonNull SecurityControllerCallback callback) {
synchronized (mCallbacks) {
if (callback == null || mCallbacks.contains(callback)) return;
if (DEBUG) Log.d(TAG, "addCallback " + callback);

View File

@@ -19,6 +19,8 @@ package com.android.systemui.statusbar.policy;
import android.content.Context;
import android.hardware.SensorPrivacyManager;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
@@ -60,7 +62,7 @@ public class SensorPrivacyControllerImpl implements SensorPrivacyController,
/**
* Adds the provided listener for callbacks when sensor privacy state changes.
*/
public void addCallback(OnSensorPrivacyChangedListener listener) {
public void addCallback(@NonNull OnSensorPrivacyChangedListener listener) {
synchronized (mLock) {
mListeners.add(listener);
notifyListenerLocked(listener);
@@ -70,7 +72,7 @@ public class SensorPrivacyControllerImpl implements SensorPrivacyController,
/**
* Removes the provided listener from callbacks when sensor privacy state changes.
*/
public void removeCallback(OnSensorPrivacyChangedListener listener) {
public void removeCallback(@NonNull OnSensorPrivacyChangedListener listener) {
synchronized (mLock) {
mListeners.remove(listener);
}

View File

@@ -34,6 +34,8 @@ import android.os.UserManager;
import android.provider.ContactsContract;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.internal.util.UserIcons;
import com.android.settingslib.drawable.UserIconDrawable;
import com.android.systemui.R;
@@ -75,12 +77,14 @@ public class UserInfoControllerImpl implements UserInfoController {
null, null);
}
public void addCallback(OnUserInfoChangedListener callback) {
@Override
public void addCallback(@NonNull OnUserInfoChangedListener callback) {
mCallbacks.add(callback);
callback.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount);
}
public void removeCallback(OnUserInfoChangedListener callback) {
@Override
public void removeCallback(@NonNull OnUserInfoChangedListener callback) {
mCallbacks.remove(callback);
}

View File

@@ -37,6 +37,8 @@ import android.service.notification.ZenModeConfig.ZenRule;
import android.text.format.DateFormat;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -124,14 +126,14 @@ public class ZenModeControllerImpl extends CurrentUserTracker
}
@Override
public void addCallback(Callback callback) {
public void addCallback(@NonNull Callback callback) {
synchronized (mCallbacksLock) {
mCallbacks.add(callback);
}
}
@Override
public void removeCallback(Callback callback) {
public void removeCallback(@NonNull Callback callback) {
synchronized (mCallbacksLock) {
mCallbacks.remove(callback);
}

View File

@@ -15,14 +15,10 @@
*/
package com.android.systemui.tuner;
import android.content.ContentResolver;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.view.MenuItem;
import androidx.preference.Preference;
@@ -33,13 +29,13 @@ import androidx.preference.SwitchPreference;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeAvailabilityTracker;
import com.android.systemui.demomode.DemoModeController;
public class DemoModeFragment extends PreferenceFragment implements OnPreferenceChangeListener {
private static final String DEMO_MODE_ON = "sysui_tuner_demo_on";
private static final String[] STATUS_ICONS = {
"volume",
"bluetooth",
@@ -57,6 +53,17 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference
private SwitchPreference mEnabledSwitch;
private SwitchPreference mOnSwitch;
private DemoModeController mDemoModeController;
private Tracker mDemoModeTracker;
// We are the only ones who ever call this constructor, so don't worry about the warning
@SuppressLint("ValidFragment")
public DemoModeFragment(DemoModeController demoModeController) {
super();
mDemoModeController = demoModeController;
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
Context context = getContext();
@@ -73,13 +80,11 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference
screen.addPreference(mOnSwitch);
setPreferenceScreen(screen);
mDemoModeTracker = new Tracker(context);
mDemoModeTracker.startTracking();
updateDemoModeEnabled();
updateDemoModeOn();
ContentResolver contentResolver = getContext().getContentResolver();
contentResolver.registerContentObserver(Settings.Global.getUriFor(
DemoMode.DEMO_MODE_ALLOWED), false, mDemoModeObserver);
contentResolver.registerContentObserver(Settings.Global.getUriFor(DEMO_MODE_ON), false,
mDemoModeObserver);
setHasOptionsMenu(true);
}
@@ -107,21 +112,17 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference
@Override
public void onDestroy() {
getContext().getContentResolver().unregisterContentObserver(mDemoModeObserver);
mDemoModeTracker.stopTracking();
super.onDestroy();
}
private void updateDemoModeEnabled() {
boolean enabled = Settings.Global.getInt(getContext().getContentResolver(),
DemoMode.DEMO_MODE_ALLOWED, 0) != 0;
mEnabledSwitch.setChecked(enabled);
mOnSwitch.setEnabled(enabled);
mEnabledSwitch.setChecked(mDemoModeTracker.isDemoModeAvailable());
mOnSwitch.setEnabled(mDemoModeTracker.isDemoModeAvailable());
}
private void updateDemoModeOn() {
boolean enabled = Settings.Global.getInt(getContext().getContentResolver(),
DEMO_MODE_ON, 0) != 0;
mOnSwitch.setChecked(enabled);
mOnSwitch.setChecked(mDemoModeTracker.isInDemoMode());
}
@Override
@@ -134,7 +135,7 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference
stopDemoMode();
}
MetricsLogger.action(getContext(), MetricsEvent.TUNER_DEMO_MODE_ENABLED, enabled);
setGlobal(DemoMode.DEMO_MODE_ALLOWED, enabled ? 1 : 0);
mDemoModeController.requestSetDemoModeAllowed(enabled);
} else if (preference == mOnSwitch) {
MetricsLogger.action(getContext(), MetricsEvent.TUNER_DEMO_MODE_ON, enabled);
if (enabled) {
@@ -151,11 +152,11 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference
private void startDemoMode() {
Intent intent = new Intent(DemoMode.ACTION_DEMO);
intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_ENTER);
getContext().sendBroadcast(intent);
mDemoModeController.requestStartDemoMode();
intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_CLOCK);
//TODO: everything below should move to DemoModeController, or some `initialState` command
String demoTime = "1010"; // 10:10, a classic choice of horologists
try {
String[] versionParts = android.os.Build.VERSION.RELEASE_OR_CODENAME.split("\\.");
@@ -194,25 +195,31 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference
intent.putExtra("visible", "false");
getContext().sendBroadcast(intent);
setGlobal(DEMO_MODE_ON, 1);
}
private void stopDemoMode() {
Intent intent = new Intent(DemoMode.ACTION_DEMO);
intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
getContext().sendBroadcast(intent);
setGlobal(DEMO_MODE_ON, 0);
mDemoModeController.requestFinishDemoMode();
}
private void setGlobal(String key, int value) {
Settings.Global.putInt(getContext().getContentResolver(), key, value);
}
private class Tracker extends DemoModeAvailabilityTracker {
Tracker(Context context) {
super(context);
}
private final ContentObserver mDemoModeObserver =
new ContentObserver(new Handler(Looper.getMainLooper())) {
public void onChange(boolean selfChange) {
@Override
public void onDemoModeAvailabilityChanged() {
updateDemoModeEnabled();
updateDemoModeOn();
};
}
@Override
public void onDemoModeStarted() {
updateDemoModeOn();
}
@Override
public void onDemoModeFinished() {
updateDemoModeOn();
}
};
}

View File

@@ -31,6 +31,7 @@ import androidx.preference.PreferenceScreen;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.fragments.FragmentService;
import javax.inject.Inject;
@@ -41,9 +42,12 @@ public class TunerActivity extends Activity implements
private static final String TAG_TUNER = "tuner";
private final DemoModeController mDemoModeController;
@Inject
TunerActivity() {
TunerActivity(DemoModeController demoModeController) {
super();
mDemoModeController = demoModeController;
}
protected void onCreate(Bundle savedInstanceState) {
@@ -61,7 +65,8 @@ public class TunerActivity extends Activity implements
final String action = getIntent().getAction();
boolean showDemoMode = action != null && action.equals(
"com.android.settings.action.DEMO_MODE");
final PreferenceFragment fragment = showDemoMode ? new DemoModeFragment()
final PreferenceFragment fragment = showDemoMode
? new DemoModeFragment(mDemoModeController)
: new TunerFragment();
getFragmentManager().beginTransaction().replace(R.id.content_frame,
fragment, TAG_TUNER).commit();

View File

@@ -18,7 +18,6 @@ package com.android.systemui.tuner;
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.net.Uri;
@@ -33,9 +32,9 @@ import android.util.ArraySet;
import com.android.internal.util.ArrayUtils;
import com.android.systemui.DejankUtils;
import com.android.systemui.DemoMode;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -54,6 +53,7 @@ import javax.inject.Singleton;
@Singleton
public class TunerServiceImpl extends TunerService {
private static final String TAG = "TunerService";
private static final String TUNER_VERSION = "sysui_tuner_version";
private static final int CURRENT_TUNER_VERSION = 4;
@@ -76,6 +76,7 @@ public class TunerServiceImpl extends TunerService {
private final HashSet<Tunable> mTunables = LeakDetector.ENABLED ? new HashSet<>() : null;
private final Context mContext;
private final LeakDetector mLeakDetector;
private final DemoModeController mDemoModeController;
private ContentResolver mContentResolver;
private int mCurrentUser;
@@ -84,11 +85,16 @@ public class TunerServiceImpl extends TunerService {
/**
*/
@Inject
public TunerServiceImpl(Context context, @Main Handler mainHandler,
LeakDetector leakDetector, BroadcastDispatcher broadcastDispatcher) {
public TunerServiceImpl(
Context context,
@Main Handler mainHandler,
LeakDetector leakDetector,
DemoModeController demoModeController,
BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mContentResolver = mContext.getContentResolver();
mLeakDetector = leakDetector;
mDemoModeController = demoModeController;
for (UserInfo user : UserManager.get(mContext).getUsers()) {
mCurrentUser = user.getUserHandle().getIdentifier();
@@ -244,12 +250,11 @@ public class TunerServiceImpl extends TunerService {
}
public void clearAllFromUser(int user) {
// A couple special cases.
Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
Intent intent = new Intent(DemoMode.ACTION_DEMO);
intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
mContext.sendBroadcast(intent);
// Turn off demo mode
mDemoModeController.requestFinishDemoMode();
mDemoModeController.requestSetDemoModeAllowed(false);
// A couple special cases.
for (String key : mTunableLookup.keySet()) {
if (ArrayUtils.contains(RESET_EXCEPTION_LIST, key)) {
continue;

View File

@@ -29,6 +29,7 @@ import com.android.keyguard.KeyguardViewController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
import com.android.systemui.doze.DozeHost;
@@ -101,10 +102,10 @@ public abstract class TvSystemUIModule {
@Singleton
static BatteryController provideBatteryController(Context context,
EnhancedEstimates enhancedEstimates, PowerManager powerManager,
BroadcastDispatcher broadcastDispatcher, @Main Handler mainHandler,
@Background Handler bgHandler) {
BroadcastDispatcher broadcastDispatcher, DemoModeController demoModeController,
@Main Handler mainHandler, @Background Handler bgHandler) {
BatteryController bC = new BatteryControllerImpl(context, enhancedEstimates, powerManager,
broadcastDispatcher, mainHandler, bgHandler);
broadcastDispatcher, demoModeController, mainHandler, bgHandler);
bC.init();
return bC;
}

View File

@@ -18,7 +18,7 @@ package com.android.systemui.volume;
import android.content.res.Configuration;
import com.android.systemui.DemoMode;
import com.android.systemui.demomode.DemoMode;
import java.io.FileDescriptor;
import java.io.PrintWriter;

View File

@@ -27,6 +27,8 @@ import android.view.WindowManager.LayoutParams;
import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.Dependency;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.PluginDependencyProvider;
@@ -38,6 +40,8 @@ import com.android.systemui.tuner.TunerService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -72,8 +76,11 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
);
@Inject
public VolumeDialogComponent(Context context, KeyguardViewMediator keyguardViewMediator,
VolumeDialogControllerImpl volumeDialogController) {
public VolumeDialogComponent(
Context context,
KeyguardViewMediator keyguardViewMediator,
VolumeDialogControllerImpl volumeDialogController,
DemoModeController demoModeController) {
mContext = context;
mKeyguardViewMediator = keyguardViewMediator;
mController = volumeDialogController;
@@ -94,6 +101,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
applyConfiguration();
Dependency.get(TunerService.class).addTunable(this, VOLUME_DOWN_SILENT, VOLUME_UP_SILENT,
VOLUME_SILENT_DO_NOT_DISTURB);
demoModeController.addCallback(this);
}
protected VolumeDialog createDefault() {
@@ -163,6 +171,13 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
// noop
}
@Override
public List<String> demoCommands() {
List<String> s = new ArrayList<>();
s.add(DemoMode.COMMAND_VOLUME);
return s;
}
@Override
public void register() {
mController.register();

View File

@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.phone;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -29,6 +28,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -66,6 +66,7 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase {
private NotificationIconAreaController mController;
@Mock
private BubbleController mBubbleController;
@Mock private DemoModeController mDemoModeController;
@Before
public void setup() {
@@ -77,7 +78,8 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase {
mController = new NotificationIconAreaController(mContext, mStatusBar,
mStatusBarStateController, mWakeUpCoordinator, mKeyguardBypassController,
mNotificationMediaManager, mListener, mDozeParameters, mBubbleController);
mNotificationMediaManager, mListener, mDozeParameters, mBubbleController,
mDemoModeController);
}
@Test

View File

@@ -83,10 +83,12 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.PluginDependencyProvider;
@@ -97,7 +99,6 @@ import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -252,6 +253,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private ExtensionController mExtensionController;
@Mock private UserInfoControllerImpl mUserInfoControllerImpl;
@Mock private PhoneStatusBarPolicy mPhoneStatusBarPolicy;
@Mock private DemoModeController mDemoModeController;
@Mock private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
private ShadeController mShadeController;
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -411,6 +413,7 @@ public class StatusBarTest extends SysuiTestCase {
mPhoneStatusBarPolicy,
mKeyguardIndicationController,
mDismissCallbackRegistry,
mDemoModeController,
mNotificationShadeDepthControllerLazy,
mStatusBarTouchableRegionManager);

View File

@@ -29,6 +29,7 @@ import android.testing.TestableLooper;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.power.EnhancedEstimates;
import org.junit.Assert;
@@ -44,17 +45,21 @@ import org.mockito.MockitoAnnotations;
@TestableLooper.RunWithLooper
public class BatteryControllerTest extends SysuiTestCase {
@Mock
private PowerManager mPowerManager;
@Mock
private BroadcastDispatcher mBroadcastDispatcher;
@Mock private PowerManager mPowerManager;
@Mock private BroadcastDispatcher mBroadcastDispatcher;
@Mock private DemoModeController mDemoModeController;
private BatteryControllerImpl mBatteryController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mBatteryController = new BatteryControllerImpl(getContext(), mock(EnhancedEstimates.class),
mPowerManager, mBroadcastDispatcher, new Handler(), new Handler());
mBatteryController = new BatteryControllerImpl(getContext(),
mock(EnhancedEstimates.class),
mPowerManager,
mBroadcastDispatcher,
mDemoModeController,
new Handler(),
new Handler());
mBatteryController.init();
}

View File

@@ -66,6 +66,7 @@ import com.android.settingslib.net.DataUsageController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
@@ -113,6 +114,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
protected DeviceProvisionedController mMockProvisionController;
protected DeviceProvisionedListener mUserCallback;
protected Instrumentation mInstrumentation;
protected DemoModeController mDemoModeController;
protected int mSubId;
@@ -146,6 +148,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
res.addOverride(R.string.cell_data_off_content_description, NO_DATA_STRING);
res.addOverride(R.string.not_default_data_content_description, NOT_DEFAULT_DATA_STRING);
mDemoModeController = mock(DemoModeController.class);
mMockWm = mock(WifiManager.class);
mMockTm = mock(TelephonyManager.class);
mMockSm = mock(SubscriptionManager.class);
@@ -200,10 +203,21 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
return null;
}).when(mMockProvisionController).addCallback(any());
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
mMockNsm, mMockSm, mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
mMockSubDefaults, mMockProvisionController, mMockBd);
mNetworkController = new NetworkControllerImpl(mContext,
mMockCm,
mMockTm,
mMockWm,
mMockNsm,
mMockSm,
mConfig,
TestableLooper.get(this).getLooper(),
mCallbackHandler,
mock(AccessPointControllerImpl.class),
mock(DataUsageController.class),
mMockSubDefaults,
mMockProvisionController,
mMockBd,
mDemoModeController);
setupNetworkController();
// Trigger blank callbacks to always get the current state (some tests don't trigger
@@ -254,7 +268,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class),
mock(DataUsageController.class), mMockSubDefaults,
mock(DeviceProvisionedController.class), mMockBd);
mock(DeviceProvisionedController.class), mMockBd, mDemoModeController);
setupNetworkController();

View File

@@ -106,7 +106,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class),
mock(DataUsageController.class), mMockSubDefaults,
mock(DeviceProvisionedController.class), mMockBd);
mock(DeviceProvisionedController.class), mMockBd, mDemoModeController);
setupNetworkController();
setupDefaultSignal();

View File

@@ -63,7 +63,8 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd);
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
mDemoModeController);
setupNetworkController();
verifyLastMobileDataIndicators(false, -1, 0);
@@ -81,7 +82,8 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd);
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
mDemoModeController);
mNetworkController.registerListeners();
// Wait for the main looper to execute the previous command
@@ -147,7 +149,8 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd);
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
mDemoModeController);
setupNetworkController();
// No Subscriptions.