Merge "OMS: limit shell command output via optional args" into qt-dev

am: c283f6100d

Change-Id: I0cf89a970bbbbfac0fb5dafbcc8a35f834d2d63c
This commit is contained in:
Mårten Kongstad
2019-05-06 15:24:19 -07:00
committed by android-build-merger
6 changed files with 251 additions and 47 deletions

View File

@@ -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);
}
}

View 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;
}
}

View File

@@ -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++) {

View File

@@ -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() {

View File

@@ -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;
}
}

View File

@@ -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;
}