| /* |
| * 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.assertWith; |
| import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list; |
| |
| import android.content.ComponentName; |
| import android.content.pm.ShortcutInfo; |
| import android.test.suitebuilder.annotation.SmallTest; |
| |
| import com.android.frameworks.servicestests.R; |
| import com.android.server.pm.ShortcutService.ConfigConstants; |
| |
| /** |
| * Tests related to shortcut rank auto-adjustment. |
| */ |
| @SmallTest |
| public class ShortcutManagerTest3 extends BaseShortcutManagerTest { |
| |
| private static final String CALLING_PACKAGE = CALLING_PACKAGE_1; |
| |
| private static final ComponentName A1 = new ComponentName(CALLING_PACKAGE, |
| ShortcutActivity.class.getName()); |
| |
| private static final ComponentName A2 = new ComponentName(CALLING_PACKAGE, |
| ShortcutActivity2.class.getName()); |
| |
| private static final ComponentName A3 = new ComponentName(CALLING_PACKAGE, |
| ShortcutActivity3.class.getName()); |
| |
| private ShortcutInfo shortcut(String id, ComponentName activity, int rank) { |
| return makeShortcutWithActivityAndRank(id, activity, rank); |
| } |
| |
| private ShortcutInfo shortcut(String id, ComponentName activity) { |
| return makeShortcutWithActivityAndRank(id, activity, ShortcutInfo.RANK_NOT_SET); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| |
| // We don't need throttling during this test class, and also relax the max cap. |
| mService.updateConfigurationLocked( |
| ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=99999999," |
| + ConfigConstants.KEY_MAX_SHORTCUTS + "=99999999" |
| ); |
| |
| setCaller(CALLING_PACKAGE, USER_0); |
| } |
| |
| private void publishManifestShortcuts(ComponentName activity, int resId) { |
| addManifestShortcutResource(activity, resId); |
| updatePackageVersion(CALLING_PACKAGE, 1); |
| mService.mPackageMonitor.onReceive(getTestContext(), |
| genPackageAddIntent(CALLING_PACKAGE, USER_0)); |
| } |
| |
| public void testSetDynamicShortcuts_noManifestShortcuts() { |
| mManager.setDynamicShortcuts(list( |
| shortcut("s1", A1) |
| )); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s1"); |
| |
| assertTrue(mManager.setDynamicShortcuts(list( |
| shortcut("s5", A1), |
| shortcut("s4", A1), |
| shortcut("s3", A1) |
| ))); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s4", "s3"); |
| |
| // RANK_NOT_SET is always the last. |
| assertTrue(mManager.setDynamicShortcuts(list( |
| shortcut("s5", A1), |
| shortcut("s4", A1, 5), |
| shortcut("s3", A1, 3), |
| shortcut("s2", A1) |
| ))); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s3", "s4", "s5", "s2"); |
| |
| // Same rank, preserve the argument order. |
| assertTrue(mManager.setDynamicShortcuts(list( |
| shortcut("s5", A1, 5), |
| shortcut("s4", A1, 0), |
| shortcut("s3", A1, 5) |
| ))); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s4", "s5", "s3"); |
| |
| // Multiple activities. |
| assertTrue(mManager.setDynamicShortcuts(list( |
| shortcut("s5", A1), |
| shortcut("s4", A2), |
| shortcut("s3", A3) |
| ))); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5"); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("s4"); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A3) |
| .haveRanksInOrder("s3"); |
| |
| assertTrue(mManager.setDynamicShortcuts(list( |
| shortcut("s5", A1, 5), |
| shortcut("s4", A1), |
| shortcut("s3", A1, 5), |
| shortcut("x5", A2, 5), |
| shortcut("x4", A2), |
| shortcut("x3", A2, 1) |
| ))); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s3", "s4"); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x5", "x4"); |
| |
| // Clear. Make sure it wouldn't lead to invalid internals state. |
| // (ShortcutService.verifyStates() will do so internally.) |
| assertTrue(mManager.setDynamicShortcuts(list())); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1).isEmpty(); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2).isEmpty(); |
| } |
| |
| private void runTestWithManifestShortcuts(Runnable r) { |
| publishManifestShortcuts(A1, R.xml.shortcut_5_alt); |
| publishManifestShortcuts(A2, R.xml.shortcut_1); |
| |
| assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A1) |
| .haveRanksInOrder("ms1_alt", "ms2_alt", "ms3_alt", "ms4_alt", "ms5_alt"); |
| |
| assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A2) |
| .haveRanksInOrder("ms1"); |
| |
| // Existence of manifest shortcuts shouldn't affect dynamic shortcut ranks, |
| // so running another test here should pass. |
| r.run(); |
| |
| // And dynamic shortcut tests shouldn't affect manifest shortcuts, so repeat the |
| // same check. |
| assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A1) |
| .haveRanksInOrder("ms1_alt", "ms2_alt", "ms3_alt", "ms4_alt", "ms5_alt"); |
| |
| assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A2) |
| .haveRanksInOrder("ms1"); |
| } |
| |
| public void testSetDynamicShortcuts_withManifestShortcuts() { |
| runTestWithManifestShortcuts(() -> testSetDynamicShortcuts_noManifestShortcuts()); |
| } |
| |
| public void testAddDynamicShortcuts_noManifestShortcuts() { |
| mManager.addDynamicShortcuts(list( |
| shortcut("s1", A1) |
| )); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s1"); |
| |
| //------------------------------------------------------ |
| long lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.addDynamicShortcuts(list( |
| shortcut("s5", A1, 0), |
| shortcut("s4", A1), |
| shortcut("s2", A1, 3), |
| shortcut("x1", A2), |
| shortcut("x3", A2, 2), |
| shortcut("x2", A2, 2), |
| shortcut("s3", A1, 0) |
| )); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s3", "s1", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2", "x1"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .haveIds("s5", "s3", "s1", "s2", "s4", "x3", "x2", "x1"); |
| |
| //------------------------------------------------------ |
| lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.addDynamicShortcuts(list( |
| shortcut("s1", A1, 1) |
| )); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s1", "s3", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2", "x1"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .haveIds("s1", "s3"); |
| |
| //------------------------------------------------------ |
| lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.addDynamicShortcuts(list( |
| shortcut("s1", A1, 1), |
| |
| // This is add, not update, so the following means s5 will have NO_RANK, |
| // which puts it at the end. |
| shortcut("s5", A1), |
| shortcut("s3", A1, 0), |
| |
| // s10 also has NO_RANK, so it'll be put at the end, even after "s5" as we preserve |
| // the argument order. |
| shortcut("s10", A1), |
| |
| // Note we're changing the activity for x2. |
| shortcut("x2", A1, 0), |
| shortcut("x10", A2) |
| )); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s3", "x2", "s1", "s2", "s4", "s5", "s10"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x1", "x10"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .haveIds("s3", "x2", "s1", "s5", "s10", "x1", "x10"); |
| |
| //------------------------------------------------------ |
| lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| // Change the activities again. |
| mManager.addDynamicShortcuts(list( |
| shortcut("s1", A2), |
| shortcut("s2", A2, 999) |
| )); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s3", "x2", "s4", "s5", "s10"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x1", "x10", "s2", "s1"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .haveIds("s1", "s2", "s4", "s5", "s10"); |
| } |
| |
| public void testAddDynamicShortcuts_withManifestShortcuts() { |
| runTestWithManifestShortcuts(() -> testAddDynamicShortcuts_noManifestShortcuts()); |
| } |
| |
| public void testUpdateShortcuts_noManifestShortcuts() { |
| mManager.addDynamicShortcuts(list( |
| shortcut("s5", A1, 0), |
| shortcut("s4", A1), |
| shortcut("s2", A1, 3), |
| shortcut("x1", A2), |
| shortcut("x3", A2, 2), |
| shortcut("x2", A2, 2), |
| shortcut("s3", A1, 0) |
| )); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s3", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2", "x1"); |
| |
| //------------------------------------------------------ |
| long lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.updateShortcuts(list()); |
| // Same order. |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s3", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2", "x1"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .isEmpty(); |
| |
| |
| runWithCaller(LAUNCHER_1, USER_0, () -> { |
| mLauncherApps.pinShortcuts(CALLING_PACKAGE, list("s2", "s4", "x2"), HANDLE_USER_0); |
| }); |
| // Still same order. |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s3", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2", "x1"); |
| |
| //------------------------------------------------------ |
| lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.updateShortcuts(list( |
| shortcut("s4", A1, 1), |
| |
| // Rank not changing, should keep the same positions. |
| // c.f. in case of addDynamicShortcuts, this means "put them at the end". |
| shortcut("s3", A1), |
| shortcut("x2", A2) |
| )); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s4", "s3", "s2"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2", "x1"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .haveIds("s4", "s3", "s2", "x2"); |
| |
| //------------------------------------------------------ |
| lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.updateShortcuts(list( |
| shortcut("s4", A1, 0), |
| |
| // Change the activity without specifying a rank -> keep the same rank. |
| shortcut("s5", A2), |
| |
| // Change the activity without specifying a rank -> assign a new rank. |
| shortcut("x2", A1, 2), |
| |
| // "xx" doesn't exist, so it'll be ignored. |
| shortcut("xx", A1, 0) |
| )); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s4", "x2", "s3", "s2"); |
| |
| // Interesting case: both x3 and s5 originally had rank=0, and in this case s5 has moved |
| // to A2 without changing the rank. So they're tie for the new rank, as well as |
| // the "rank changed" bit. Also in this case, "s5" won't have an implicit order, since |
| // its rank isn't changing. So we sort them by ID, thus s5 comes before x3. |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("s5", "x3", "x1"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .haveIds("s4", "x2", "s5", "x3"); |
| |
| //------------------------------------------------------ |
| lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.updateShortcuts(list( |
| shortcut("s3", A3))); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s4", "x2", "s2"); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("s5", "x3", "x1"); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A3) |
| .haveRanksInOrder("s3"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .haveIds("s3", "s2"); |
| } |
| |
| public void testUpdateShortcuts_withManifestShortcuts() { |
| runTestWithManifestShortcuts(() -> testUpdateShortcuts_noManifestShortcuts()); |
| } |
| |
| public void testDeleteDynamicShortcuts_noManifestShortcuts() { |
| mManager.addDynamicShortcuts(list( |
| shortcut("s5", A1, 0), |
| shortcut("s4", A1), |
| shortcut("s2", A1, 3), |
| shortcut("x1", A2), |
| shortcut("x3", A2, 2), |
| shortcut("x2", A2, 2), |
| shortcut("s3", A1, 0) |
| )); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s3", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2", "x1"); |
| |
| //------------------------------------------------------ |
| long lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.removeDynamicShortcuts(list()); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s3", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2", "x1"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .isEmpty(); |
| |
| runWithCaller(LAUNCHER_1, USER_0, () -> { |
| mLauncherApps.pinShortcuts( |
| CALLING_PACKAGE, list("s2", "s4", "x1", "x2"), HANDLE_USER_0); |
| }); |
| // Still same order. |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s3", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2", "x1"); |
| |
| //------------------------------------------------------ |
| lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.removeDynamicShortcuts(list("s3", "x1", "xxxx")); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .haveIds("s2", "s4"); |
| } |
| |
| public void testDeleteDynamicShortcuts_withManifestShortcuts() { |
| runTestWithManifestShortcuts(() -> testDeleteDynamicShortcuts_noManifestShortcuts()); |
| } |
| |
| public void testDisableShortcuts_noManifestShortcuts() { |
| mManager.addDynamicShortcuts(list( |
| shortcut("s5", A1, 0), |
| shortcut("s4", A1), |
| shortcut("s2", A1, 3), |
| shortcut("x1", A2), |
| shortcut("x3", A2, 2), |
| shortcut("x2", A2, 2), |
| shortcut("s3", A1, 0) |
| )); |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s3", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2", "x1"); |
| |
| //------------------------------------------------------ |
| long lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.disableShortcuts(list()); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s3", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2", "x1"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .isEmpty(); |
| |
| //------------------------------------------------------ |
| lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.disableShortcuts(list("s3", "x1", "xxxx")); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .haveIds("s2", "s4"); |
| |
| runWithCaller(LAUNCHER_1, USER_0, () -> { |
| mLauncherApps.pinShortcuts(CALLING_PACKAGE, list("s2", "s4", "x2"), HANDLE_USER_0); |
| }); |
| // Still same order. |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s2", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x3", "x2"); |
| |
| //------------------------------------------------------ |
| lastApiTime = ++mInjectedCurrentTimeMillis; |
| |
| mManager.disableShortcuts(list("s2", "x3")); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1) |
| .haveRanksInOrder("s5", "s4"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2) |
| .haveRanksInOrder("x2"); |
| |
| assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime) |
| .haveIds("s4", "x2"); |
| } |
| |
| public void testDisableShortcuts_withManifestShortcuts() { |
| runTestWithManifestShortcuts(() -> testDisableShortcuts_noManifestShortcuts()); |
| } |
| |
| } |