blob: f9ff5149e54c572c319678439679ad3baf6a6ff8 [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.pm;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertContains;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertSuccess;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.readAll;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.resultContains;
import android.content.ComponentName;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.frameworks.servicestests.R;
import com.android.server.pm.ShortcutService.ConfigConstants;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Unit test for "cmd shortcut"
*
* Launcher related commands are tested in
*/
@SmallTest
public class ShortcutManagerTest7 extends BaseShortcutManagerTest {
private List<String> callShellCommand(String... args) throws IOException, RemoteException {
// For reset to work, the current time needs to be incrementing.
mInjectedCurrentTimeMillis++;
final AtomicInteger resultCode = new AtomicInteger(Integer.MIN_VALUE);
final ResultReceiver rr = new ResultReceiver(mHandler) {
@Override
public void send(int resultCode_, Bundle resultData) {
resultCode.set(resultCode_);
}
};
final File out = File.createTempFile("shellout-", ".tmp",
getTestContext().getCacheDir());
try {
try (final ParcelFileDescriptor fd = ParcelFileDescriptor.open(out,
ParcelFileDescriptor.MODE_READ_WRITE)) {
mService.onShellCommand(
/* fdin*/ null,
/* fdout*/ fd.getFileDescriptor(),
/* fderr*/ fd.getFileDescriptor(),
args, rr);
}
return readAll(out);
} finally {
out.delete();
}
}
public void testNonShell() throws Exception {
mService.mMaxUpdatesPerInterval = 99;
mInjectedCallingUid = 12345;
assertExpectException(SecurityException.class, "must be shell",
() -> callShellCommand("reset-config"));
mInjectedCallingUid = Process.SYSTEM_UID;
assertExpectException(SecurityException.class, "must be shell",
() -> callShellCommand("reset-config"));
assertEquals(99, mService.mMaxUpdatesPerInterval);
}
public void testRoot() throws Exception {
mService.mMaxUpdatesPerInterval = 99;
mInjectedCallingUid = Process.ROOT_UID;
assertSuccess(callShellCommand("reset-config"));
assertEquals(3, mService.mMaxUpdatesPerInterval);
}
public void testRestConfig() throws Exception {
mService.mMaxUpdatesPerInterval = 99;
mInjectedCallingUid = Process.SHELL_UID;
assertSuccess(callShellCommand("reset-config"));
assertEquals(3, mService.mMaxUpdatesPerInterval);
}
public void testOverrideConfig() throws Exception {
mService.mMaxUpdatesPerInterval = 99;
mInjectedCallingUid = Process.SHELL_UID;
assertSuccess(callShellCommand("override-config",
ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=1"));
assertEquals(1, mService.mMaxUpdatesPerInterval);
}
public void testResetThrottling() throws Exception {
prepareCrossProfileDataSet();
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
mInjectedCallingUid = Process.SHELL_UID;
assertSuccess(callShellCommand("reset-throttling"));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
}
public void testResetThrottling_user_not_running() throws Exception {
prepareCrossProfileDataSet();
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
mInjectedCallingUid = Process.SHELL_UID;
assertTrue(resultContains(
callShellCommand("reset-throttling", "--user", "10"),
"User 10 is not running or locked"));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
}
public void testResetThrottling_user_running() throws Exception {
prepareCrossProfileDataSet();
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
mRunningUsers.put(USER_10, true);
mUnlockedUsers.put(USER_10, true);
mInjectedCallingUid = Process.SHELL_UID;
assertSuccess(callShellCommand("reset-throttling", "--user", "10"));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
}
public void testResetAllThrottling() throws Exception {
prepareCrossProfileDataSet();
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.getRemainingCallCount() < 3);
});
mInjectedCallingUid = Process.SHELL_UID;
assertSuccess(callShellCommand("reset-all-throttling"));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
}
public void testLauncherCommands() throws Exception {
prepareGetHomeActivitiesAsUser(
/* preferred */ null,
list(getSystemLauncher(), getFallbackLauncher()),
USER_0);
prepareGetHomeActivitiesAsUser(
/* preferred */ cn(CALLING_PACKAGE_2, "name"),
list(getSystemLauncher(), getFallbackLauncher(),
ri(CALLING_PACKAGE_1, "name", false, 0),
ri(CALLING_PACKAGE_2, "name", false, 0)
),
USER_10);
assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
// First, test "get".
mRunningUsers.put(USER_10, true);
mUnlockedUsers.put(USER_10, true);
mInjectedCallingUid = Process.SHELL_UID;
assertContains(
assertSuccess(callShellCommand("get-default-launcher")),
"Launcher: ComponentInfo{com.android.systemlauncher/systemlauncher_name}");
assertContains(
assertSuccess(callShellCommand("get-default-launcher", "--user", "10")),
"Launcher: ComponentInfo{com.android.test.2/name}");
// Next, test "clear".
assertSuccess(callShellCommand("clear-default-launcher", "--user", "10"));
// User-10's launcher should be cleared.
assertEquals(null, mService.getUserShortcutsLocked(USER_10).getLastKnownLauncher());
assertEquals(null, mService.getUserShortcutsLocked(USER_10).getCachedLauncher());
// but user'0's shouldn't.
assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
// Change user-0's launcher.
prepareGetHomeActivitiesAsUser(
/* preferred */ cn(CALLING_PACKAGE_1, "name"),
list(
ri(CALLING_PACKAGE_1, "name", false, 0)
),
USER_0);
assertContains(
assertSuccess(callShellCommand("get-default-launcher")),
"Launcher: ComponentInfo{com.android.test.1/name}");
}
public void testUnloadUser() throws Exception {
prepareCrossProfileDataSet();
assertNotNull(mService.getShortcutsForTest().get(USER_10));
mRunningUsers.put(USER_10, true);
mUnlockedUsers.put(USER_10, true);
mInjectedCallingUid = Process.SHELL_UID;
assertSuccess(callShellCommand("unload-user", "--user", "10"));
assertNull(mService.getShortcutsForTest().get(USER_10));
}
public void testClearShortcuts() throws Exception {
mRunningUsers.put(USER_10, true);
// Add two manifests and two dynamics.
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.addDynamicShortcuts(list(
makeShortcut("s1"), makeShortcut("s2"))));
});
runWithCaller(LAUNCHER_1, USER_10, () -> {
mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_10);
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertWith(getCallerShortcuts())
.haveIds("ms1", "ms2", "s1", "s2")
.areAllEnabled()
.selectPinned()
.haveIds("ms2", "s2");
});
// First, call for a different package.
mRunningUsers.put(USER_10, true);
mUnlockedUsers.put(USER_10, true);
mInjectedCallingUid = Process.SHELL_UID;
assertSuccess(callShellCommand("clear-shortcuts", "--user", "10", CALLING_PACKAGE_2));
// Shouldn't be cleared yet.
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertWith(getCallerShortcuts())
.haveIds("ms1", "ms2", "s1", "s2")
.areAllEnabled()
.selectPinned()
.haveIds("ms2", "s2");
});
mInjectedCallingUid = Process.SHELL_UID;
assertSuccess(callShellCommand("clear-shortcuts", "--user", "10", CALLING_PACKAGE_1));
// Only manifest shortcuts will remain, and are no longer pinned.
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertWith(getCallerShortcuts())
.haveIds("ms1", "ms2")
.areAllEnabled()
.areAllNotPinned();
});
}
}