[ScreenDecor CLI] ScreenDecorCommand based on ParseableCommand
This CL implements the ScreenDecorCommand class based on the new ParseableCommand definitions. This approach lets us move all of the parsing into the lib and handle the command object in a cleaner way. Test: manual Bug: 285941724 Change-Id: Ic801c654ade599dc4921994836ead46c2bba9f69
This commit is contained in:
@@ -80,10 +80,12 @@ import com.android.systemui.decor.OverlayWindow;
|
||||
import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
|
||||
import com.android.systemui.decor.RoundedCornerDecorProviderFactory;
|
||||
import com.android.systemui.decor.RoundedCornerResDelegateImpl;
|
||||
import com.android.systemui.decor.ScreenDecorCommand;
|
||||
import com.android.systemui.log.ScreenDecorationsLogger;
|
||||
import com.android.systemui.qs.SettingObserver;
|
||||
import com.android.systemui.settings.DisplayTracker;
|
||||
import com.android.systemui.settings.UserTracker;
|
||||
import com.android.systemui.statusbar.commandline.CommandRegistry;
|
||||
import com.android.systemui.statusbar.events.PrivacyDotViewController;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
import com.android.systemui.util.concurrency.ThreadFactory;
|
||||
@@ -131,6 +133,7 @@ public class ScreenDecorations implements CoreStartable, Dumpable {
|
||||
protected boolean mIsRegistered;
|
||||
private final Context mContext;
|
||||
private final Executor mMainExecutor;
|
||||
private final CommandRegistry mCommandRegistry;
|
||||
private final SecureSettings mSecureSettings;
|
||||
@VisibleForTesting
|
||||
DisplayTracker.Callback mDisplayListener;
|
||||
@@ -315,6 +318,7 @@ public class ScreenDecorations implements CoreStartable, Dumpable {
|
||||
public ScreenDecorations(Context context,
|
||||
@Main Executor mainExecutor,
|
||||
SecureSettings secureSettings,
|
||||
CommandRegistry commandRegistry,
|
||||
UserTracker userTracker,
|
||||
DisplayTracker displayTracker,
|
||||
PrivacyDotViewController dotViewController,
|
||||
@@ -326,6 +330,7 @@ public class ScreenDecorations implements CoreStartable, Dumpable {
|
||||
mContext = context;
|
||||
mMainExecutor = mainExecutor;
|
||||
mSecureSettings = secureSettings;
|
||||
mCommandRegistry = commandRegistry;
|
||||
mUserTracker = userTracker;
|
||||
mDisplayTracker = displayTracker;
|
||||
mDotViewController = dotViewController;
|
||||
@@ -350,6 +355,10 @@ public class ScreenDecorations implements CoreStartable, Dumpable {
|
||||
}
|
||||
};
|
||||
|
||||
private final ScreenDecorCommand.Callback mScreenDecorCommandCallback = (cmd, pw) -> {
|
||||
android.util.Log.d(TAG, cmd.toString());
|
||||
};
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (DEBUG_DISABLE_SCREEN_DECORATIONS) {
|
||||
@@ -361,6 +370,8 @@ public class ScreenDecorations implements CoreStartable, Dumpable {
|
||||
mExecutor.execute(this::startOnScreenDecorationsThread);
|
||||
mDotViewController.setUiExecutor(mExecutor);
|
||||
mAuthController.addCallback(mAuthControllerCallback);
|
||||
mCommandRegistry.registerCommand(ScreenDecorCommand.SCREEN_DECOR_CMD_NAME,
|
||||
() -> new ScreenDecorCommand(mScreenDecorCommandCallback));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.decor
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.Path
|
||||
import android.util.PathParser
|
||||
import com.android.systemui.statusbar.commandline.ParseableCommand
|
||||
import com.android.systemui.statusbar.commandline.Type
|
||||
import com.android.systemui.statusbar.commandline.map
|
||||
import java.io.PrintWriter
|
||||
|
||||
/** Debug screen-decor command to be handled by the SystemUI command line interface */
|
||||
class ScreenDecorCommand(
|
||||
private val callback: Callback,
|
||||
) : ParseableCommand(SCREEN_DECOR_CMD_NAME) {
|
||||
val debug: Boolean? by
|
||||
param(
|
||||
longName = "debug",
|
||||
description =
|
||||
"Enter or exits debug mode. Effectively makes the corners visible and allows " +
|
||||
"for overriding the path data for the anti-aliasing corner paths and display " +
|
||||
"cutout.",
|
||||
valueParser = Type.Boolean,
|
||||
)
|
||||
|
||||
val color: Int? by
|
||||
param(
|
||||
longName = "color",
|
||||
shortName = "c",
|
||||
description =
|
||||
"Set a specific color for the debug assets. See Color#parseString() for " +
|
||||
"accepted inputs.",
|
||||
valueParser = Type.String.map { it.toColorIntOrNull() }
|
||||
)
|
||||
|
||||
val roundedTop: RoundedCornerSubCommand? by subCommand(RoundedCornerSubCommand("rounded-top"))
|
||||
|
||||
val roundedBottom: RoundedCornerSubCommand? by
|
||||
subCommand(RoundedCornerSubCommand("rounded-bottom"))
|
||||
|
||||
override fun execute(pw: PrintWriter) {
|
||||
callback.onExecute(this, pw)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "ScreenDecorCommand(" +
|
||||
"debug=$debug, " +
|
||||
"color=$color, " +
|
||||
"roundedTop=$roundedTop, " +
|
||||
"roundedBottom=$roundedBottom)"
|
||||
}
|
||||
|
||||
/** For use in ScreenDecorations.java, define a Callback */
|
||||
interface Callback {
|
||||
fun onExecute(cmd: ScreenDecorCommand, pw: PrintWriter)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SCREEN_DECOR_CMD_NAME = "screen-decor"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a subcommand suitable for `rounded-top` and `rounded-bottom`. They both have the same
|
||||
* API.
|
||||
*/
|
||||
class RoundedCornerSubCommand(name: String) : ParseableCommand(name) {
|
||||
val height by
|
||||
param(
|
||||
longName = "height",
|
||||
description = "The height of a corner, in pixels.",
|
||||
valueParser = Type.Int,
|
||||
)
|
||||
.required()
|
||||
|
||||
val width by
|
||||
param(
|
||||
longName = "width",
|
||||
description =
|
||||
"The width of the corner, in pixels. Likely should be equal to the height.",
|
||||
valueParser = Type.Int,
|
||||
)
|
||||
.required()
|
||||
|
||||
val pathData by
|
||||
param(
|
||||
longName = "path-data",
|
||||
shortName = "d",
|
||||
description =
|
||||
"PathParser-compatible path string to be rendered as the corner drawable. " +
|
||||
"This path should be a closed arc oriented as the top-left corner " +
|
||||
"of the device",
|
||||
valueParser = Type.String.map { it.toPathOrNull() }
|
||||
)
|
||||
.required()
|
||||
|
||||
val viewportHeight: Float? by
|
||||
param(
|
||||
longName = "viewport-height",
|
||||
description =
|
||||
"The height of the viewport for the given path string. " +
|
||||
"If null, the corner height will be used.",
|
||||
valueParser = Type.Float,
|
||||
)
|
||||
|
||||
val scaleY: Float
|
||||
get() = viewportHeight?.let { height.toFloat() / it } ?: 1.0f
|
||||
|
||||
val viewportWidth: Float? by
|
||||
param(
|
||||
longName = "viewport-width",
|
||||
description =
|
||||
"The width of the viewport for the given path string. " +
|
||||
"If null, the corner width will be used.",
|
||||
valueParser = Type.Float,
|
||||
)
|
||||
|
||||
val scaleX: Float
|
||||
get() = viewportWidth?.let { width.toFloat() / it } ?: 1.0f
|
||||
|
||||
override fun execute(pw: PrintWriter) {
|
||||
// Not needed for a subcommand
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "RoundedCornerSubCommand(" +
|
||||
"height=$height," +
|
||||
" width=$width," +
|
||||
" pathData='$pathData'," +
|
||||
" viewportHeight=$viewportHeight," +
|
||||
" viewportWidth=$viewportWidth)"
|
||||
}
|
||||
|
||||
fun toRoundedCornerDebugModel(): DebugRoundedCornerModel =
|
||||
DebugRoundedCornerModel(
|
||||
path = pathData,
|
||||
width = width,
|
||||
height = height,
|
||||
scaleX = scaleX,
|
||||
scaleY = scaleY,
|
||||
)
|
||||
}
|
||||
|
||||
fun String.toPathOrNull(): Path? =
|
||||
try {
|
||||
PathParser.createPathFromPathData(this)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
fun String.toColorIntOrNull(): Int? =
|
||||
try {
|
||||
Color.parseColor(this)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
@@ -96,6 +96,7 @@ import com.android.systemui.log.ScreenDecorationsLogger;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.settings.FakeDisplayTracker;
|
||||
import com.android.systemui.settings.UserTracker;
|
||||
import com.android.systemui.statusbar.commandline.CommandRegistry;
|
||||
import com.android.systemui.statusbar.events.PrivacyDotViewController;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
import com.android.systemui.util.concurrency.FakeThreadFactory;
|
||||
@@ -139,6 +140,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private Display mDisplay;
|
||||
@Mock
|
||||
private CommandRegistry mCommandRegistry;
|
||||
@Mock
|
||||
private UserTracker mUserTracker;
|
||||
@Mock
|
||||
private PrivacyDotViewController mDotViewController;
|
||||
@@ -232,7 +235,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer"))));
|
||||
|
||||
mScreenDecorations = spy(new ScreenDecorations(mContext, mExecutor, mSecureSettings,
|
||||
mUserTracker, mDisplayTracker, mDotViewController, mThreadFactory,
|
||||
mCommandRegistry, mUserTracker, mDisplayTracker, mDotViewController,
|
||||
mThreadFactory,
|
||||
mPrivacyDotDecorProviderFactory, mFaceScanningProviderFactory,
|
||||
new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer")),
|
||||
mAuthController) {
|
||||
@@ -1227,7 +1231,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders);
|
||||
when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(true);
|
||||
ScreenDecorations screenDecorations = new ScreenDecorations(mContext, mExecutor,
|
||||
mSecureSettings, mUserTracker, mDisplayTracker, mDotViewController,
|
||||
mSecureSettings, mCommandRegistry, mUserTracker, mDisplayTracker,
|
||||
mDotViewController,
|
||||
mThreadFactory, mPrivacyDotDecorProviderFactory, mFaceScanningProviderFactory,
|
||||
new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer")), mAuthController);
|
||||
screenDecorations.start();
|
||||
|
||||
Reference in New Issue
Block a user