Handle non-primary user only apps in watchlist report
Bug: 72995507 Test: Install an app in work profile and able to generate watchlist report Test: runtest frameworks-services -c com.android.server.net.watchlist.WatchlistLoggingHandlerTests Change-Id: I01e4e3986b9a5db7cb9929a5924a4bf7b13bbcd0
This commit is contained in:
@@ -22,12 +22,14 @@ import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.DropBoxManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Slog;
|
||||
@@ -238,20 +240,34 @@ class WatchlistLoggingHandler extends Handler {
|
||||
* if an app is really visited C&C site.
|
||||
* (2) App digests that previously recorded in database.
|
||||
*/
|
||||
private List<String> getAllDigestsForReport(WatchlistReportDbHelper.AggregatedResult record) {
|
||||
@VisibleForTesting
|
||||
List<String> getAllDigestsForReport(WatchlistReportDbHelper.AggregatedResult record) {
|
||||
// Step 1: Get all installed application digests.
|
||||
final List<UserInfo> users = ((UserManager) mContext.getSystemService(
|
||||
Context.USER_SERVICE)).getUsers();
|
||||
final int totalUsers = users.size();
|
||||
final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
|
||||
PackageManager.MATCH_ANY_USER | PackageManager.MATCH_ALL);
|
||||
final HashSet<String> result = new HashSet<>(apps.size() + record.appDigestCNCList.size());
|
||||
final int size = apps.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
byte[] digest = getDigestFromUid(apps.get(i).uid);
|
||||
if (digest == null) {
|
||||
final int appUid = apps.get(i).uid;
|
||||
boolean added = false;
|
||||
// As the uid returned by getInstalledApplications() is for primary user only, it
|
||||
// may exist in secondary users but not primary user, so we need to loop and see if
|
||||
// that user has the app enabled.
|
||||
for (int j = 0; j < totalUsers && !added; j++) {
|
||||
int uid = UserHandle.getUid(users.get(j).id, appUid);
|
||||
byte[] digest = getDigestFromUid(uid);
|
||||
if (digest != null) {
|
||||
result.add(HexDump.toHexString(digest));
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
Slog.e(TAG, "Cannot get digest from uid: " + apps.get(i).uid
|
||||
+ ",pkg: " + apps.get(i).packageName);
|
||||
continue;
|
||||
}
|
||||
result.add(HexDump.toHexString(digest));
|
||||
}
|
||||
// Step 2: Add all digests from records
|
||||
result.addAll(record.appDigestCNCList.keySet());
|
||||
@@ -288,9 +304,9 @@ class WatchlistLoggingHandler extends Handler {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Slog.e(TAG, "Should not happen");
|
||||
}
|
||||
// Not able to find a package name for this uid, possibly the package is installed on
|
||||
// another user.
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,18 +16,43 @@
|
||||
|
||||
package com.android.server.net.watchlist;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.FileUtils;
|
||||
import android.os.Looper;
|
||||
import android.os.UserManager;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* runtest frameworks-services -c com.android.server.net.watchlist.WatchlistLoggingHandlerTests
|
||||
@@ -36,18 +61,126 @@ import java.util.Arrays;
|
||||
@SmallTest
|
||||
public class WatchlistLoggingHandlerTests {
|
||||
|
||||
private static final String APK_A = "A.apk";
|
||||
private static final String APK_B = "B.apk";
|
||||
private static final String APK_A_CONTENT = "AAA";
|
||||
private static final String APK_B_CONTENT = "BBB";
|
||||
// Sha256 of "AAA"
|
||||
private static final String APK_A_CONTENT_HASH =
|
||||
"CB1AD2119D8FAFB69566510EE712661F9F14B83385006EF92AEC47F523A38358";
|
||||
// Sha256 of "BBB"
|
||||
private static final String APK_B_CONTENT_HASH =
|
||||
"DCDB704109A454784B81229D2B05F368692E758BFA33CB61D04C1B93791B0273";
|
||||
|
||||
private Context mServiceContext;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
final Context context = InstrumentationRegistry.getContext();
|
||||
final UserManager mockUserManager = mock(UserManager.class);
|
||||
final PackageManager mockPackageManager = mock(PackageManager.class);
|
||||
|
||||
// Context that will be used by WatchlistLoggingHandler
|
||||
mServiceContext = new ContextWrapper(context) {
|
||||
@Override
|
||||
public PackageManager getPackageManager() {
|
||||
return mockPackageManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSystemService(String name) {
|
||||
switch (name) {
|
||||
case Context.USER_SERVICE:
|
||||
return mockUserManager;
|
||||
default:
|
||||
return super.getSystemService(name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Returns 2 users, user 0 and user 10
|
||||
doAnswer((InvocationOnMock invocation) -> {
|
||||
final ArrayList<UserInfo> info = new ArrayList<>();
|
||||
info.add(new UserInfo(0, "user1", 0));
|
||||
info.add(new UserInfo(10, "user2", 0));
|
||||
return info;
|
||||
}).when(mockUserManager).getUsers();
|
||||
|
||||
// Returns 2 apps, with uid 1 and uid 2
|
||||
doAnswer((InvocationOnMock invocation) -> {
|
||||
final List<ApplicationInfo> result = new ArrayList<>();
|
||||
ApplicationInfo info1 = new ApplicationInfo();
|
||||
info1.uid = 1;
|
||||
result.add(info1);
|
||||
ApplicationInfo info2 = new ApplicationInfo();
|
||||
info2.uid = 2;
|
||||
result.add(info2);
|
||||
return result;
|
||||
}).when(mockPackageManager).getInstalledApplications(anyInt());
|
||||
|
||||
// Uid 1 app with is installed in primary user and package name is "A"
|
||||
// Uid 2 app is installed in secondary user and package name is "B"
|
||||
doAnswer((InvocationOnMock invocation) -> {
|
||||
int uid = (int) invocation.getArguments()[0];
|
||||
if (uid == 1) {
|
||||
return new String[]{"A"};
|
||||
} else if (uid == 1000001) {
|
||||
return null;
|
||||
} else if (uid == 2) {
|
||||
return null;
|
||||
} else if (uid == 1000002) {
|
||||
return new String[]{"B"};
|
||||
}
|
||||
return null;
|
||||
}).when(mockPackageManager).getPackagesForUid(anyInt());
|
||||
|
||||
String fileDir = InstrumentationRegistry.getContext().getFilesDir().getAbsolutePath();
|
||||
// Simulate app's apk file path
|
||||
doAnswer((InvocationOnMock invocation) -> {
|
||||
String pkg = (String) invocation.getArguments()[0];
|
||||
PackageInfo result = new PackageInfo();
|
||||
result.applicationInfo = new ApplicationInfo();
|
||||
result.applicationInfo.publicSourceDir = fileDir + "/" + pkg + ".apk";
|
||||
return result;
|
||||
}).when(mockPackageManager).getPackageInfoAsUser(anyString(), anyInt(), anyInt());
|
||||
|
||||
FileUtils.bytesToFile(fileDir + "/" + APK_A, APK_A_CONTENT.getBytes());
|
||||
FileUtils.bytesToFile(fileDir + "/" + APK_B, APK_B_CONTENT.getBytes());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
String fileDir = InstrumentationRegistry.getContext().getFilesDir().getAbsolutePath();
|
||||
new File(fileDir, APK_A).delete();
|
||||
new File(fileDir, APK_B).delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWatchlistLoggingHandler_getAllDigestsForReportWithMultiUsers()
|
||||
throws Exception {
|
||||
List<String> result = new WatchlistLoggingHandler(mServiceContext,
|
||||
Looper.getMainLooper()).getAllDigestsForReport(
|
||||
new WatchlistReportDbHelper.AggregatedResult(new HashSet<String>(), null,
|
||||
new HashMap<String, String>()));
|
||||
assertEquals(2, result.size());
|
||||
assertEquals(APK_A_CONTENT_HASH, result.get(0));
|
||||
assertEquals(APK_B_CONTENT_HASH, result.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWatchlistLoggingHandler_getAllSubDomains() throws Exception {
|
||||
String[] subDomains = WatchlistLoggingHandler.getAllSubDomains("abc.def.gh.i.jkl.mm");
|
||||
assertTrue(Arrays.equals(subDomains, new String[] {"abc.def.gh.i.jkl.mm",
|
||||
assertTrue(Arrays.equals(subDomains, new String[]{"abc.def.gh.i.jkl.mm",
|
||||
"def.gh.i.jkl.mm", "gh.i.jkl.mm", "i.jkl.mm", "jkl.mm", "mm"}));
|
||||
subDomains = WatchlistLoggingHandler.getAllSubDomains(null);
|
||||
assertNull(subDomains);
|
||||
subDomains = WatchlistLoggingHandler.getAllSubDomains("jkl.mm");
|
||||
assertTrue(Arrays.equals(subDomains, new String[] {"jkl.mm", "mm"}));
|
||||
assertTrue(Arrays.equals(subDomains, new String[]{"jkl.mm", "mm"}));
|
||||
subDomains = WatchlistLoggingHandler.getAllSubDomains("abc");
|
||||
assertTrue(Arrays.equals(subDomains, new String[] {"abc"}));
|
||||
assertTrue(Arrays.equals(subDomains, new String[]{"abc"}));
|
||||
subDomains = WatchlistLoggingHandler.getAllSubDomains("jkl.mm.");
|
||||
assertTrue(Arrays.equals(subDomains, new String[] {"jkl.mm.", "mm."}));
|
||||
assertTrue(Arrays.equals(subDomains, new String[]{"jkl.mm.", "mm."}));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user