blob: 99f5839785351e849e0fcfb48120d7dd872ca7d0 [file] [log] [blame]
/*
* Copyright (C) 2016 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.NonNull;
import android.annotation.Nullable;
import android.content.om.IOverlayManager;
import android.content.om.OverlayInfo;
import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.UserHandle;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
/**
* Implementation of 'cmd overlay' commands.
*
* This class provides an interface to the OverlayManagerService via adb.
* Intended only for manual debugging. Execute 'adb exec-out cmd overlay help'
* for a list of available commands.
*/
final class OverlayManagerShellCommand extends ShellCommand {
private final IOverlayManager mInterface;
OverlayManagerShellCommand(@NonNull final IOverlayManager iom) {
mInterface = iom;
}
@Override
public int onCommand(@Nullable final String cmd) {
if (cmd == null) {
return handleDefaultCommands(cmd);
}
final PrintWriter err = getErrPrintWriter();
try {
switch (cmd) {
case "list":
return runList();
case "enable":
return runEnableDisable(true);
case "disable":
return runEnableDisable(false);
case "enable-exclusive":
return runEnableExclusive();
case "set-priority":
return runSetPriority();
default:
return handleDefaultCommands(cmd);
}
} catch (IllegalArgumentException e) {
err.println("Error: " + e.getMessage());
} catch (RemoteException e) {
err.println("Remote exception: " + e);
}
return -1;
}
@Override
public void onHelp() {
final PrintWriter out = getOutPrintWriter();
out.println("Overlay manager (overlay) commands:");
out.println(" help");
out.println(" Print this help text.");
out.println(" dump [--verbose] [--user USER_ID] [[FIELD] PACKAGE]");
out.println(" Print debugging information about the overlay manager.");
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(" 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");
out.println(" Disable overlay package PACKAGE.");
out.println(" enable-exclusive [--user USER_ID] [--category] PACKAGE");
out.println(" Enable overlay package PACKAGE and disable all other overlays for");
out.println(" its target package. If the --category option is given, only disables");
out.println(" other overlays in the same category.");
out.println(" set-priority [--user USER_ID] PACKAGE PARENT|lowest|highest");
out.println(" Change the priority of the overlay PACKAGE to be just higher than");
out.println(" the priority of PACKAGE_PARENT If PARENT is the special keyword");
out.println(" 'lowest', change priority of PACKAGE to the lowest priority.");
out.println(" If PARENT is the special keyword 'highest', change priority of");
out.println(" PACKAGE to the highest priority.");
}
private int runList() throws RemoteException {
final PrintWriter out = getOutPrintWriter();
final PrintWriter err = getErrPrintWriter();
int userId = UserHandle.USER_SYSTEM;
String opt;
while ((opt = getNextOption()) != null) {
switch (opt) {
case "--user":
userId = UserHandle.parseUserArg(getNextArgRequired());
break;
default:
err.println("Error: Unknown option: " + opt);
return 1;
}
}
final String packageName = getNextArg();
if (packageName != null) {
List<OverlayInfo> overlaysForTarget = mInterface.getOverlayInfosForTarget(
packageName, userId);
// If the package is not targeted by any overlays, check if the package is an overlay.
if (overlaysForTarget.isEmpty()) {
final OverlayInfo info = mInterface.getOverlayInfo(packageName, userId);
if (info != null) {
printListOverlay(out, info);
}
return 0;
}
out.println(packageName);
// Print the overlays for the target.
final int n = overlaysForTarget.size();
for (int i = 0; i < n; i++) {
printListOverlay(out, overlaysForTarget.get(i));
}
return 0;
}
// Print all overlays grouped by target package name.
final Map<String, List<OverlayInfo>> allOverlays = mInterface.getAllOverlays(userId);
for (final String targetPackageName : allOverlays.keySet()) {
out.println(targetPackageName);
List<OverlayInfo> overlaysForTarget = allOverlays.get(targetPackageName);
final int n = overlaysForTarget.size();
for (int i = 0; i < n; i++) {
printListOverlay(out, overlaysForTarget.get(i));
}
out.println();
}
return 0;
}
private void printListOverlay(PrintWriter out, OverlayInfo oi) {
String status;
switch (oi.state) {
case OverlayInfo.STATE_ENABLED_STATIC:
case OverlayInfo.STATE_ENABLED:
status = "[x]";
break;
case OverlayInfo.STATE_DISABLED:
status = "[ ]";
break;
default:
status = "---";
break;
}
out.println(String.format("%s %s", status, oi.packageName));
}
private int runEnableDisable(final boolean enable) throws RemoteException {
final PrintWriter err = getErrPrintWriter();
int userId = UserHandle.USER_SYSTEM;
String opt;
while ((opt = getNextOption()) != null) {
switch (opt) {
case "--user":
userId = UserHandle.parseUserArg(getNextArgRequired());
break;
default:
err.println("Error: Unknown option: " + opt);
return 1;
}
}
final String packageName = getNextArgRequired();
return mInterface.setEnabled(packageName, enable, userId) ? 0 : 1;
}
private int runEnableExclusive() throws RemoteException {
final PrintWriter err = getErrPrintWriter();
int userId = UserHandle.USER_SYSTEM;
boolean inCategory = false;
String opt;
while ((opt = getNextOption()) != null) {
switch (opt) {
case "--user":
userId = UserHandle.parseUserArg(getNextArgRequired());
break;
case "--category":
inCategory = true;
break;
default:
err.println("Error: Unknown option: " + opt);
return 1;
}
}
final String overlay = getNextArgRequired();
if (inCategory) {
return mInterface.setEnabledExclusiveInCategory(overlay, userId) ? 0 : 1;
} else {
return mInterface.setEnabledExclusive(overlay, true, userId) ? 0 : 1;
}
}
private int runSetPriority() throws RemoteException {
final PrintWriter err = getErrPrintWriter();
int userId = UserHandle.USER_SYSTEM;
String opt;
while ((opt = getNextOption()) != null) {
switch (opt) {
case "--user":
userId = UserHandle.parseUserArg(getNextArgRequired());
break;
default:
err.println("Error: Unknown option: " + opt);
return 1;
}
}
final String packageName = getNextArgRequired();
final String newParentPackageName = getNextArgRequired();
if ("highest".equals(newParentPackageName)) {
return mInterface.setHighestPriority(packageName, userId) ? 0 : 1;
} else if ("lowest".equals(newParentPackageName)) {
return mInterface.setLowestPriority(packageName, userId) ? 0 : 1;
} else {
return mInterface.setPriority(packageName, newParentPackageName, userId) ? 0 : 1;
}
}
}