Merge "OMS: limit shell command output via optional args" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c283f6100d
@@ -177,6 +177,23 @@ public class InstallOverlayTests extends BaseHostJUnit4Test {
|
||||
.contains(APP_OVERLAY_PACKAGE_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdbShellOMSInterface() throws Exception {
|
||||
installPackage("OverlayHostTests_AppOverlayV1.apk");
|
||||
assertTrue(shell("cmd overlay list " + DEVICE_TEST_PKG).contains(DEVICE_TEST_PKG));
|
||||
assertTrue(shell("cmd overlay list " + DEVICE_TEST_PKG).contains(APP_OVERLAY_PACKAGE_NAME));
|
||||
assertEquals("[ ] " + APP_OVERLAY_PACKAGE_NAME,
|
||||
shell("cmd overlay list " + APP_OVERLAY_PACKAGE_NAME).trim());
|
||||
assertEquals("STATE_DISABLED",
|
||||
shell("cmd overlay dump state " + APP_OVERLAY_PACKAGE_NAME).trim());
|
||||
|
||||
setOverlayEnabled(APP_OVERLAY_PACKAGE_NAME, true);
|
||||
assertEquals("[x] " + APP_OVERLAY_PACKAGE_NAME,
|
||||
shell("cmd overlay list " + APP_OVERLAY_PACKAGE_NAME).trim());
|
||||
assertEquals("STATE_ENABLED",
|
||||
shell("cmd overlay dump state " + APP_OVERLAY_PACKAGE_NAME).trim());
|
||||
}
|
||||
|
||||
private void delay() {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
@@ -195,20 +212,24 @@ public class InstallOverlayTests extends BaseHostJUnit4Test {
|
||||
}
|
||||
|
||||
private void installConvertExistingInstantPackageToFull(String pkg) throws Exception {
|
||||
getDevice().executeShellCommand("cmd package install-existing --wait --full " + pkg);
|
||||
shell("cmd package install-existing --wait --full " + pkg);
|
||||
}
|
||||
|
||||
private void setPackageEnabled(String pkg, boolean enabled) throws Exception {
|
||||
getDevice().executeShellCommand("cmd package " + (enabled ? "enable " : "disable ") + pkg);
|
||||
shell("cmd package " + (enabled ? "enable " : "disable ") + pkg);
|
||||
delay();
|
||||
}
|
||||
|
||||
private void setOverlayEnabled(String pkg, boolean enabled) throws Exception {
|
||||
getDevice().executeShellCommand("cmd overlay " + (enabled ? "enable " : "disable ") + pkg);
|
||||
shell("cmd overlay " + (enabled ? "enable " : "disable ") + pkg);
|
||||
delay();
|
||||
}
|
||||
|
||||
private boolean overlayManagerContainsPackage(String pkg) throws Exception {
|
||||
return getDevice().executeShellCommand("cmd overlay list").contains(pkg);
|
||||
return shell("cmd overlay list").contains(pkg);
|
||||
}
|
||||
|
||||
private String shell(final String cmd) throws Exception {
|
||||
return getDevice().executeShellCommand(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
63
services/core/java/com/android/server/om/DumpState.java
Normal file
63
services/core/java/com/android/server/om/DumpState.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.server.om;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.os.UserHandle;
|
||||
|
||||
/**
|
||||
* State for dumps performed by the OverlayManagerService.
|
||||
*/
|
||||
public final class DumpState {
|
||||
@UserIdInt private int mUserId = UserHandle.USER_ALL;
|
||||
@Nullable private String mPackageName;
|
||||
@Nullable private String mField;
|
||||
private boolean mVerbose;
|
||||
|
||||
/** Sets the user to dump the state for */
|
||||
public void setUserId(@UserIdInt int userId) {
|
||||
mUserId = userId;
|
||||
}
|
||||
@UserIdInt public int getUserId() {
|
||||
return mUserId;
|
||||
}
|
||||
|
||||
/** Sets the name of the package to dump the state for */
|
||||
public void setPackageName(String packageName) {
|
||||
mPackageName = packageName;
|
||||
}
|
||||
@Nullable public String getPackageName() {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
/** Sets the name of the field to dump the state of */
|
||||
public void setField(String field) {
|
||||
mField = field;
|
||||
}
|
||||
@Nullable public String getField() {
|
||||
return mField;
|
||||
}
|
||||
|
||||
/** Enables verbose dump state */
|
||||
public void setVerbose(boolean verbose) {
|
||||
mVerbose = verbose;
|
||||
}
|
||||
public boolean isVerbose() {
|
||||
return mVerbose;
|
||||
}
|
||||
}
|
||||
@@ -749,15 +749,77 @@ public final class OverlayManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(@NonNull final FileDescriptor fd, @NonNull final PrintWriter pw,
|
||||
@NonNull final String[] argv) {
|
||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
final DumpState dumpState = new DumpState();
|
||||
dumpState.setUserId(UserHandle.getUserId(Binder.getCallingUid()));
|
||||
|
||||
int opti = 0;
|
||||
while (opti < args.length) {
|
||||
final String opt = args[opti];
|
||||
if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
|
||||
break;
|
||||
}
|
||||
opti++;
|
||||
|
||||
if ("-h".equals(opt)) {
|
||||
pw.println("dump [-h] [--verbose] [--user USER_ID] [[FIELD] PACKAGE]");
|
||||
pw.println(" Print debugging information about the overlay manager.");
|
||||
pw.println(" With optional parameter PACKAGE, limit output to the specified");
|
||||
pw.println(" package. With optional parameter FIELD, limit output to");
|
||||
pw.println(" the value of that SettingsItem field. Field names are");
|
||||
pw.println(" case insensitive and out.println the m prefix can be omitted,");
|
||||
pw.println(" so the following are equivalent: mState, mstate, State, state.");
|
||||
return;
|
||||
} else if ("--user".equals(opt)) {
|
||||
opti++;
|
||||
if (opti >= args.length) {
|
||||
pw.println("Error: user missing argument");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
dumpState.setUserId(Integer.parseInt(args[opti]));
|
||||
} catch (NumberFormatException e) {
|
||||
pw.println("Error: user argument is not a number: " + args[opti]);
|
||||
return;
|
||||
}
|
||||
} else if ("--verbose".equals(opt)) {
|
||||
dumpState.setVerbose(true);
|
||||
} else {
|
||||
pw.println("Unknown argument: " + opt + "; use -h for help");
|
||||
}
|
||||
}
|
||||
if (opti < args.length) {
|
||||
final String arg = args[opti];
|
||||
opti++;
|
||||
switch (arg) {
|
||||
case "packagename":
|
||||
case "userid":
|
||||
case "targetpackagename":
|
||||
case "targetoverlayablename":
|
||||
case "basecodepath":
|
||||
case "state":
|
||||
case "isenabled":
|
||||
case "isstatic":
|
||||
case "priority":
|
||||
case "category":
|
||||
dumpState.setField(arg);
|
||||
break;
|
||||
default:
|
||||
dumpState.setPackageName(arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dumpState.getPackageName() == null && opti < args.length) {
|
||||
dumpState.setPackageName(args[opti]);
|
||||
opti++;
|
||||
}
|
||||
|
||||
enforceDumpPermission("dump");
|
||||
|
||||
final boolean verbose = argv.length > 0 && "--verbose".equals(argv[0]);
|
||||
|
||||
synchronized (mLock) {
|
||||
mImpl.onDump(pw);
|
||||
mPackageManager.dump(pw, verbose);
|
||||
mImpl.dump(pw, dumpState);
|
||||
if (dumpState.getPackageName() == null) {
|
||||
mPackageManager.dump(pw, dumpState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1046,10 +1108,10 @@ public final class OverlayManagerService extends SystemService {
|
||||
private static final String TAB1 = " ";
|
||||
private static final String TAB2 = TAB1 + TAB1;
|
||||
|
||||
public void dump(@NonNull final PrintWriter pw, final boolean verbose) {
|
||||
public void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) {
|
||||
pw.println("PackageInfo cache");
|
||||
|
||||
if (!verbose) {
|
||||
if (!dumpState.isVerbose()) {
|
||||
int count = 0;
|
||||
final int n = mCache.size();
|
||||
for (int i = 0; i < n; i++) {
|
||||
|
||||
@@ -636,9 +636,11 @@ final class OverlayManagerServiceImpl {
|
||||
return true;
|
||||
}
|
||||
|
||||
void onDump(@NonNull final PrintWriter pw) {
|
||||
mSettings.dump(pw);
|
||||
pw.println("Default overlays: " + TextUtils.join(";", mDefaultOverlays));
|
||||
void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) {
|
||||
mSettings.dump(pw, dumpState);
|
||||
if (dumpState.getPackageName() == null) {
|
||||
pw.println("Default overlays: " + TextUtils.join(";", mDefaultOverlays));
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull String[] getDefaultOverlayPackages() {
|
||||
|
||||
@@ -22,6 +22,7 @@ import static com.android.server.om.OverlayManagerService.TAG;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.om.OverlayInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Slog;
|
||||
import android.util.Xml;
|
||||
@@ -288,35 +289,78 @@ final class OverlayManagerSettings {
|
||||
return true;
|
||||
}
|
||||
|
||||
void dump(@NonNull final PrintWriter p) {
|
||||
final IndentingPrintWriter pw = new IndentingPrintWriter(p, " ");
|
||||
pw.println("Settings");
|
||||
pw.increaseIndent();
|
||||
|
||||
if (mItems.isEmpty()) {
|
||||
pw.println("<none>");
|
||||
return;
|
||||
void dump(@NonNull final PrintWriter p, @NonNull DumpState dumpState) {
|
||||
// select items to display
|
||||
Stream<SettingsItem> items = mItems.stream();
|
||||
if (dumpState.getUserId() != UserHandle.USER_ALL) {
|
||||
items = items.filter(item -> item.mUserId == dumpState.getUserId());
|
||||
}
|
||||
if (dumpState.getPackageName() != null) {
|
||||
items = items.filter(item -> item.mPackageName.equals(dumpState.getPackageName()));
|
||||
}
|
||||
|
||||
final int n = mItems.size();
|
||||
for (int i = 0; i < n; i++) {
|
||||
final SettingsItem item = mItems.get(i);
|
||||
pw.println(item.mPackageName + ":" + item.getUserId() + " {");
|
||||
pw.increaseIndent();
|
||||
// display items
|
||||
final IndentingPrintWriter pw = new IndentingPrintWriter(p, " ");
|
||||
if (dumpState.getField() != null) {
|
||||
items.forEach(item -> dumpSettingsItemField(pw, item, dumpState.getField()));
|
||||
} else {
|
||||
items.forEach(item -> dumpSettingsItem(pw, item));
|
||||
}
|
||||
}
|
||||
|
||||
pw.println("mPackageName...........: " + item.mPackageName);
|
||||
pw.println("mUserId................: " + item.getUserId());
|
||||
pw.println("mTargetPackageName.....: " + item.getTargetPackageName());
|
||||
pw.println("mTargetOverlayableName.: " + item.getTargetOverlayableName());
|
||||
pw.println("mBaseCodePath..........: " + item.getBaseCodePath());
|
||||
pw.println("mState.................: " + OverlayInfo.stateToString(item.getState()));
|
||||
pw.println("mIsEnabled.............: " + item.isEnabled());
|
||||
pw.println("mIsStatic..............: " + item.isStatic());
|
||||
pw.println("mPriority..............: " + item.mPriority);
|
||||
pw.println("mCategory..............: " + item.mCategory);
|
||||
private void dumpSettingsItem(@NonNull final IndentingPrintWriter pw,
|
||||
@NonNull final SettingsItem item) {
|
||||
pw.println(item.mPackageName + ":" + item.getUserId() + " {");
|
||||
pw.increaseIndent();
|
||||
|
||||
pw.decreaseIndent();
|
||||
pw.println("}");
|
||||
pw.println("mPackageName...........: " + item.mPackageName);
|
||||
pw.println("mUserId................: " + item.getUserId());
|
||||
pw.println("mTargetPackageName.....: " + item.getTargetPackageName());
|
||||
pw.println("mTargetOverlayableName.: " + item.getTargetOverlayableName());
|
||||
pw.println("mBaseCodePath..........: " + item.getBaseCodePath());
|
||||
pw.println("mState.................: " + OverlayInfo.stateToString(item.getState()));
|
||||
pw.println("mIsEnabled.............: " + item.isEnabled());
|
||||
pw.println("mIsStatic..............: " + item.isStatic());
|
||||
pw.println("mPriority..............: " + item.mPriority);
|
||||
pw.println("mCategory..............: " + item.mCategory);
|
||||
|
||||
pw.decreaseIndent();
|
||||
pw.println("}");
|
||||
}
|
||||
|
||||
private void dumpSettingsItemField(@NonNull final IndentingPrintWriter pw,
|
||||
@NonNull final SettingsItem item, @NonNull final String field) {
|
||||
switch (field) {
|
||||
case "packagename":
|
||||
pw.println(item.mPackageName);
|
||||
break;
|
||||
case "userid":
|
||||
pw.println(item.mUserId);
|
||||
break;
|
||||
case "targetpackagename":
|
||||
pw.println(item.mTargetPackageName);
|
||||
break;
|
||||
case "targetoverlayablename":
|
||||
pw.println(item.mTargetOverlayableName);
|
||||
break;
|
||||
case "basecodepath":
|
||||
pw.println(item.mBaseCodePath);
|
||||
break;
|
||||
case "state":
|
||||
pw.println(OverlayInfo.stateToString(item.mState));
|
||||
break;
|
||||
case "isenabled":
|
||||
pw.println(item.mIsEnabled);
|
||||
break;
|
||||
case "isstatic":
|
||||
pw.println(item.mIsStatic);
|
||||
break;
|
||||
case "priority":
|
||||
pw.println(item.mPriority);
|
||||
break;
|
||||
case "category":
|
||||
pw.println(item.mCategory);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,13 +77,17 @@ final class OverlayManagerShellCommand extends ShellCommand {
|
||||
out.println("Overlay manager (overlay) commands:");
|
||||
out.println(" help");
|
||||
out.println(" Print this help text.");
|
||||
out.println(" dump [--verbose] [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
|
||||
out.println(" dump [--verbose] [--user USER_ID] [[FIELD] PACKAGE]");
|
||||
out.println(" Print debugging information about the overlay manager.");
|
||||
out.println(" list [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
|
||||
out.println(" With optional parameter PACKAGE, limit output to the specified");
|
||||
out.println(" package. With optional parameter FIELD, limit output to");
|
||||
out.println(" the value of that SettingsItem field. Field names are");
|
||||
out.println(" case insensitive and out.println the m prefix can be omitted,");
|
||||
out.println(" so the following are equivalent: mState, mstate, State, state.");
|
||||
out.println(" list [--user USER_ID] [PACKAGE]");
|
||||
out.println(" Print information about target and overlay packages.");
|
||||
out.println(" Overlay packages are printed in priority order. With optional");
|
||||
out.println(" parameters PACKAGEs, limit output to the specified packages");
|
||||
out.println(" but include more information about each package.");
|
||||
out.println(" parameter PACKAGE, limit output to the specified package.");
|
||||
out.println(" enable [--user USER_ID] PACKAGE");
|
||||
out.println(" Enable overlay package PACKAGE.");
|
||||
out.println(" disable [--user USER_ID] PACKAGE");
|
||||
@@ -116,14 +120,20 @@ final class OverlayManagerShellCommand extends ShellCommand {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
final String packageName = getNextArg();
|
||||
|
||||
final Map<String, List<OverlayInfo>> allOverlays = mInterface.getAllOverlays(userId);
|
||||
for (final String targetPackageName : allOverlays.keySet()) {
|
||||
out.println(targetPackageName);
|
||||
if (targetPackageName.equals(packageName)) {
|
||||
out.println(targetPackageName);
|
||||
}
|
||||
List<OverlayInfo> overlaysForTarget = allOverlays.get(targetPackageName);
|
||||
final int n = overlaysForTarget.size();
|
||||
for (int i = 0; i < n; i++) {
|
||||
final OverlayInfo oi = overlaysForTarget.get(i);
|
||||
if (!targetPackageName.equals(packageName) && !oi.packageName.equals(packageName)) {
|
||||
continue;
|
||||
}
|
||||
String status;
|
||||
switch (oi.state) {
|
||||
case OverlayInfo.STATE_ENABLED_STATIC:
|
||||
@@ -139,7 +149,9 @@ final class OverlayManagerShellCommand extends ShellCommand {
|
||||
}
|
||||
out.println(String.format("%s %s", status, oi.packageName));
|
||||
}
|
||||
out.println();
|
||||
if (targetPackageName.equals(packageName)) {
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user