1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.om; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.om.IOverlayManager; 22 import android.content.om.OverlayInfo; 23 import android.os.RemoteException; 24 import android.os.ShellCommand; 25 import android.os.UserHandle; 26 27 import java.io.PrintWriter; 28 import java.util.List; 29 import java.util.Map; 30 31 /** 32 * Implementation of 'cmd overlay' commands. 33 * 34 * This class provides an interface to the OverlayManagerService via adb. 35 * Intended only for manual debugging. Execute 'adb exec-out cmd overlay help' 36 * for a list of available commands. 37 */ 38 final class OverlayManagerShellCommand extends ShellCommand { 39 private final IOverlayManager mInterface; 40 OverlayManagerShellCommand(@onNull final IOverlayManager iom)41 OverlayManagerShellCommand(@NonNull final IOverlayManager iom) { 42 mInterface = iom; 43 } 44 45 @Override onCommand(@ullable final String cmd)46 public int onCommand(@Nullable final String cmd) { 47 if (cmd == null) { 48 return handleDefaultCommands(cmd); 49 } 50 final PrintWriter err = getErrPrintWriter(); 51 try { 52 switch (cmd) { 53 case "list": 54 return runList(); 55 case "enable": 56 return runEnableDisable(true); 57 case "disable": 58 return runEnableDisable(false); 59 case "enable-exclusive": 60 return runEnableExclusive(); 61 case "set-priority": 62 return runSetPriority(); 63 default: 64 return handleDefaultCommands(cmd); 65 } 66 } catch (IllegalArgumentException e) { 67 err.println("Error: " + e.getMessage()); 68 } catch (RemoteException e) { 69 err.println("Remote exception: " + e); 70 } 71 return -1; 72 } 73 74 @Override onHelp()75 public void onHelp() { 76 final PrintWriter out = getOutPrintWriter(); 77 out.println("Overlay manager (overlay) commands:"); 78 out.println(" help"); 79 out.println(" Print this help text."); 80 out.println(" dump [--verbose] [--user USER_ID] [[FIELD] PACKAGE]"); 81 out.println(" Print debugging information about the overlay manager."); 82 out.println(" With optional parameter PACKAGE, limit output to the specified"); 83 out.println(" package. With optional parameter FIELD, limit output to"); 84 out.println(" the value of that SettingsItem field. Field names are"); 85 out.println(" case insensitive and out.println the m prefix can be omitted,"); 86 out.println(" so the following are equivalent: mState, mstate, State, state."); 87 out.println(" list [--user USER_ID] [PACKAGE]"); 88 out.println(" Print information about target and overlay packages."); 89 out.println(" Overlay packages are printed in priority order. With optional"); 90 out.println(" parameter PACKAGE, limit output to the specified package."); 91 out.println(" enable [--user USER_ID] PACKAGE"); 92 out.println(" Enable overlay package PACKAGE."); 93 out.println(" disable [--user USER_ID] PACKAGE"); 94 out.println(" Disable overlay package PACKAGE."); 95 out.println(" enable-exclusive [--user USER_ID] [--category] PACKAGE"); 96 out.println(" Enable overlay package PACKAGE and disable all other overlays for"); 97 out.println(" its target package. If the --category option is given, only disables"); 98 out.println(" other overlays in the same category."); 99 out.println(" set-priority [--user USER_ID] PACKAGE PARENT|lowest|highest"); 100 out.println(" Change the priority of the overlay PACKAGE to be just higher than"); 101 out.println(" the priority of PACKAGE_PARENT If PARENT is the special keyword"); 102 out.println(" 'lowest', change priority of PACKAGE to the lowest priority."); 103 out.println(" If PARENT is the special keyword 'highest', change priority of"); 104 out.println(" PACKAGE to the highest priority."); 105 } 106 runList()107 private int runList() throws RemoteException { 108 final PrintWriter out = getOutPrintWriter(); 109 final PrintWriter err = getErrPrintWriter(); 110 111 int userId = UserHandle.USER_SYSTEM; 112 String opt; 113 while ((opt = getNextOption()) != null) { 114 switch (opt) { 115 case "--user": 116 userId = UserHandle.parseUserArg(getNextArgRequired()); 117 break; 118 default: 119 err.println("Error: Unknown option: " + opt); 120 return 1; 121 } 122 } 123 124 final String packageName = getNextArg(); 125 if (packageName != null) { 126 List<OverlayInfo> overlaysForTarget = mInterface.getOverlayInfosForTarget( 127 packageName, userId); 128 129 // If the package is not targeted by any overlays, check if the package is an overlay. 130 if (overlaysForTarget.isEmpty()) { 131 final OverlayInfo info = mInterface.getOverlayInfo(packageName, userId); 132 if (info != null) { 133 printListOverlay(out, info); 134 } 135 return 0; 136 } 137 138 out.println(packageName); 139 140 // Print the overlays for the target. 141 final int n = overlaysForTarget.size(); 142 for (int i = 0; i < n; i++) { 143 printListOverlay(out, overlaysForTarget.get(i)); 144 } 145 146 return 0; 147 } 148 149 // Print all overlays grouped by target package name. 150 final Map<String, List<OverlayInfo>> allOverlays = mInterface.getAllOverlays(userId); 151 for (final String targetPackageName : allOverlays.keySet()) { 152 out.println(targetPackageName); 153 154 List<OverlayInfo> overlaysForTarget = allOverlays.get(targetPackageName); 155 final int n = overlaysForTarget.size(); 156 for (int i = 0; i < n; i++) { 157 printListOverlay(out, overlaysForTarget.get(i)); 158 } 159 out.println(); 160 } 161 162 return 0; 163 } 164 printListOverlay(PrintWriter out, OverlayInfo oi)165 private void printListOverlay(PrintWriter out, OverlayInfo oi) { 166 String status; 167 switch (oi.state) { 168 case OverlayInfo.STATE_ENABLED_STATIC: 169 case OverlayInfo.STATE_ENABLED: 170 status = "[x]"; 171 break; 172 case OverlayInfo.STATE_DISABLED: 173 status = "[ ]"; 174 break; 175 default: 176 status = "---"; 177 break; 178 } 179 out.println(String.format("%s %s", status, oi.packageName)); 180 } 181 runEnableDisable(final boolean enable)182 private int runEnableDisable(final boolean enable) throws RemoteException { 183 final PrintWriter err = getErrPrintWriter(); 184 185 int userId = UserHandle.USER_SYSTEM; 186 String opt; 187 while ((opt = getNextOption()) != null) { 188 switch (opt) { 189 case "--user": 190 userId = UserHandle.parseUserArg(getNextArgRequired()); 191 break; 192 default: 193 err.println("Error: Unknown option: " + opt); 194 return 1; 195 } 196 } 197 198 final String packageName = getNextArgRequired(); 199 return mInterface.setEnabled(packageName, enable, userId) ? 0 : 1; 200 } 201 runEnableExclusive()202 private int runEnableExclusive() throws RemoteException { 203 final PrintWriter err = getErrPrintWriter(); 204 205 int userId = UserHandle.USER_SYSTEM; 206 boolean inCategory = false; 207 String opt; 208 while ((opt = getNextOption()) != null) { 209 switch (opt) { 210 case "--user": 211 userId = UserHandle.parseUserArg(getNextArgRequired()); 212 break; 213 case "--category": 214 inCategory = true; 215 break; 216 default: 217 err.println("Error: Unknown option: " + opt); 218 return 1; 219 } 220 } 221 final String overlay = getNextArgRequired(); 222 if (inCategory) { 223 return mInterface.setEnabledExclusiveInCategory(overlay, userId) ? 0 : 1; 224 } else { 225 return mInterface.setEnabledExclusive(overlay, true, userId) ? 0 : 1; 226 } 227 } 228 runSetPriority()229 private int runSetPriority() throws RemoteException { 230 final PrintWriter err = getErrPrintWriter(); 231 232 int userId = UserHandle.USER_SYSTEM; 233 String opt; 234 while ((opt = getNextOption()) != null) { 235 switch (opt) { 236 case "--user": 237 userId = UserHandle.parseUserArg(getNextArgRequired()); 238 break; 239 default: 240 err.println("Error: Unknown option: " + opt); 241 return 1; 242 } 243 } 244 245 final String packageName = getNextArgRequired(); 246 final String newParentPackageName = getNextArgRequired(); 247 248 if ("highest".equals(newParentPackageName)) { 249 return mInterface.setHighestPriority(packageName, userId) ? 0 : 1; 250 } else if ("lowest".equals(newParentPackageName)) { 251 return mInterface.setLowestPriority(packageName, userId) ? 0 : 1; 252 } else { 253 return mInterface.setPriority(packageName, newParentPackageName, userId) ? 0 : 1; 254 } 255 } 256 } 257