/* * 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 "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] [PACKAGE [PACKAGE [...]]]"); out.println(" Print debugging information about the overlay manager."); out.println(" list [--user USER_ID] [PACKAGE [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(" 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(" 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 Map> allOverlays = mInterface.getAllOverlays(userId); for (final String targetPackageName : allOverlays.keySet()) { out.println(targetPackageName); List overlaysForTarget = allOverlays.get(targetPackageName); final int N = overlaysForTarget.size(); for (int i = 0; i < N; i++) { final OverlayInfo oi = overlaysForTarget.get(i); String status; switch (oi.state) { 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)); } out.println(); } return 0; } 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 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; } } }