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 package android.content.pm.cts.shortcutmanager; 17 18 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.appOps; 19 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list; 20 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.retryUntil; 21 22 import android.app.AppOpsManager; 23 import android.app.usage.UsageEvents; 24 import android.app.usage.UsageEvents.Event; 25 import android.app.usage.UsageStatsManager; 26 import android.content.pm.cts.shortcutmanager.common.Constants; 27 import android.test.suitebuilder.annotation.SmallTest; 28 import android.text.format.Time; 29 30 import com.android.compatibility.common.util.CddTest; 31 32 @CddTest(requirement="3.8.1/C-4-1") 33 @SmallTest 34 public class ShortcutManagerUsageTest extends ShortcutManagerCtsTestsBase { 35 private static final String APPOPS_SET_SHELL_COMMAND = "appops set {0} " + 36 AppOpsManager.OPSTR_GET_USAGE_STATS + " {1}"; 37 38 // We need some allowance due to b/30415390. 39 private static long USAGE_STATS_RANGE_ALLOWANCE = 60 * 1000; 40 41 @Override 42 protected void setUp() throws Exception { 43 super.setUp(); 44 45 appOps(getInstrumentation(), getTestContext().getPackageName(), 46 AppOpsManager.OPSTR_GET_USAGE_STATS, "allow"); 47 } 48 49 @Override 50 protected void tearDown() throws Exception { 51 appOps(getInstrumentation(), getTestContext().getPackageName(), 52 AppOpsManager.OPSTR_GET_USAGE_STATS, "deny"); 53 54 super.tearDown(); 55 } 56 57 private static String generateRandomId(String signature) { 58 Time tobj = new Time(); 59 tobj.set(System.currentTimeMillis()); 60 return tobj.format("%Y-%m-%d %H:%M:%S") + "." + signature + "." 61 + Constants.sRandom.nextLong(); 62 } 63 64 private boolean hasEvent(UsageEvents events, String packageName, String id) { 65 final Event e = new Event(); 66 while (events.hasNextEvent()) { 67 if (!events.getNextEvent(e)) { 68 break; 69 } 70 if (e.getEventType() == Event.SHORTCUT_INVOCATION 71 && packageName.equals(e.getPackageName()) 72 && id.equals(e.getShortcutId())) { 73 return true; 74 } 75 } 76 return false; 77 } 78 79 public void testReportShortcutUsed() throws InterruptedException { 80 81 runWithCallerWithStrictMode(mPackageContext1, () -> { 82 enableManifestActivity("Launcher_manifest_2", true); 83 84 retryUntil(() -> getManager().getManifestShortcuts().size() > 0, 85 "Manifest shortcuts didn't show up"); 86 }); 87 88 final String id1 = generateRandomId("id1"); 89 final String id2 = generateRandomId("id2"); 90 final String id3 = generateRandomId("id3"); 91 92 final String idManifest = "ms21"; 93 final String idNonexistance = "nonexistence"; 94 95 runWithCallerWithStrictMode(mPackageContext1, () -> { 96 assertTrue(getManager().setDynamicShortcuts(list( 97 makeShortcut(id1), 98 makeShortcut(id2) 99 ))); 100 }); 101 runWithCallerWithStrictMode(mPackageContext2, () -> { 102 assertTrue(getManager().setDynamicShortcuts(list( 103 makeShortcut(id1), 104 makeShortcut(id3) 105 ))); 106 }); 107 108 final UsageStatsManager usm = getTestContext().getSystemService(UsageStatsManager.class); 109 110 // Report usage. 111 final long start1 = System.currentTimeMillis() - USAGE_STATS_RANGE_ALLOWANCE; 112 runWithCallerWithStrictMode(mPackageContext2, () -> getManager().reportShortcutUsed(id3)); 113 final long end1 = System.currentTimeMillis() + USAGE_STATS_RANGE_ALLOWANCE; 114 115 // Check the log. 116 retryUntil(() -> hasEvent(usm.queryEvents(start1, end1), 117 mPackageContext2.getPackageName(), id3), "Events weren't populated"); 118 119 // Report usage. 120 final long start2 = System.currentTimeMillis() - USAGE_STATS_RANGE_ALLOWANCE; 121 runWithCallerWithStrictMode(mPackageContext1, () -> getManager().reportShortcutUsed(id1)); 122 final long end2 = System.currentTimeMillis() + USAGE_STATS_RANGE_ALLOWANCE; 123 124 // Check the log. 125 retryUntil(() -> hasEvent(usm.queryEvents(start2, end2), 126 mPackageContext1.getPackageName(), id1), "Events weren't populated"); 127 128 // Report usage. 129 final long start3 = System.currentTimeMillis() - USAGE_STATS_RANGE_ALLOWANCE; 130 runWithCallerWithStrictMode(mPackageContext1, () -> getManager().reportShortcutUsed(idNonexistance)); 131 runWithCallerWithStrictMode(mPackageContext1, () -> getManager().reportShortcutUsed(idManifest)); 132 final long end3 = System.currentTimeMillis() + USAGE_STATS_RANGE_ALLOWANCE; 133 134 // Check the log. 135 retryUntil(() -> hasEvent(usm.queryEvents(start3, end3), 136 mPackageContext1.getPackageName(), idManifest), "Events weren't populated"); 137 // Ensure that the nonexistent shortcut is not reported, even after the other one is. 138 assertFalse(hasEvent(usm.queryEvents(start3, end3), 139 mPackageContext1.getPackageName(), idNonexistance)); 140 } 141 } 142