blob: c1c5fa932b0c1f8dc73b249ee0fdec01a57f05f6 [file] [log] [blame]
Lifu Tang054cfe52018-12-26 12:57:22 -08001package com.android.settingslib.location;
2
3import static com.google.common.truth.Truth.assertThat;
4
5import static org.mockito.ArgumentMatchers.isA;
6import static org.mockito.Mockito.spy;
7import static org.mockito.Mockito.when;
8
9import android.app.AppOpsManager;
10import android.app.AppOpsManager.OpEntry;
11import android.app.AppOpsManager.PackageOps;
12import android.content.Context;
13import android.content.pm.ApplicationInfo;
14import android.content.pm.PackageManager;
15import android.content.pm.PackageManager.NameNotFoundException;
16import android.os.Process;
17import android.os.UserHandle;
18import android.os.UserManager;
19
Svet Ganovaf189e32019-02-15 18:45:29 -080020import android.util.LongSparseLongArray;
Lifu Tang054cfe52018-12-26 12:57:22 -080021import org.junit.Before;
22import org.junit.Test;
23import org.junit.runner.RunWith;
24import org.mockito.Mock;
25import org.mockito.MockitoAnnotations;
26import org.robolectric.RobolectricTestRunner;
27import org.robolectric.RuntimeEnvironment;
28
29import java.time.Clock;
30import java.util.ArrayList;
31import java.util.Collections;
32import java.util.List;
33import java.util.concurrent.TimeUnit;
34
35@RunWith(RobolectricTestRunner.class)
36public class RecentLocationAccessesTest {
37
38 private static final int TEST_UID = 1234;
39 private static final long NOW = 1_000_000_000; // Approximately 9/8/2001
40 private static final long ONE_MIN_AGO = NOW - TimeUnit.MINUTES.toMillis(1);
41 private static final long TWENTY_THREE_HOURS_AGO = NOW - TimeUnit.HOURS.toMillis(23);
42 private static final long TWO_DAYS_AGO = NOW - TimeUnit.DAYS.toMillis(2);
43 private static final String[] TEST_PACKAGE_NAMES =
44 {"package_1MinAgo", "package_14MinAgo", "package_20MinAgo"};
45
46 @Mock
47 private PackageManager mPackageManager;
48 @Mock
49 private AppOpsManager mAppOpsManager;
50 @Mock
51 private UserManager mUserManager;
52 @Mock
53 private Clock mClock;
54 private Context mContext;
55 private int mTestUserId;
56 private RecentLocationAccesses mRecentLocationAccesses;
57
58 @Before
59 public void setUp() throws NameNotFoundException {
60 MockitoAnnotations.initMocks(this);
61 mContext = spy(RuntimeEnvironment.application);
62
63 when(mContext.getPackageManager()).thenReturn(mPackageManager);
64 when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
65 when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
66 when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
67 when(mPackageManager.getApplicationLabel(isA(ApplicationInfo.class)))
68 .thenReturn("testApplicationLabel");
69 when(mPackageManager.getUserBadgedLabel(isA(CharSequence.class), isA(UserHandle.class)))
70 .thenReturn("testUserBadgedLabel");
71 mTestUserId = UserHandle.getUserId(TEST_UID);
72 when(mUserManager.getUserProfiles())
73 .thenReturn(Collections.singletonList(new UserHandle(mTestUserId)));
74
75 long[] testRequestTime = {ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO};
76 List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime);
77 when(mAppOpsManager.getPackagesForOps(RecentLocationAccesses.LOCATION_OPS)).thenReturn(
78 appOps);
79 mockTestApplicationInfos(mTestUserId, TEST_PACKAGE_NAMES);
80
81 when(mClock.millis()).thenReturn(NOW);
82 mRecentLocationAccesses = new RecentLocationAccesses(mContext, mClock);
83 }
84
85 @Test
86 public void testGetAppList_shouldFilterRecentAccesses() {
87 List<RecentLocationAccesses.Access> requests = mRecentLocationAccesses.getAppList();
88 // Only two of the apps have requested location within 15 min.
89 assertThat(requests).hasSize(2);
90 // Make sure apps are ordered by recency
91 assertThat(requests.get(0).packageName).isEqualTo(TEST_PACKAGE_NAMES[0]);
92 assertThat(requests.get(0).accessFinishTime).isEqualTo(ONE_MIN_AGO);
93 assertThat(requests.get(1).packageName).isEqualTo(TEST_PACKAGE_NAMES[1]);
94 assertThat(requests.get(1).accessFinishTime).isEqualTo(TWENTY_THREE_HOURS_AGO);
95 }
96
97 @Test
98 public void testGetAppList_shouldNotShowAndroidOS() throws NameNotFoundException {
99 // Add android OS to the list of apps.
100 PackageOps androidSystemPackageOps =
101 createPackageOps(
102 RecentLocationAccesses.ANDROID_SYSTEM_PACKAGE_NAME,
103 Process.SYSTEM_UID,
104 AppOpsManager.OP_FINE_LOCATION,
105 ONE_MIN_AGO);
106 long[] testRequestTime =
107 {ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO, ONE_MIN_AGO};
108 List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime);
109 appOps.add(androidSystemPackageOps);
110 when(mAppOpsManager.getPackagesForOps(RecentLocationAccesses.LOCATION_OPS)).thenReturn(
111 appOps);
112 mockTestApplicationInfos(
113 Process.SYSTEM_UID, RecentLocationAccesses.ANDROID_SYSTEM_PACKAGE_NAME);
114
115 List<RecentLocationAccesses.Access> requests = mRecentLocationAccesses.getAppList();
116 // Android OS shouldn't show up in the list of apps.
117 assertThat(requests).hasSize(2);
118 // Make sure apps are ordered by recency
119 assertThat(requests.get(0).packageName).isEqualTo(TEST_PACKAGE_NAMES[0]);
120 assertThat(requests.get(0).accessFinishTime).isEqualTo(ONE_MIN_AGO);
121 assertThat(requests.get(1).packageName).isEqualTo(TEST_PACKAGE_NAMES[1]);
122 assertThat(requests.get(1).accessFinishTime).isEqualTo(TWENTY_THREE_HOURS_AGO);
123 }
124
125 private void mockTestApplicationInfos(int userId, String... packageNameList)
126 throws NameNotFoundException {
127 for (String packageName : packageNameList) {
128 ApplicationInfo appInfo = new ApplicationInfo();
129 appInfo.packageName = packageName;
130 when(mPackageManager.getApplicationInfoAsUser(
131 packageName, PackageManager.GET_META_DATA, userId)).thenReturn(appInfo);
132 }
133 }
134
135 private List<PackageOps> createTestPackageOpsList(String[] packageNameList, long[] time) {
136 List<PackageOps> packageOpsList = new ArrayList<>();
137 for (int i = 0; i < packageNameList.length; i++) {
138 PackageOps packageOps = createPackageOps(
139 packageNameList[i],
140 TEST_UID,
141 AppOpsManager.OP_FINE_LOCATION,
142 time[i]);
143 packageOpsList.add(packageOps);
144 }
145 return packageOpsList;
146 }
147
148 private PackageOps createPackageOps(String packageName, int uid, int op, long time) {
149 return new PackageOps(
150 packageName,
151 uid,
152 Collections.singletonList(createOpEntryWithTime(op, time)));
153 }
154
155 private OpEntry createOpEntryWithTime(int op, long time) {
Lifu Tang054cfe52018-12-26 12:57:22 -0800156 // Slot for background access timestamp.
Svet Ganovaf189e32019-02-15 18:45:29 -0800157 final LongSparseLongArray accessTimes = new LongSparseLongArray();
158 accessTimes.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_BACKGROUND,
159 AppOpsManager.OP_FLAG_SELF), time);
160
161 return new OpEntry(op, false, AppOpsManager.MODE_ALLOWED, accessTimes, null /*durations*/,
162 null /*rejectTimes*/, null /* proxyUids */, null /* proxyPackages */);
Lifu Tang054cfe52018-12-26 12:57:22 -0800163 }
164}