diff options
author | 2024-01-12 03:52:59 +0000 | |
---|---|---|
committer | 2024-01-19 18:53:50 +0000 | |
commit | e83659c9a5a2cf1bdba5256c4f9684b7434b88b5 (patch) | |
tree | 10bdba24837354ba96cd82ab4f8e6a0c5f30a40d | |
parent | b487e625fb9294f28d3b8a4b994df24decd77875 (diff) |
Added new permission guard to BIC Service in preparation of adding SystemAPI.
Test: atest BackgroundInstallControlServiceHostTest BackgroundInstallControlServiceTest BinaryTransparencyHostTest
Bug: 296060433
API-Coverage-Bug: 319762342
Change-Id: I88c0d664ebe4b26e3f5bb131c9468c8876a286d4
8 files changed, 465 insertions, 329 deletions
diff --git a/core/java/android/app/background_install_control_manager.aconfig b/core/java/android/app/background_install_control_manager.aconfig new file mode 100644 index 000000000000..029b93ab4534 --- /dev/null +++ b/core/java/android/app/background_install_control_manager.aconfig @@ -0,0 +1,9 @@ +package: "android.app" + +flag { + namespace: "background_install_control" + name: "bic_client" + description: "System API for background install control." + is_fixed_read_only: true + bug: "287507984" +} diff --git a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java index c110fb67b54f..200b17bc2f97 100644 --- a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java +++ b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java @@ -16,7 +16,12 @@ package com.android.server.pm; +import static android.Manifest.permission.GET_BACKGROUND_INSTALLED_PACKAGES; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + import android.annotation.NonNull; +import android.annotation.RequiresPermission; +import android.app.Flags; import android.app.usage.UsageEvents; import android.app.usage.UsageStatsManagerInternal; import android.content.Context; @@ -27,6 +32,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; +import android.os.Binder; import android.os.Build; import android.os.Environment; import android.os.Handler; @@ -69,26 +75,29 @@ public class BackgroundInstallControlService extends SystemService { private static final String DISK_FILE_NAME = "states"; private static final String DISK_DIR_NAME = "bic"; - private static final int MAX_FOREGROUND_TIME_FRAMES_SIZE = 10; + private static final String ENFORCE_PERMISSION_ERROR_MSG = + "User is not permitted to call service: "; + private static final int MAX_FOREGROUND_TIME_FRAMES_SIZE = 10; private static final int MSG_USAGE_EVENT_RECEIVED = 0; private static final int MSG_PACKAGE_ADDED = 1; private static final int MSG_PACKAGE_REMOVED = 2; private final BinderService mBinderService; private final PackageManager mPackageManager; + // TODO migrate all internal PackageManager calls to PackageManagerInternal where possible. + // b/310983905 private final PackageManagerInternal mPackageManagerInternal; private final PermissionManagerServiceInternal mPermissionManager; private final Handler mHandler; private final File mDiskFile; - + private final Context mContext; private SparseSetArray<String> mBackgroundInstalledPackages = null; // User ID -> package name -> set of foreground time frame - private final SparseArrayMap<String, - TreeSet<ForegroundTimeFrame>> mInstallerForegroundTimeFrames = - new SparseArrayMap<>(); + private final SparseArrayMap<String, TreeSet<ForegroundTimeFrame>> + mInstallerForegroundTimeFrames = new SparseArrayMap<>(); public BackgroundInstallControlService(@NonNull Context context) { this(new InjectorImpl(context)); @@ -102,15 +111,13 @@ public class BackgroundInstallControlService extends SystemService { mPermissionManager = injector.getPermissionManager(); mHandler = new EventHandler(injector.getLooper(), this); mDiskFile = injector.getDiskFile(); + mContext = injector.getContext(); UsageStatsManagerInternal usageStatsManagerInternal = injector.getUsageStatsManagerInternal(); usageStatsManagerInternal.registerListener( (userId, event) -> - mHandler.obtainMessage(MSG_USAGE_EVENT_RECEIVED, - userId, - 0, - event).sendToTarget() - ); + mHandler.obtainMessage(MSG_USAGE_EVENT_RECEIVED, userId, 0, event) + .sendToTarget()); mBinderService = new BinderService(this); } @@ -124,12 +131,17 @@ public class BackgroundInstallControlService extends SystemService { @Override public ParceledListSlice<PackageInfo> getBackgroundInstalledPackages( @PackageManager.PackageInfoFlagsBits long flags, int userId) { + if (Flags.bicClient()) { + mService.enforceCallerPermissions(); + } if (!Build.IS_DEBUGGABLE) { return mService.getBackgroundInstalledPackages(flags, userId); } // The debug.transparency.bg-install-apps (only works for debuggable builds) // is used to set mock list of background installed apps for testing. // The list of apps' names is delimited by ",". + // TODO: Remove after migrating test to new background install method using + // {@link BackgroundInstallControlCallbackHelperTest}.installPackage b/310983905 String propertyString = SystemProperties.get("debug.transparency.bg-install-apps"); if (TextUtils.isEmpty(propertyString)) { return mService.getBackgroundInstalledPackages(flags, userId); @@ -137,25 +149,36 @@ public class BackgroundInstallControlService extends SystemService { return mService.getMockBackgroundInstalledPackages(propertyString); } } + + } + + @RequiresPermission(GET_BACKGROUND_INSTALLED_PACKAGES) + void enforceCallerPermissions() throws SecurityException { + mContext.enforceCallingOrSelfPermission(GET_BACKGROUND_INSTALLED_PACKAGES, + ENFORCE_PERMISSION_ERROR_MSG + GET_BACKGROUND_INSTALLED_PACKAGES); } @VisibleForTesting ParceledListSlice<PackageInfo> getBackgroundInstalledPackages( @PackageManager.PackageInfoFlagsBits long flags, int userId) { - List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser( + final long token = Binder.clearCallingIdentity(); + try { + List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser( PackageManager.PackageInfoFlags.of(flags), userId); - initBackgroundInstalledPackages(); - - ListIterator<PackageInfo> iter = packages.listIterator(); - while (iter.hasNext()) { - String packageName = iter.next().packageName; - if (!mBackgroundInstalledPackages.contains(userId, packageName)) { - iter.remove(); + initBackgroundInstalledPackages(); + ListIterator<PackageInfo> iter = packages.listIterator(); + while (iter.hasNext()) { + String packageName = iter.next().packageName; + if (!mBackgroundInstalledPackages.contains(userId, packageName)) { + iter.remove(); + } } - } - return new ParceledListSlice<>(packages); + return new ParceledListSlice<>(packages); + } finally { + Binder.restoreCallingIdentity(token); + } } /** @@ -168,8 +191,9 @@ public class BackgroundInstallControlService extends SystemService { List<PackageInfo> mockPackages = new ArrayList<>(); for (String name : mockPackageNames) { try { - PackageInfo packageInfo = mPackageManager.getPackageInfo(name, - PackageManager.PackageInfoFlags.of(PackageManager.MATCH_ALL)); + PackageInfo packageInfo = + mPackageManager.getPackageInfo( + name, PackageManager.PackageInfoFlags.of(PackageManager.MATCH_ALL)); mockPackages.add(packageInfo); } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Package's PackageInfo not found " + name); @@ -190,18 +214,16 @@ public class BackgroundInstallControlService extends SystemService { @Override public void handleMessage(Message msg) { switch (msg.what) { - case MSG_USAGE_EVENT_RECEIVED: { - mService.handleUsageEvent((UsageEvents.Event) msg.obj, msg.arg1 /* userId */); + case MSG_USAGE_EVENT_RECEIVED: + mService.handleUsageEvent( + (UsageEvents.Event) msg.obj, msg.arg1 /* userId */); break; - } - case MSG_PACKAGE_ADDED: { + case MSG_PACKAGE_ADDED: mService.handlePackageAdd((String) msg.obj, msg.arg1 /* userId */); break; - } - case MSG_PACKAGE_REMOVED: { + case MSG_PACKAGE_REMOVED: mService.handlePackageRemove((String) msg.obj, msg.arg1 /* userId */); break; - } default: Slog.w(TAG, "Unknown message: " + msg.what); } @@ -211,8 +233,9 @@ public class BackgroundInstallControlService extends SystemService { void handlePackageAdd(String packageName, int userId) { ApplicationInfo appInfo = null; try { - appInfo = mPackageManager.getApplicationInfoAsUser(packageName, - PackageManager.ApplicationInfoFlags.of(0), userId); + appInfo = + mPackageManager.getApplicationInfoAsUser( + packageName, PackageManager.ApplicationInfoFlags.of(0), userId); } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Package's appInfo not found " + packageName); return; @@ -231,15 +254,18 @@ public class BackgroundInstallControlService extends SystemService { // the installers without INSTALL_PACKAGES perm can't perform // the installation in background. So we can just filter out them. - if (mPermissionManager.checkPermission(installerPackageName, - android.Manifest.permission.INSTALL_PACKAGES, Context.DEVICE_ID_DEFAULT, - userId) != PackageManager.PERMISSION_GRANTED) { + if (mPermissionManager.checkPermission( + installerPackageName, + android.Manifest.permission.INSTALL_PACKAGES, + Context.DEVICE_ID_DEFAULT, + userId) + != PERMISSION_GRANTED) { return; } // convert up-time to current time. - final long installTimestamp = System.currentTimeMillis() - - (SystemClock.uptimeMillis() - appInfo.createTimestamp); + final long installTimestamp = + System.currentTimeMillis() - (SystemClock.uptimeMillis() - appInfo.createTimestamp); if (installedByAdb(initiatingPackageName) || wasForegroundInstallation(installerPackageName, userId, installTimestamp)) { @@ -257,8 +283,8 @@ public class BackgroundInstallControlService extends SystemService { return PackageManagerServiceUtils.isInstalledByAdb(initiatingPackageName); } - private boolean wasForegroundInstallation(String installerPackageName, - int userId, long installTimestamp) { + private boolean wasForegroundInstallation( + String installerPackageName, int userId, long installTimestamp) { TreeSet<BackgroundInstallControlService.ForegroundTimeFrame> foregroundTimeFrames = mInstallerForegroundTimeFrames.get(userId, installerPackageName); @@ -347,12 +373,12 @@ public class BackgroundInstallControlService extends SystemService { for (int i = 0; i < mBackgroundInstalledPackages.size(); i++) { int userId = mBackgroundInstalledPackages.keyAt(i); for (String packageName : mBackgroundInstalledPackages.get(userId)) { - long token = protoOutputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + long token = + protoOutputStream.start( + BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); protoOutputStream.write( BackgroundInstalledPackageProto.PACKAGE_NAME, packageName); - protoOutputStream.write( - BackgroundInstalledPackageProto.USER_ID, userId + 1); + protoOutputStream.write(BackgroundInstalledPackageProto.USER_ID, userId + 1); protoOutputStream.end(token); } } @@ -385,23 +411,28 @@ public class BackgroundInstallControlService extends SystemService { != (int) BackgroundInstalledPackagesProto.BG_INSTALLED_PKG) { continue; } - long token = protoInputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + long token = + protoInputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); String packageName = null; int userId = UserHandle.USER_NULL; while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (protoInputStream.getFieldNumber()) { case (int) BackgroundInstalledPackageProto.PACKAGE_NAME: - packageName = protoInputStream.readString( - BackgroundInstalledPackageProto.PACKAGE_NAME); + packageName = + protoInputStream.readString( + BackgroundInstalledPackageProto.PACKAGE_NAME); break; case (int) BackgroundInstalledPackageProto.USER_ID: - userId = protoInputStream.readInt( - BackgroundInstalledPackageProto.USER_ID) - 1; + userId = + protoInputStream.readInt( + BackgroundInstalledPackageProto.USER_ID) + - 1; break; default: - Slog.w(TAG, "Undefined field in proto: " - + protoInputStream.getFieldNumber()); + Slog.w( + TAG, + "Undefined field in proto: " + + protoInputStream.getFieldNumber()); } } protoInputStream.end(token); @@ -430,9 +461,12 @@ public class BackgroundInstallControlService extends SystemService { if (mInstallerForegroundTimeFrames.contains(userId, pkgName)) { return true; } - return mPermissionManager.checkPermission(pkgName, - android.Manifest.permission.INSTALL_PACKAGES, Context.DEVICE_ID_DEFAULT, - userId) == PackageManager.PERMISSION_GRANTED; + return mPermissionManager.checkPermission( + pkgName, + android.Manifest.permission.INSTALL_PACKAGES, + Context.DEVICE_ID_DEFAULT, + userId) + == PERMISSION_GRANTED; } @Override @@ -446,21 +480,22 @@ public class BackgroundInstallControlService extends SystemService { publishBinderService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE, mBinderService); } - mPackageManagerInternal.getPackageList(new PackageManagerInternal.PackageListObserver() { - @Override - public void onPackageAdded(String packageName, int uid) { - final int userId = UserHandle.getUserId(uid); - mHandler.obtainMessage(MSG_PACKAGE_ADDED, - userId, 0, packageName).sendToTarget(); - } + mPackageManagerInternal.getPackageList( + new PackageManagerInternal.PackageListObserver() { + @Override + public void onPackageAdded(String packageName, int uid) { + final int userId = UserHandle.getUserId(uid); + mHandler.obtainMessage(MSG_PACKAGE_ADDED, userId, 0, packageName) + .sendToTarget(); + } - @Override - public void onPackageRemoved(String packageName, int uid) { - final int userId = UserHandle.getUserId(uid); - mHandler.obtainMessage(MSG_PACKAGE_REMOVED, - userId, 0, packageName).sendToTarget(); - } - }); + @Override + public void onPackageRemoved(String packageName, int uid) { + final int userId = UserHandle.getUserId(uid); + mHandler.obtainMessage(MSG_PACKAGE_REMOVED, userId, 0, packageName) + .sendToTarget(); + } + }); } // The foreground time frame (ForegroundTimeFrame) represents the period @@ -516,7 +551,7 @@ public class BackgroundInstallControlService extends SystemService { } /** - * Dependency injector for {@link #BackgroundInstallControlService)}. + * Dependency injector for {@link BackgroundInstallControlService}. */ interface Injector { Context getContext(); @@ -532,6 +567,7 @@ public class BackgroundInstallControlService extends SystemService { Looper getLooper(); File getDiskFile(); + } private static final class InjectorImpl implements Injector { @@ -568,11 +604,11 @@ public class BackgroundInstallControlService extends SystemService { @Override public Looper getLooper() { - ServiceThread serviceThread = new ServiceThread(TAG, - android.os.Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */); + ServiceThread serviceThread = + new ServiceThread( + TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */); serviceThread.start(); return serviceThread.getLooper(); - } @Override diff --git a/services/tests/BackgroundInstallControlServiceTests/host/Android.bp b/services/tests/BackgroundInstallControlServiceTests/host/Android.bp index 4fcdbfc21f6c..d479e52f92d8 100644 --- a/services/tests/BackgroundInstallControlServiceTests/host/Android.bp +++ b/services/tests/BackgroundInstallControlServiceTests/host/Android.bp @@ -11,7 +11,6 @@ // 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 { // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import diff --git a/services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java b/services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java index 74506076d82f..c99e7129853b 100644 --- a/services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java +++ b/services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java @@ -41,17 +41,26 @@ public final class BackgroundInstallControlServiceHostTest extends BaseHostJUnit private static final String MOCK_APK_FILE_1 = "BackgroundInstallControlMockApp1.apk"; private static final String MOCK_APK_FILE_2 = "BackgroundInstallControlMockApp2.apk"; + // TODO: Move the silent installs to test-app using {@link + // BackgroundInstallControlServiceTest#installPackage(String, String)} and remove deviceConfig + // branch in BICS. + // b/310983905 @Test public void testGetMockBackgroundInstalledPackages() throws Exception { - installPackage(TEST_DATA_DIR + MOCK_APK_FILE_1); + installPackage(TEST_DATA_DIR + MOCK_APK_FILE_1); installPackage(TEST_DATA_DIR + MOCK_APK_FILE_2); assertThat(getDevice().getAppPackageInfo(MOCK_PACKAGE_NAME_1)).isNotNull(); assertThat(getDevice().getAppPackageInfo(MOCK_PACKAGE_NAME_2)).isNotNull(); - assertThat(getDevice().setProperty("debug.transparency.bg-install-apps", - MOCK_PACKAGE_NAME_1 + "," + MOCK_PACKAGE_NAME_2)).isTrue(); - runDeviceTest("testGetMockBackgroundInstalledPackages"); + assertThat( + getDevice() + .setProperty( + "debug.transparency.bg-install-apps", + MOCK_PACKAGE_NAME_1 + "," + MOCK_PACKAGE_NAME_2)) + .isTrue(); + runDeviceTest( + "BackgroundInstallControlServiceTest", "testGetMockBackgroundInstalledPackages"); assertThat(getDevice().uninstallPackage(MOCK_PACKAGE_NAME_1)).isNull(); assertThat(getDevice().uninstallPackage(MOCK_PACKAGE_NAME_2)).isNull(); @@ -65,10 +74,10 @@ public final class BackgroundInstallControlServiceHostTest extends BaseHostJUnit assertThat(result.getStatus() == CommandStatus.SUCCESS).isTrue(); } - private void runDeviceTest(String method) throws DeviceNotAvailableException { + private void runDeviceTest(String testName, String method) throws DeviceNotAvailableException { var options = new DeviceTestRunOptions(PACKAGE_NAME); - options.setTestClassName(PACKAGE_NAME + ".BackgroundInstallControlServiceTest"); + options.setTestClassName(PACKAGE_NAME + "." + testName); options.setTestMethodName(method); runDeviceTests(options); } -} +}
\ No newline at end of file diff --git a/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/AndroidManifest.xml b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/AndroidManifest.xml index 1fa1f84cd04e..cbe58a8fec70 100644 --- a/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/AndroidManifest.xml +++ b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/AndroidManifest.xml @@ -24,4 +24,4 @@ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" android:label="APCT tests for background install control service" android:targetPackage="com.android.server.pm.test.app" /> -</manifest> +</manifest>
\ No newline at end of file diff --git a/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java index b74e5619fd0c..b23f59106881 100644 --- a/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java +++ b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java @@ -16,6 +16,10 @@ package com.android.server.pm.test.app; +import static android.Manifest.permission.GET_BACKGROUND_INSTALLED_PACKAGES; + +import static com.android.compatibility.common.util.SystemUtil.runShellCommand; + import static com.google.common.truth.Truth.assertThat; import android.content.Context; @@ -23,12 +27,15 @@ import android.content.pm.IBackgroundInstallControlService; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.UserHandle; import androidx.test.runner.AndroidJUnit4; +import com.android.compatibility.common.util.ShellIdentityUtils; + +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,31 +46,52 @@ import java.util.stream.Collectors; @RunWith(AndroidJUnit4.class) public class BackgroundInstallControlServiceTest { private static final String TAG = "BackgroundInstallControlServiceTest"; + private static final String MOCK_PACKAGE_NAME = "com.android.servicestests.apps.bicmockapp3"; private IBackgroundInstallControlService mIBics; @Before public void setUp() { - mIBics = IBackgroundInstallControlService.Stub.asInterface( - ServiceManager.getService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE)); + mIBics = + IBackgroundInstallControlService.Stub.asInterface( + ServiceManager.getService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE)); assertThat(mIBics).isNotNull(); } + @After + public void tearDown() { + runShellCommand("pm uninstall " + MOCK_PACKAGE_NAME); + } + @Test public void testGetMockBackgroundInstalledPackages() throws RemoteException { - ParceledListSlice<PackageInfo> slice = mIBics.getBackgroundInstalledPackages( - PackageManager.MATCH_ALL, - UserHandle.USER_ALL); + ParceledListSlice<PackageInfo> slice = + ShellIdentityUtils.invokeMethodWithShellPermissions( + mIBics, + (bics) -> { + try { + return bics.getBackgroundInstalledPackages( + PackageManager.MATCH_ALL, Process.myUserHandle() + .getIdentifier()); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + }, + GET_BACKGROUND_INSTALLED_PACKAGES); assertThat(slice).isNotNull(); var packageList = slice.getList(); assertThat(packageList).isNotNull(); assertThat(packageList).hasSize(2); - var expectedPackageNames = Set.of("com.android.servicestests.apps.bicmockapp1", - "com.android.servicestests.apps.bicmockapp2"); - var actualPackageNames = packageList.stream().map((packageInfo) -> packageInfo.packageName) - .collect(Collectors.toSet()); + var expectedPackageNames = + Set.of( + "com.android.servicestests.apps.bicmockapp1", + "com.android.servicestests.apps.bicmockapp2"); + var actualPackageNames = + packageList.stream() + .map((packageInfo) -> packageInfo.packageName) + .collect(Collectors.toSet()); assertThat(actualPackageNames).containsExactlyElementsIn(expectedPackageNames); } -} +}
\ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java index daf18edaf2de..8656f60afc1e 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java @@ -9,13 +9,16 @@ * * 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. + * 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 android.Manifest.permission.GET_BACKGROUND_INSTALLED_PACKAGES; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -27,6 +30,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -97,7 +101,6 @@ public final class BackgroundInstallControlServiceTest { private Looper mLooper; private File mFile; - @Mock private Context mContext; @Mock @@ -108,8 +111,10 @@ public final class BackgroundInstallControlServiceTest { private UsageStatsManagerInternal mUsageStatsManagerInternal; @Mock private PermissionManagerServiceInternal mPermissionManager; + @Captor private ArgumentCaptor<PackageManagerInternal.PackageListObserver> mPackageListObserverCaptor; + @Captor private ArgumentCaptor<UsageEventListener> mUsageEventListenerCaptor; @@ -119,11 +124,12 @@ public final class BackgroundInstallControlServiceTest { mTestLooper = new TestLooper(); mLooper = mTestLooper.getLooper(); - mFile = new File( - InstrumentationRegistry.getInstrumentation().getContext().getCacheDir(), - "test"); - mBackgroundInstallControlService = new BackgroundInstallControlService( - new MockInjector(mContext)); + mFile = + new File( + InstrumentationRegistry.getInstrumentation().getContext().getCacheDir(), + "test"); + mBackgroundInstallControlService = + new BackgroundInstallControlService(new MockInjector(mContext)); verify(mUsageStatsManagerInternal).registerListener(mUsageEventListenerCaptor.capture()); mUsageEventListener = mUsageEventListenerCaptor.getValue(); @@ -143,8 +149,7 @@ public final class BackgroundInstallControlServiceTest { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); mBackgroundInstallControlService.initBackgroundInstalledPackages(); assertNotNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); - assertEquals(0, - mBackgroundInstallControlService.getBackgroundInstalledPackages().size()); + assertEquals(0, mBackgroundInstallControlService.getBackgroundInstalledPackages().size()); } @Test @@ -161,12 +166,9 @@ public final class BackgroundInstallControlServiceTest { // Write test data to the file on the disk. try { ProtoOutputStream protoOutputStream = new ProtoOutputStream(fileOutputStream); - long token = protoOutputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); - protoOutputStream.write( - BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_1); - protoOutputStream.write( - BackgroundInstalledPackageProto.USER_ID, USER_ID_1 + 1); + long token = protoOutputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + protoOutputStream.write(BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_1); + protoOutputStream.write(BackgroundInstalledPackageProto.USER_ID, USER_ID_1 + 1); protoOutputStream.end(token); protoOutputStream.flush(); atomicFile.finishWrite(fileOutputStream); @@ -198,20 +200,14 @@ public final class BackgroundInstallControlServiceTest { try { ProtoOutputStream protoOutputStream = new ProtoOutputStream(fileOutputStream); - long token = protoOutputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); - protoOutputStream.write( - BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_1); - protoOutputStream.write( - BackgroundInstalledPackageProto.USER_ID, USER_ID_1 + 1); + long token = protoOutputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + protoOutputStream.write(BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_1); + protoOutputStream.write(BackgroundInstalledPackageProto.USER_ID, USER_ID_1 + 1); protoOutputStream.end(token); - token = protoOutputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); - protoOutputStream.write( - BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_2); - protoOutputStream.write( - BackgroundInstalledPackageProto.USER_ID, USER_ID_2 + 1); + token = protoOutputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + protoOutputStream.write(BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_2); + protoOutputStream.write(BackgroundInstalledPackageProto.USER_ID, USER_ID_2 + 1); protoOutputStream.end(token); protoOutputStream.flush(); @@ -241,7 +237,7 @@ public final class BackgroundInstallControlServiceTest { // Read the file on the disk to verify var packagesInDisk = new SparseSetArray<>(); AtomicFile atomicFile = new AtomicFile(mFile); - try (FileInputStream fileInputStream = atomicFile.openRead()) { + try (FileInputStream fileInputStream = atomicFile.openRead()) { ProtoInputStream protoInputStream = new ProtoInputStream(fileInputStream); while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { @@ -249,23 +245,25 @@ public final class BackgroundInstallControlServiceTest { != (int) BackgroundInstalledPackagesProto.BG_INSTALLED_PKG) { continue; } - long token = protoInputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + long token = + protoInputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); String packageName = null; int userId = UserHandle.USER_NULL; while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (protoInputStream.getFieldNumber()) { case (int) BackgroundInstalledPackageProto.PACKAGE_NAME: - packageName = protoInputStream.readString( - BackgroundInstalledPackageProto.PACKAGE_NAME); + packageName = + protoInputStream.readString( + BackgroundInstalledPackageProto.PACKAGE_NAME); break; case (int) BackgroundInstalledPackageProto.USER_ID: - userId = protoInputStream.readInt( - BackgroundInstalledPackageProto.USER_ID) - 1; + userId = + protoInputStream.readInt( + BackgroundInstalledPackageProto.USER_ID) + - 1; break; default: - fail("Undefined field in proto: " - + protoInputStream.getFieldNumber()); + fail("Undefined field in proto: " + protoInputStream.getFieldNumber()); } } protoInputStream.end(token); @@ -296,7 +294,7 @@ public final class BackgroundInstallControlServiceTest { // Read the file on the disk to verify var packagesInDisk = new SparseSetArray<>(); AtomicFile atomicFile = new AtomicFile(mFile); - try (FileInputStream fileInputStream = atomicFile.openRead()) { + try (FileInputStream fileInputStream = atomicFile.openRead()) { ProtoInputStream protoInputStream = new ProtoInputStream(fileInputStream); while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { @@ -304,23 +302,25 @@ public final class BackgroundInstallControlServiceTest { != (int) BackgroundInstalledPackagesProto.BG_INSTALLED_PKG) { continue; } - long token = protoInputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + long token = + protoInputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); String packageName = null; int userId = UserHandle.USER_NULL; while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (protoInputStream.getFieldNumber()) { case (int) BackgroundInstalledPackageProto.PACKAGE_NAME: - packageName = protoInputStream.readString( - BackgroundInstalledPackageProto.PACKAGE_NAME); + packageName = + protoInputStream.readString( + BackgroundInstalledPackageProto.PACKAGE_NAME); break; case (int) BackgroundInstalledPackageProto.USER_ID: - userId = protoInputStream.readInt( - BackgroundInstalledPackageProto.USER_ID) - 1; + userId = + protoInputStream.readInt( + BackgroundInstalledPackageProto.USER_ID) + - 1; break; default: - fail("Undefined field in proto: " - + protoInputStream.getFieldNumber()); + fail("Undefined field in proto: " + protoInputStream.getFieldNumber()); } } protoInputStream.end(token); @@ -353,7 +353,7 @@ public final class BackgroundInstallControlServiceTest { // Read the file on the disk to verify var packagesInDisk = new SparseSetArray<>(); AtomicFile atomicFile = new AtomicFile(mFile); - try (FileInputStream fileInputStream = atomicFile.openRead()) { + try (FileInputStream fileInputStream = atomicFile.openRead()) { ProtoInputStream protoInputStream = new ProtoInputStream(fileInputStream); while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { @@ -361,23 +361,25 @@ public final class BackgroundInstallControlServiceTest { != (int) BackgroundInstalledPackagesProto.BG_INSTALLED_PKG) { continue; } - long token = protoInputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + long token = + protoInputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); String packageName = null; int userId = UserHandle.USER_NULL; while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (protoInputStream.getFieldNumber()) { case (int) BackgroundInstalledPackageProto.PACKAGE_NAME: - packageName = protoInputStream.readString( - BackgroundInstalledPackageProto.PACKAGE_NAME); + packageName = + protoInputStream.readString( + BackgroundInstalledPackageProto.PACKAGE_NAME); break; case (int) BackgroundInstalledPackageProto.USER_ID: - userId = protoInputStream.readInt( - BackgroundInstalledPackageProto.USER_ID) - 1; + userId = + protoInputStream.readInt( + BackgroundInstalledPackageProto.USER_ID) + - 1; break; default: - fail("Undefined field in proto: " - + protoInputStream.getFieldNumber()); + fail("Undefined field in proto: " + protoInputStream.getFieldNumber()); } } protoInputStream.end(token); @@ -399,51 +401,55 @@ public final class BackgroundInstallControlServiceTest { @Test public void testHandleUsageEvent_permissionDenied() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_DENIED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, 0); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PackageManager.PERMISSION_DENIED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, USER_ID_1, INSTALLER_NAME_1, 0); mTestLooper.dispatchAll(); - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); } @Test public void testHandleUsageEvent_permissionGranted() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, 0); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, USER_ID_1, INSTALLER_NAME_1, 0); mTestLooper.dispatchAll(); - assertEquals(1, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + assertEquals( + 1, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); } @Test public void testHandleUsageEvent_ignoredEvent() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.USER_INTERACTION, - USER_ID_1, INSTALLER_NAME_1, 0); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent(UsageEvents.Event.USER_INTERACTION, USER_ID_1, INSTALLER_NAME_1, 0); mTestLooper.dispatchAll(); - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); } @Test public void testHandleUsageEvent_firstActivityResumedHalfTimeFrame() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_1); mTestLooper.dispatchAll(); var installerForegroundTimeFrames = @@ -461,14 +467,18 @@ public final class BackgroundInstallControlServiceTest { @Test public void testHandleUsageEvent_firstActivityResumedOneTimeFrame() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_1); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); mTestLooper.dispatchAll(); var installerForegroundTimeFrames = @@ -486,16 +496,23 @@ public final class BackgroundInstallControlServiceTest { @Test public void testHandleUsageEvent_firstActivityResumedOneAndHalfTimeFrame() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_1); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_3); mTestLooper.dispatchAll(); var installerForegroundTimeFrames = @@ -517,12 +534,13 @@ public final class BackgroundInstallControlServiceTest { @Test public void testHandleUsageEvent_firstNoneActivityResumed() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); mTestLooper.dispatchAll(); var installerForegroundTimeFrames = @@ -535,27 +553,26 @@ public final class BackgroundInstallControlServiceTest { } @Test - public void testHandleUsageEvent_packageAddedNoUsageEvent() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedNoUsageEvent() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ INSTALLER_NAME_1, - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ INSTALLER_NAME_1, + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1); when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -572,27 +589,26 @@ public final class BackgroundInstallControlServiceTest { } @Test - public void testHandleUsageEvent_packageAddedInsideTimeFrame() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedInsideTimeFrame() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ INSTALLER_NAME_1, - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ INSTALLER_NAME_1, + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1); when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -604,12 +620,16 @@ public final class BackgroundInstallControlServiceTest { // The 2 usage events make the package adding inside a time frame. // So it's not a background install. Thus, it's null for the return of // mBackgroundInstallControlService.getBackgroundInstalledPackages() - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_1); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); mPackageListObserver.onPackageAdded(PACKAGE_NAME_1, uid); mTestLooper.dispatchAll(); @@ -617,27 +637,26 @@ public final class BackgroundInstallControlServiceTest { } @Test - public void testHandleUsageEvent_packageAddedOutsideTimeFrame1() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedOutsideTimeFrame1() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ INSTALLER_NAME_1, - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ INSTALLER_NAME_1, + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1); when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -650,12 +669,16 @@ public final class BackgroundInstallControlServiceTest { // Compared to testHandleUsageEvent_packageAddedInsideTimeFrame, // it's a background install. Thus, it's not null for the return of // mBackgroundInstallControlService.getBackgroundInstalledPackages() - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_2); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); mPackageListObserver.onPackageAdded(PACKAGE_NAME_1, uid); mTestLooper.dispatchAll(); @@ -665,28 +688,28 @@ public final class BackgroundInstallControlServiceTest { assertEquals(1, packages.size()); assertTrue(packages.contains(USER_ID_1, PACKAGE_NAME_1)); } + @Test - public void testHandleUsageEvent_packageAddedOutsideTimeFrame2() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedOutsideTimeFrame2() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ INSTALLER_NAME_1, - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ INSTALLER_NAME_1, + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1); when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -700,12 +723,16 @@ public final class BackgroundInstallControlServiceTest { // Compared to testHandleUsageEvent_packageAddedInsideTimeFrame, // it's a background install. Thus, it's not null for the return of // mBackgroundInstallControlService.getBackgroundInstalledPackages() - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_2, INSTALLER_NAME_2, USAGE_EVENT_TIMESTAMP_2); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_2, INSTALLER_NAME_2, USAGE_EVENT_TIMESTAMP_3); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_2, + INSTALLER_NAME_2, + USAGE_EVENT_TIMESTAMP_2); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_2, INSTALLER_NAME_2, USAGE_EVENT_TIMESTAMP_3); mPackageListObserver.onPackageAdded(PACKAGE_NAME_1, uid); mTestLooper.dispatchAll(); @@ -715,31 +742,31 @@ public final class BackgroundInstallControlServiceTest { assertEquals(1, packages.size()); assertTrue(packages.contains(USER_ID_1, PACKAGE_NAME_1)); } + @Test - public void testHandleUsageEvent_packageAddedThroughAdb() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedThroughAdb() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); // This test is a duplicate of testHandleUsageEvent_packageAddedThroughAdb except the // initiatingPackageName used to be null but is now "com.android.shell". This test ensures // that the behavior is still the same for when the initiatingPackageName is null. - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ null, - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ null, + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); // b/265203007 when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -751,12 +778,16 @@ public final class BackgroundInstallControlServiceTest { // for ADB installs the initiatingPackageName used to be null, despite being detected // as a background install. Since we do not want to treat side-loaded apps as background // install getBackgroundInstalledPackages() is expected to return null - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_2); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); mPackageListObserver.onPackageAdded(PACKAGE_NAME_1, uid); mTestLooper.dispatchAll(); @@ -764,31 +795,31 @@ public final class BackgroundInstallControlServiceTest { var packages = mBackgroundInstallControlService.getBackgroundInstalledPackages(); assertNull(packages); } + @Test - public void testHandleUsageEvent_packageAddedThroughAdb2() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedThroughAdb2() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); // This test is a duplicate of testHandleUsageEvent_packageAddedThroughAdb except the // initiatingPackageName used to be null but is now "com.android.shell". This test ensures // that the behavior is still the same after this change. - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ "com.android.shell", - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ "com.android.shell", + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); // b/265203007 when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -800,12 +831,16 @@ public final class BackgroundInstallControlServiceTest { // for ADB installs the initiatingPackageName is com.android.shell, despite being detected // as a background install. Since we do not want to treat side-loaded apps as background // install getBackgroundInstalledPackages() is expected to return null - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_2); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); mPackageListObserver.onPackageAdded(PACKAGE_NAME_1, uid); mTestLooper.dispatchAll(); @@ -813,6 +848,7 @@ public final class BackgroundInstallControlServiceTest { var packages = mBackgroundInstallControlService.getBackgroundInstalledPackages(); assertNull(packages); } + @Test public void testPackageRemoved() { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); @@ -859,8 +895,7 @@ public final class BackgroundInstallControlServiceTest { packages.add(packageInfo2); var packageInfo3 = makePackageInfo(PACKAGE_NAME_3); packages.add(packageInfo3); - doReturn(packages).when(mPackageManager).getInstalledPackagesAsUser( - any(), anyInt()); + doReturn(packages).when(mPackageManager).getInstalledPackagesAsUser(any(), anyInt()); var resultPackages = mBackgroundInstallControlService.getBackgroundInstalledPackages(0L, USER_ID_1); @@ -870,18 +905,30 @@ public final class BackgroundInstallControlServiceTest { assertFalse(resultPackages.getList().contains(packageInfo3)); } + @Test(expected = SecurityException.class) + public void enforceCallerPermissionsThrowsSecurityException() { + doThrow(new SecurityException("test")).when(mContext) + .enforceCallingOrSelfPermission(eq(GET_BACKGROUND_INSTALLED_PACKAGES), anyString()); + + mBackgroundInstallControlService.enforceCallerPermissions(); + } + + @Test + public void enforceCallerPermissionsDoesNotThrowSecurityException() { + //enforceCallerQueryPackagesPermissions do not throw + + mBackgroundInstallControlService.enforceCallerPermissions(); + } + /** * Mock a usage event occurring. * * @param usageEventId id of a usage event - * @param userId user id of a usage event - * @param pkgName package name of a usage event - * @param timestamp timestamp of a usage event + * @param userId user id of a usage event + * @param pkgName package name of a usage event + * @param timestamp timestamp of a usage event */ - private void generateUsageEvent(int usageEventId, - int userId, - String pkgName, - long timestamp) { + private void generateUsageEvent(int usageEventId, int userId, String pkgName, long timestamp) { Event event = new Event(usageEventId, timestamp); event.mPackage = pkgName; mUsageEventListener.onUsageEvent(userId, event); diff --git a/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java b/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java index 2bc056ee743f..cee27b6847ec 100644 --- a/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java +++ b/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java @@ -16,6 +16,8 @@ package android.transparency.test.app; +import static android.Manifest.permission.GET_BACKGROUND_INSTALLED_PACKAGES; + import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -27,6 +29,7 @@ import android.util.Log; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.compatibility.common.util.ShellIdentityUtils; import com.android.internal.os.IBinaryTransparencyService.AppInfo; import org.junit.Before; @@ -116,7 +119,12 @@ public class BinaryTransparencyTest { @Test public void testCollectAllSilentInstalledMbaInfo() { // Action - var appInfoList = mBt.collectAllSilentInstalledMbaInfo(new Bundle()); + var appInfoList = + ShellIdentityUtils.invokeMethodWithShellPermissions( + mBt, + (Bt) -> + mBt.collectAllSilentInstalledMbaInfo(new Bundle()), + GET_BACKGROUND_INSTALLED_PACKAGES); // Verify assertThat(appInfoList).isNotEmpty(); // because we just installed from the host side |