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