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 */ 16package com.android.server.pm; 17 18import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.array; 19import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertContains; 20import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException; 21import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertSuccess; 22import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith; 23import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list; 24import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.readAll; 25import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.resultContains; 26 27import android.content.ComponentName; 28import android.os.Bundle; 29import android.os.ParcelFileDescriptor; 30import android.os.Process; 31import android.os.RemoteException; 32import android.os.ResultReceiver; 33import android.test.suitebuilder.annotation.SmallTest; 34 35import com.android.frameworks.servicestests.R; 36import com.android.server.pm.ShortcutService.ConfigConstants; 37 38import java.io.File; 39import java.io.IOException; 40import java.util.List; 41import java.util.concurrent.atomic.AtomicInteger; 42 43/** 44 * Unit test for "cmd shortcut" and "dumpsys shortcut". 45 * 46 * Launcher related commands are tested in 47 */ 48@SmallTest 49public class ShortcutManagerTest7 extends BaseShortcutManagerTest { 50 private List<String> callShellCommand(String... args) throws IOException, RemoteException { 51 52 // For reset to work, the current time needs to be incrementing. 53 mInjectedCurrentTimeMillis++; 54 55 final AtomicInteger resultCode = new AtomicInteger(Integer.MIN_VALUE); 56 57 final ResultReceiver rr = new ResultReceiver(mHandler) { 58 @Override 59 public void send(int resultCode_, Bundle resultData) { 60 resultCode.set(resultCode_); 61 } 62 }; 63 final File out = File.createTempFile("shellout-", ".tmp", 64 getTestContext().getCacheDir()); 65 try { 66 try (final ParcelFileDescriptor fd = ParcelFileDescriptor.open(out, 67 ParcelFileDescriptor.MODE_READ_WRITE)) { 68 mService.onShellCommand( 69 /* fdin*/ null, 70 /* fdout*/ fd.getFileDescriptor(), 71 /* fderr*/ fd.getFileDescriptor(), 72 args, null, rr); 73 } 74 return readAll(out); 75 } finally { 76 out.delete(); 77 } 78 } 79 80 public void testNonShell() throws Exception { 81 mService.mMaxUpdatesPerInterval = 99; 82 83 mInjectedCallingUid = 12345; 84 assertExpectException(SecurityException.class, "must be shell", 85 () -> callShellCommand("reset-config")); 86 87 mInjectedCallingUid = Process.SYSTEM_UID; 88 assertExpectException(SecurityException.class, "must be shell", 89 () -> callShellCommand("reset-config")); 90 91 assertEquals(99, mService.mMaxUpdatesPerInterval); 92 } 93 94 public void testRoot() throws Exception { 95 mService.mMaxUpdatesPerInterval = 99; 96 97 mInjectedCallingUid = Process.ROOT_UID; 98 assertSuccess(callShellCommand("reset-config")); 99 100 assertEquals(3, mService.mMaxUpdatesPerInterval); 101 } 102 103 public void testRestConfig() throws Exception { 104 mService.mMaxUpdatesPerInterval = 99; 105 106 mInjectedCallingUid = Process.SHELL_UID; 107 assertSuccess(callShellCommand("reset-config")); 108 109 assertEquals(3, mService.mMaxUpdatesPerInterval); 110 } 111 112 public void testOverrideConfig() throws Exception { 113 mService.mMaxUpdatesPerInterval = 99; 114 115 mInjectedCallingUid = Process.SHELL_UID; 116 assertSuccess(callShellCommand("override-config", 117 ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=1")); 118 119 assertEquals(1, mService.mMaxUpdatesPerInterval); 120 } 121 122 public void testResetThrottling() throws Exception { 123 prepareCrossProfileDataSet(); 124 125 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 126 assertTrue(mManager.getRemainingCallCount() < 3); 127 }); 128 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 129 assertTrue(mManager.getRemainingCallCount() < 3); 130 }); 131 132 mInjectedCallingUid = Process.SHELL_UID; 133 assertSuccess(callShellCommand("reset-throttling")); 134 135 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 136 assertEquals(3, mManager.getRemainingCallCount()); 137 }); 138 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 139 assertTrue(mManager.getRemainingCallCount() < 3); 140 }); 141 } 142 143 public void testResetThrottling_user_not_running() throws Exception { 144 prepareCrossProfileDataSet(); 145 146 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 147 assertTrue(mManager.getRemainingCallCount() < 3); 148 }); 149 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 150 assertTrue(mManager.getRemainingCallCount() < 3); 151 }); 152 153 mInjectedCallingUid = Process.SHELL_UID; 154 155 mRunningUsers.put(USER_10, false); 156 157 assertTrue(resultContains( 158 callShellCommand("reset-throttling", "--user", "10"), 159 "User 10 is not running or locked")); 160 161 mRunningUsers.put(USER_10, true); 162 163 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 164 assertTrue(mManager.getRemainingCallCount() < 3); 165 }); 166 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 167 assertTrue(mManager.getRemainingCallCount() < 3); 168 }); 169 } 170 171 public void testResetThrottling_user_running() throws Exception { 172 prepareCrossProfileDataSet(); 173 174 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 175 assertTrue(mManager.getRemainingCallCount() < 3); 176 }); 177 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 178 assertTrue(mManager.getRemainingCallCount() < 3); 179 }); 180 181 mRunningUsers.put(USER_10, true); 182 mUnlockedUsers.put(USER_10, true); 183 184 mInjectedCallingUid = Process.SHELL_UID; 185 assertSuccess(callShellCommand("reset-throttling", "--user", "10")); 186 187 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 188 assertTrue(mManager.getRemainingCallCount() < 3); 189 }); 190 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 191 assertEquals(3, mManager.getRemainingCallCount()); 192 }); 193 } 194 195 public void testResetAllThrottling() throws Exception { 196 prepareCrossProfileDataSet(); 197 198 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 199 assertTrue(mManager.getRemainingCallCount() < 3); 200 }); 201 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 202 assertTrue(mManager.getRemainingCallCount() < 3); 203 }); 204 205 mInjectedCallingUid = Process.SHELL_UID; 206 assertSuccess(callShellCommand("reset-all-throttling")); 207 208 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { 209 assertEquals(3, mManager.getRemainingCallCount()); 210 }); 211 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 212 assertEquals(3, mManager.getRemainingCallCount()); 213 }); 214 } 215 216 public void testLauncherCommands() throws Exception { 217 prepareGetHomeActivitiesAsUser( 218 /* preferred */ null, 219 list(getSystemLauncher(), getFallbackLauncher()), 220 USER_0); 221 222 prepareGetHomeActivitiesAsUser( 223 /* preferred */ cn(CALLING_PACKAGE_2, "name"), 224 list(getSystemLauncher(), getFallbackLauncher(), 225 ri(CALLING_PACKAGE_1, "name", false, 0), 226 ri(CALLING_PACKAGE_2, "name", false, 0) 227 ), 228 USER_10); 229 230 assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0)); 231 232 // First, test "get". 233 234 mRunningUsers.put(USER_10, true); 235 mUnlockedUsers.put(USER_10, true); 236 mInjectedCallingUid = Process.SHELL_UID; 237 assertContains( 238 assertSuccess(callShellCommand("get-default-launcher")), 239 "Launcher: ComponentInfo{com.android.systemlauncher/systemlauncher_name}"); 240 241 assertContains( 242 assertSuccess(callShellCommand("get-default-launcher", "--user", "10")), 243 "Launcher: ComponentInfo{com.android.test.2/name}"); 244 245 // Next, test "clear". 246 assertSuccess(callShellCommand("clear-default-launcher", "--user", "10")); 247 248 // User-10's launcher should be cleared. 249 assertEquals(null, mService.getUserShortcutsLocked(USER_10).getLastKnownLauncher()); 250 assertEquals(null, mService.getUserShortcutsLocked(USER_10).getCachedLauncher()); 251 252 // but user'0's shouldn't. 253 assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME), 254 mService.getUserShortcutsLocked(USER_0).getCachedLauncher()); 255 256 // Change user-0's launcher. 257 prepareGetHomeActivitiesAsUser( 258 /* preferred */ cn(CALLING_PACKAGE_1, "name"), 259 list( 260 ri(CALLING_PACKAGE_1, "name", false, 0) 261 ), 262 USER_0); 263 assertContains( 264 assertSuccess(callShellCommand("get-default-launcher")), 265 "Launcher: ComponentInfo{com.android.test.1/name}"); 266 } 267 268 public void testUnloadUser() throws Exception { 269 prepareCrossProfileDataSet(); 270 271 assertNotNull(mService.getShortcutsForTest().get(USER_10)); 272 273 mRunningUsers.put(USER_10, true); 274 mUnlockedUsers.put(USER_10, true); 275 276 mInjectedCallingUid = Process.SHELL_UID; 277 assertSuccess(callShellCommand("unload-user", "--user", "10")); 278 279 assertNull(mService.getShortcutsForTest().get(USER_10)); 280 } 281 282 public void testClearShortcuts() throws Exception { 283 284 mRunningUsers.put(USER_10, true); 285 286 // Add two manifests and two dynamics. 287 addManifestShortcutResource( 288 new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()), 289 R.xml.shortcut_2); 290 updatePackageVersion(CALLING_PACKAGE_1, 1); 291 mService.mPackageMonitor.onReceive(getTestContext(), 292 genPackageAddIntent(CALLING_PACKAGE_1, USER_10)); 293 294 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 295 assertTrue(mManager.addDynamicShortcuts(list( 296 makeShortcut("s1"), makeShortcut("s2")))); 297 }); 298 runWithCaller(LAUNCHER_1, USER_10, () -> { 299 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_10); 300 }); 301 302 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 303 assertWith(getCallerShortcuts()) 304 .haveIds("ms1", "ms2", "s1", "s2") 305 .areAllEnabled() 306 307 .selectPinned() 308 .haveIds("ms2", "s2"); 309 }); 310 311 // First, call for a different package. 312 313 mRunningUsers.put(USER_10, true); 314 mUnlockedUsers.put(USER_10, true); 315 316 mInjectedCallingUid = Process.SHELL_UID; 317 assertSuccess(callShellCommand("clear-shortcuts", "--user", "10", CALLING_PACKAGE_2)); 318 319 // Shouldn't be cleared yet. 320 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 321 assertWith(getCallerShortcuts()) 322 .haveIds("ms1", "ms2", "s1", "s2") 323 .areAllEnabled() 324 325 .selectPinned() 326 .haveIds("ms2", "s2"); 327 }); 328 329 mInjectedCallingUid = Process.SHELL_UID; 330 assertSuccess(callShellCommand("clear-shortcuts", "--user", "10", CALLING_PACKAGE_1)); 331 332 // Only manifest shortcuts will remain, and are no longer pinned. 333 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { 334 assertWith(getCallerShortcuts()) 335 .haveIds("ms1", "ms2") 336 .areAllEnabled() 337 .areAllNotPinned(); 338 }); 339 } 340 341 public void testDumpsysArgs() { 342 checkDumpsysArgs(null, true, false, false); 343 checkDumpsysArgs(array("-u"), true, true, false); 344 checkDumpsysArgs(array("--uid"), true, true, false); 345 346 checkDumpsysArgs(array("-f"), true, false, true); 347 checkDumpsysArgs(array("--files"), true, false, true); 348 349 checkDumpsysArgs(array("-a"), true, true, true); 350 checkDumpsysArgs(array("--all"), true, true, true); 351 352 checkDumpsysArgs(array("-a", "-n"), false, true, true); 353 checkDumpsysArgs(array("-a", "--no-main"), false, true, true); 354 } 355 356 private void checkDumpsysArgs(String[] args, boolean expectMain, boolean expectUid, 357 boolean expectDumpFiles) { 358 String dump = dumpsys(args); 359 360 assertEquals(expectMain, dump.contains("Icon format: PNG")); 361 assertEquals(expectUid, dump.contains("SHORTCUT MANAGER UID STATES")); 362 assertEquals(expectDumpFiles, dump.contains("SHORTCUT MANAGER FILES")); 363 } 364 365} 366