Loading core/java/android/app/background_install_control_manager.aconfig 0 → 100644 +9 −0 Original line number Diff line number Diff line 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" } services/core/java/com/android/server/pm/BackgroundInstallControlService.java +107 −71 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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)); Loading @@ -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); } Loading @@ -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); Loading @@ -137,16 +149,24 @@ 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) { 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; Loading @@ -156,6 +176,9 @@ public class BackgroundInstallControlService extends SystemService { } return new ParceledListSlice<>(packages); } finally { Binder.restoreCallingIdentity(token); } } /** Loading @@ -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); Loading @@ -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); } Loading @@ -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; Loading @@ -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)) { Loading @@ -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); Loading Loading @@ -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( 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); } } Loading Loading @@ -385,22 +411,27 @@ 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( 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: " Slog.w( TAG, "Undefined field in proto: " + protoInputStream.getFieldNumber()); } } Loading Loading @@ -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 Loading @@ -446,19 +480,20 @@ public class BackgroundInstallControlService extends SystemService { publishBinderService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE, mBinderService); } mPackageManagerInternal.getPackageList(new PackageManagerInternal.PackageListObserver() { 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(); 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(); mHandler.obtainMessage(MSG_PACKAGE_REMOVED, userId, 0, packageName) .sendToTarget(); } }); } Loading Loading @@ -516,7 +551,7 @@ public class BackgroundInstallControlService extends SystemService { } /** * Dependency injector for {@link #BackgroundInstallControlService)}. * Dependency injector for {@link BackgroundInstallControlService}. */ interface Injector { Context getContext(); Loading @@ -532,6 +567,7 @@ public class BackgroundInstallControlService extends SystemService { Looper getLooper(); File getDiskFile(); } private static final class InjectorImpl implements Injector { Loading Loading @@ -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 Loading services/tests/BackgroundInstallControlServiceTests/host/Android.bp +0 −1 Original line number Diff line number Diff line Loading @@ -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 Loading services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java +16 −7 Original line number Diff line number Diff line Loading @@ -41,6 +41,10 @@ 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); Loading @@ -49,9 +53,14 @@ public final class BackgroundInstallControlServiceHostTest extends BaseHostJUnit 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(); Loading @@ -65,9 +74,9 @@ 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); } Loading services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java +39 −11 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -39,30 +46,51 @@ 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( 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", var expectedPackageNames = Set.of( "com.android.servicestests.apps.bicmockapp1", "com.android.servicestests.apps.bicmockapp2"); var actualPackageNames = packageList.stream().map((packageInfo) -> packageInfo.packageName) var actualPackageNames = packageList.stream() .map((packageInfo) -> packageInfo.packageName) .collect(Collectors.toSet()); assertThat(actualPackageNames).containsExactlyElementsIn(expectedPackageNames); } Loading Loading
core/java/android/app/background_install_control_manager.aconfig 0 → 100644 +9 −0 Original line number Diff line number Diff line 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" }
services/core/java/com/android/server/pm/BackgroundInstallControlService.java +107 −71 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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)); Loading @@ -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); } Loading @@ -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); Loading @@ -137,16 +149,24 @@ 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) { 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; Loading @@ -156,6 +176,9 @@ public class BackgroundInstallControlService extends SystemService { } return new ParceledListSlice<>(packages); } finally { Binder.restoreCallingIdentity(token); } } /** Loading @@ -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); Loading @@ -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); } Loading @@ -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; Loading @@ -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)) { Loading @@ -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); Loading Loading @@ -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( 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); } } Loading Loading @@ -385,22 +411,27 @@ 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( 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: " Slog.w( TAG, "Undefined field in proto: " + protoInputStream.getFieldNumber()); } } Loading Loading @@ -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 Loading @@ -446,19 +480,20 @@ public class BackgroundInstallControlService extends SystemService { publishBinderService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE, mBinderService); } mPackageManagerInternal.getPackageList(new PackageManagerInternal.PackageListObserver() { 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(); 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(); mHandler.obtainMessage(MSG_PACKAGE_REMOVED, userId, 0, packageName) .sendToTarget(); } }); } Loading Loading @@ -516,7 +551,7 @@ public class BackgroundInstallControlService extends SystemService { } /** * Dependency injector for {@link #BackgroundInstallControlService)}. * Dependency injector for {@link BackgroundInstallControlService}. */ interface Injector { Context getContext(); Loading @@ -532,6 +567,7 @@ public class BackgroundInstallControlService extends SystemService { Looper getLooper(); File getDiskFile(); } private static final class InjectorImpl implements Injector { Loading Loading @@ -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 Loading
services/tests/BackgroundInstallControlServiceTests/host/Android.bp +0 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java +16 −7 Original line number Diff line number Diff line Loading @@ -41,6 +41,10 @@ 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); Loading @@ -49,9 +53,14 @@ public final class BackgroundInstallControlServiceHostTest extends BaseHostJUnit 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(); Loading @@ -65,9 +74,9 @@ 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); } Loading
services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java +39 −11 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -39,30 +46,51 @@ 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( 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", var expectedPackageNames = Set.of( "com.android.servicestests.apps.bicmockapp1", "com.android.servicestests.apps.bicmockapp2"); var actualPackageNames = packageList.stream().map((packageInfo) -> packageInfo.packageName) var actualPackageNames = packageList.stream() .map((packageInfo) -> packageInfo.packageName) .collect(Collectors.toSet()); assertThat(actualPackageNames).containsExactlyElementsIn(expectedPackageNames); } Loading