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