Loading services/core/java/com/android/server/pm/BroadcastHelper.java +46 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.Manifest; import android.annotation.AppIdInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.BroadcastOptions; Loading @@ -40,8 +41,10 @@ import android.content.pm.PackageInstaller; import android.net.Uri; import android.os.Bundle; import android.os.PowerExemptionManager; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.util.SparseArray; Loading @@ -49,6 +52,8 @@ import android.util.SparseArray; import com.android.internal.util.ArrayUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Helper class to send broadcasts for various situations. Loading Loading @@ -327,4 +332,45 @@ public final class BroadcastHelper { sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, pkgName, null, 0, installerPkg, null, userIds, instantUserIds, null /* broadcastAllowList */, null); } /** * Get broadcast params list based on the given package and uid list. The broadcast params are * used to send broadcast separately if the given packages have different visibility allow list. * * @param pkgList The names of packages which have changes. * @param uidList The uids of packages which have changes. * @param userId The user where packages reside. * @return The list of {@link BroadcastParams} object. */ public List<BroadcastParams> getBroadcastParams(@NonNull Computer snapshot, @NonNull String[] pkgList, @NonNull int[] uidList, @UserIdInt int userId) { final List<BroadcastParams> lists = new ArrayList<>(pkgList.length); // Get allow lists for the pkg in the pkgList. Merge into the existed pkgs and uids if // allow lists are the same. for (int i = 0; i < pkgList.length; i++) { final String pkgName = pkgList[i]; final int uid = uidList[i]; if (TextUtils.isEmpty(pkgName) || Process.INVALID_UID == uid) { continue; } int[] allowList = snapshot.getVisibilityAllowList(pkgName, userId); if (allowList == null) { allowList = new int[0]; } boolean merged = false; for (int j = 0; j < lists.size(); j++) { final BroadcastParams list = lists.get(j); if (Arrays.equals(list.getAllowList().get(userId), allowList)) { list.addPackage(pkgName, uid); merged = true; break; } } if (!merged) { lists.add(new BroadcastParams(pkgName, uid, allowList, userId)); } } return lists; } } services/core/java/com/android/server/pm/BroadcastParams.java 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.util.IntArray; import android.util.SparseArray; import com.android.internal.util.DataClass; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * A helper class that contains information about package names and uids that share the same allow * list for sending broadcasts. Used by various package helpers. */ @DataClass(genConstructor = false, genConstDefs = false) final class BroadcastParams { private final @NonNull List<String> mPackageNames; private final @NonNull IntArray mUids; private final @NonNull SparseArray<int[]> mAllowList; BroadcastParams(@NonNull String packageName, @IntRange(from = 0) int uid, @NonNull int[] allowList, @UserIdInt int userId) { mPackageNames = new ArrayList<>(Arrays.asList(packageName)); mUids = IntArray.wrap(new int[]{uid}); mAllowList = new SparseArray<>(1); mAllowList.put(userId, allowList); } public void addPackage(@NonNull String packageName, @IntRange(from = 0) int uid) { mPackageNames.add(packageName); mUids.add(uid); } // Code below generated by codegen v1.0.23. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code // // To regenerate run: // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/BroadcastParams.java // // To exclude the generated code from IntelliJ auto-formatting enable (one-time): // Settings > Editor > Code Style > Formatter Control //@formatter:off @DataClass.Generated.Member public @NonNull List<String> getPackageNames() { return mPackageNames; } @DataClass.Generated.Member public @NonNull IntArray getUids() { return mUids; } @DataClass.Generated.Member public @NonNull SparseArray<int[]> getAllowList() { return mAllowList; } @DataClass.Generated( time = 1651554793681L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/services/core/java/com/android/server/pm/BroadcastParams.java", inputSignatures = "private final @android.annotation.NonNull java.util.List<java.lang.String> mPackageNames\nprivate final @android.annotation.NonNull android.util.IntArray mUids\nprivate final @android.annotation.NonNull android.util.SparseArray<int[]> mAllowList\npublic void addPackage(java.lang.String,int)\nclass BroadcastParams extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)") @Deprecated private void __metadata() {} //@formatter:on // End of generated code } services/core/java/com/android/server/pm/DistractingPackageHelper.java +9 −39 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.server.pm; import static android.content.pm.PackageManager.RESTRICTION_NONE; import static android.os.Process.SYSTEM_UID; import android.annotation.NonNull; import android.content.Intent; Loading @@ -34,7 +33,6 @@ import com.android.internal.util.ArrayUtils; import com.android.server.pm.pkg.PackageStateInternal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** Loading Loading @@ -186,50 +184,22 @@ public final class DistractingPackageHelper { */ void sendDistractingPackagesChanged(@NonNull Computer snapshot, @NonNull String[] pkgList, int[] uidList, int userId, int distractionFlags) { final List<List<String>> pkgsToSend = new ArrayList(pkgList.length); final List<IntArray> uidsToSend = new ArrayList(pkgList.length); final List<SparseArray<int[]>> allowListsToSend = new ArrayList(pkgList.length); final int[] userIds = new int[] {userId}; // Get allow lists for the pkg in the pkgList. Merge into the existed pkgs and uids if // allow lists are the same. for (int i = 0; i < pkgList.length; i++) { final String pkgName = pkgList[i]; final int uid = uidList[i]; SparseArray<int[]> allowList = mInjector.getAppsFilter().getVisibilityAllowList( snapshot, snapshot.getPackageStateInternal(pkgName, SYSTEM_UID), userIds, snapshot.getPackageStates()); if (allowList == null) { allowList = new SparseArray<>(0); } boolean merged = false; for (int j = 0; j < allowListsToSend.size(); j++) { if (Arrays.equals(allowListsToSend.get(j).get(userId), allowList.get(userId))) { pkgsToSend.get(j).add(pkgName); uidsToSend.get(j).add(uid); merged = true; break; } } if (!merged) { pkgsToSend.add(new ArrayList<>(Arrays.asList(pkgName))); uidsToSend.add(IntArray.wrap(new int[] {uid})); allowListsToSend.add(allowList); } } final List<BroadcastParams> lists = mBroadcastHelper.getBroadcastParams( snapshot, pkgList, uidList, userId); final Handler handler = mInjector.getHandler(); for (int i = 0; i < pkgsToSend.size(); i++) { for (int i = 0; i < lists.size(); i++) { final Bundle extras = new Bundle(3); final BroadcastParams list = lists.get(i); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgsToSend.get(i).toArray(new String[pkgsToSend.get(i).size()])); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidsToSend.get(i).toArray()); list.getPackageNames().toArray(new String[0])); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, list.getUids().toArray()); extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, distractionFlags); final SparseArray<int[]> allowList = allowListsToSend.get(i).size() == 0 ? null : allowListsToSend.get(i); final SparseArray<int[]> allowList = list.getAllowList().size() == 0 ? null : list.getAllowList(); handler.post(() -> mBroadcastHelper.sendPackageBroadcast( Intent.ACTION_DISTRACTING_PACKAGES_CHANGED, null /* pkg */, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null /* targetPkg */, null /* finishedReceiver */, userIds, null /* instantUserIds */, null /* finishedReceiver */, new int[]{userId}, null /* instantUserIds */, allowList, null /* bOptions */)); } } Loading services/core/java/com/android/server/pm/SuspendPackageHelper.java +9 −38 Original line number Diff line number Diff line Loading @@ -51,7 +51,6 @@ import com.android.server.pm.pkg.mutate.PackageUserStateWrite; import com.android.server.utils.WatchedArrayMap; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.function.Predicate; Loading Loading @@ -588,48 +587,20 @@ public final class SuspendPackageHelper { @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) void sendPackagesSuspendedForUser(@NonNull Computer snapshot, @NonNull String intent, @NonNull String[] pkgList, @NonNull int[] uidList, int userId) { final List<List<String>> pkgsToSend = new ArrayList(pkgList.length); final List<IntArray> uidsToSend = new ArrayList(pkgList.length); final List<SparseArray<int[]>> allowListsToSend = new ArrayList(pkgList.length); final int[] userIds = new int[] {userId}; // Get allow lists for the pkg in the pkgList. Merge into the existed pkgs and uids if // allow lists are the same. for (int i = 0; i < pkgList.length; i++) { final String pkgName = pkgList[i]; final int uid = uidList[i]; SparseArray<int[]> allowList = mInjector.getAppsFilter().getVisibilityAllowList( snapshot, snapshot.getPackageStateInternal(pkgName, SYSTEM_UID), userIds, snapshot.getPackageStates()); if (allowList == null) { allowList = new SparseArray<>(0); } boolean merged = false; for (int j = 0; j < allowListsToSend.size(); j++) { if (Arrays.equals(allowListsToSend.get(j).get(userId), allowList.get(userId))) { pkgsToSend.get(j).add(pkgName); uidsToSend.get(j).add(uid); merged = true; break; } } if (!merged) { pkgsToSend.add(new ArrayList<>(Arrays.asList(pkgName))); uidsToSend.add(IntArray.wrap(new int[] {uid})); allowListsToSend.add(allowList); } } final List<BroadcastParams> lists = mBroadcastHelper.getBroadcastParams( snapshot, pkgList, uidList, userId); final Handler handler = mInjector.getHandler(); for (int i = 0; i < pkgsToSend.size(); i++) { for (int i = 0; i < lists.size(); i++) { final Bundle extras = new Bundle(3); final BroadcastParams list = lists.get(i); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgsToSend.get(i).toArray(new String[pkgsToSend.get(i).size()])); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidsToSend.get(i).toArray()); final SparseArray<int[]> allowList = allowListsToSend.get(i).size() == 0 ? null : allowListsToSend.get(i); list.getPackageNames().toArray(new String[0])); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, list.getUids().toArray()); final SparseArray<int[]> allowList = list.getAllowList().size() == 0 ? null : list.getAllowList(); handler.post(() -> mBroadcastHelper.sendPackageBroadcast(intent, null /* pkg */, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null /* targetPkg */, null /* finishedReceiver */, userIds, null /* instantUserIds */, null /* finishedReceiver */, new int[]{userId}, null /* instantUserIds */, allowList, null /* bOptions */)); } } Loading services/tests/mockingservicestests/src/com/android/server/pm/BroadcastHelperTest.kt 0 → 100644 +117 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm import com.android.server.testutils.whenever import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.mockito.Mock import org.mockito.MockitoAnnotations @RunWith(JUnit4::class) class BroadcastHelperTest { companion object { const val TEST_PACKAGE_1 = "com.android.test.package1" const val TEST_PACKAGE_2 = "com.android.test.package2" const val TEST_UID_1 = 10100 const val TEST_UID_2 = 10101 const val TEST_USER_ID = 0 } lateinit var broadcastHelper: BroadcastHelper lateinit var packagesToChange: Array<String> lateinit var uidsToChange: IntArray @Mock lateinit var snapshot: Computer @Rule @JvmField val rule = MockSystemRule() @Before open fun setup() { MockitoAnnotations.initMocks(this) rule.system().stageNominalSystemState() broadcastHelper = BroadcastHelper(rule.mocks().injector) packagesToChange = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2) uidsToChange = intArrayOf(TEST_UID_1, TEST_UID_2) } @Test fun getBroadcastParams_withSameVisibilityAllowList_shouldGroup() { val allowList = intArrayOf(10001, 10002, 10003) mockVisibilityAllowList(TEST_PACKAGE_1, allowList) mockVisibilityAllowList(TEST_PACKAGE_2, allowList) val broadcastParams: List<BroadcastParams> = broadcastHelper.getBroadcastParams( snapshot, packagesToChange, uidsToChange, TEST_USER_ID) assertThat(broadcastParams).hasSize(1) assertThat(broadcastParams[0].packageNames).containsExactlyElementsIn( packagesToChange.toCollection(ArrayList())) assertThat(broadcastParams[0].uids.toArray()).asList().containsExactlyElementsIn( uidsToChange.toCollection(ArrayList())) } @Test fun getBroadcastParams_withDifferentVisibilityAllowList_shouldNotGroup() { val allowList1 = intArrayOf(10001, 10002, 10003) val allowList2 = intArrayOf(10001, 10002, 10007) mockVisibilityAllowList(TEST_PACKAGE_1, allowList1) mockVisibilityAllowList(TEST_PACKAGE_2, allowList2) val broadcastParams: List<BroadcastParams> = broadcastHelper.getBroadcastParams( snapshot, packagesToChange, uidsToChange, TEST_USER_ID) assertThat(broadcastParams).hasSize(2) broadcastParams.forEachIndexed { i, params -> val changedPackages = params.packageNames val changedUids = params.uids assertThat(changedPackages[0]).isEqualTo(packagesToChange[i]) assertThat(changedUids[0]).isEqualTo(uidsToChange[i]) } } @Test fun getBroadcastParams_withNullVisibilityAllowList_shouldNotGroup() { val allowList = intArrayOf(10001, 10002, 10003) mockVisibilityAllowList(TEST_PACKAGE_1, allowList) mockVisibilityAllowList(TEST_PACKAGE_2, null) val broadcastParams: List<BroadcastParams> = broadcastHelper.getBroadcastParams( snapshot, packagesToChange, uidsToChange, TEST_USER_ID) assertThat(broadcastParams).hasSize(2) broadcastParams.forEachIndexed { i, params -> val changedPackages = params.packageNames val changedUids = params.uids assertThat(changedPackages[0]).isEqualTo(packagesToChange[i]) assertThat(changedUids[0]).isEqualTo(uidsToChange[i]) } } private fun mockVisibilityAllowList(pkgName: String, list: IntArray?) { whenever(snapshot.getVisibilityAllowList(pkgName, TEST_USER_ID)) .thenReturn(list ?: IntArray(0)) } } No newline at end of file Loading
services/core/java/com/android/server/pm/BroadcastHelper.java +46 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.Manifest; import android.annotation.AppIdInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.BroadcastOptions; Loading @@ -40,8 +41,10 @@ import android.content.pm.PackageInstaller; import android.net.Uri; import android.os.Bundle; import android.os.PowerExemptionManager; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.util.SparseArray; Loading @@ -49,6 +52,8 @@ import android.util.SparseArray; import com.android.internal.util.ArrayUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Helper class to send broadcasts for various situations. Loading Loading @@ -327,4 +332,45 @@ public final class BroadcastHelper { sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, pkgName, null, 0, installerPkg, null, userIds, instantUserIds, null /* broadcastAllowList */, null); } /** * Get broadcast params list based on the given package and uid list. The broadcast params are * used to send broadcast separately if the given packages have different visibility allow list. * * @param pkgList The names of packages which have changes. * @param uidList The uids of packages which have changes. * @param userId The user where packages reside. * @return The list of {@link BroadcastParams} object. */ public List<BroadcastParams> getBroadcastParams(@NonNull Computer snapshot, @NonNull String[] pkgList, @NonNull int[] uidList, @UserIdInt int userId) { final List<BroadcastParams> lists = new ArrayList<>(pkgList.length); // Get allow lists for the pkg in the pkgList. Merge into the existed pkgs and uids if // allow lists are the same. for (int i = 0; i < pkgList.length; i++) { final String pkgName = pkgList[i]; final int uid = uidList[i]; if (TextUtils.isEmpty(pkgName) || Process.INVALID_UID == uid) { continue; } int[] allowList = snapshot.getVisibilityAllowList(pkgName, userId); if (allowList == null) { allowList = new int[0]; } boolean merged = false; for (int j = 0; j < lists.size(); j++) { final BroadcastParams list = lists.get(j); if (Arrays.equals(list.getAllowList().get(userId), allowList)) { list.addPackage(pkgName, uid); merged = true; break; } } if (!merged) { lists.add(new BroadcastParams(pkgName, uid, allowList, userId)); } } return lists; } }
services/core/java/com/android/server/pm/BroadcastParams.java 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.util.IntArray; import android.util.SparseArray; import com.android.internal.util.DataClass; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * A helper class that contains information about package names and uids that share the same allow * list for sending broadcasts. Used by various package helpers. */ @DataClass(genConstructor = false, genConstDefs = false) final class BroadcastParams { private final @NonNull List<String> mPackageNames; private final @NonNull IntArray mUids; private final @NonNull SparseArray<int[]> mAllowList; BroadcastParams(@NonNull String packageName, @IntRange(from = 0) int uid, @NonNull int[] allowList, @UserIdInt int userId) { mPackageNames = new ArrayList<>(Arrays.asList(packageName)); mUids = IntArray.wrap(new int[]{uid}); mAllowList = new SparseArray<>(1); mAllowList.put(userId, allowList); } public void addPackage(@NonNull String packageName, @IntRange(from = 0) int uid) { mPackageNames.add(packageName); mUids.add(uid); } // Code below generated by codegen v1.0.23. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code // // To regenerate run: // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/BroadcastParams.java // // To exclude the generated code from IntelliJ auto-formatting enable (one-time): // Settings > Editor > Code Style > Formatter Control //@formatter:off @DataClass.Generated.Member public @NonNull List<String> getPackageNames() { return mPackageNames; } @DataClass.Generated.Member public @NonNull IntArray getUids() { return mUids; } @DataClass.Generated.Member public @NonNull SparseArray<int[]> getAllowList() { return mAllowList; } @DataClass.Generated( time = 1651554793681L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/services/core/java/com/android/server/pm/BroadcastParams.java", inputSignatures = "private final @android.annotation.NonNull java.util.List<java.lang.String> mPackageNames\nprivate final @android.annotation.NonNull android.util.IntArray mUids\nprivate final @android.annotation.NonNull android.util.SparseArray<int[]> mAllowList\npublic void addPackage(java.lang.String,int)\nclass BroadcastParams extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)") @Deprecated private void __metadata() {} //@formatter:on // End of generated code }
services/core/java/com/android/server/pm/DistractingPackageHelper.java +9 −39 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.server.pm; import static android.content.pm.PackageManager.RESTRICTION_NONE; import static android.os.Process.SYSTEM_UID; import android.annotation.NonNull; import android.content.Intent; Loading @@ -34,7 +33,6 @@ import com.android.internal.util.ArrayUtils; import com.android.server.pm.pkg.PackageStateInternal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** Loading Loading @@ -186,50 +184,22 @@ public final class DistractingPackageHelper { */ void sendDistractingPackagesChanged(@NonNull Computer snapshot, @NonNull String[] pkgList, int[] uidList, int userId, int distractionFlags) { final List<List<String>> pkgsToSend = new ArrayList(pkgList.length); final List<IntArray> uidsToSend = new ArrayList(pkgList.length); final List<SparseArray<int[]>> allowListsToSend = new ArrayList(pkgList.length); final int[] userIds = new int[] {userId}; // Get allow lists for the pkg in the pkgList. Merge into the existed pkgs and uids if // allow lists are the same. for (int i = 0; i < pkgList.length; i++) { final String pkgName = pkgList[i]; final int uid = uidList[i]; SparseArray<int[]> allowList = mInjector.getAppsFilter().getVisibilityAllowList( snapshot, snapshot.getPackageStateInternal(pkgName, SYSTEM_UID), userIds, snapshot.getPackageStates()); if (allowList == null) { allowList = new SparseArray<>(0); } boolean merged = false; for (int j = 0; j < allowListsToSend.size(); j++) { if (Arrays.equals(allowListsToSend.get(j).get(userId), allowList.get(userId))) { pkgsToSend.get(j).add(pkgName); uidsToSend.get(j).add(uid); merged = true; break; } } if (!merged) { pkgsToSend.add(new ArrayList<>(Arrays.asList(pkgName))); uidsToSend.add(IntArray.wrap(new int[] {uid})); allowListsToSend.add(allowList); } } final List<BroadcastParams> lists = mBroadcastHelper.getBroadcastParams( snapshot, pkgList, uidList, userId); final Handler handler = mInjector.getHandler(); for (int i = 0; i < pkgsToSend.size(); i++) { for (int i = 0; i < lists.size(); i++) { final Bundle extras = new Bundle(3); final BroadcastParams list = lists.get(i); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgsToSend.get(i).toArray(new String[pkgsToSend.get(i).size()])); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidsToSend.get(i).toArray()); list.getPackageNames().toArray(new String[0])); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, list.getUids().toArray()); extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, distractionFlags); final SparseArray<int[]> allowList = allowListsToSend.get(i).size() == 0 ? null : allowListsToSend.get(i); final SparseArray<int[]> allowList = list.getAllowList().size() == 0 ? null : list.getAllowList(); handler.post(() -> mBroadcastHelper.sendPackageBroadcast( Intent.ACTION_DISTRACTING_PACKAGES_CHANGED, null /* pkg */, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null /* targetPkg */, null /* finishedReceiver */, userIds, null /* instantUserIds */, null /* finishedReceiver */, new int[]{userId}, null /* instantUserIds */, allowList, null /* bOptions */)); } } Loading
services/core/java/com/android/server/pm/SuspendPackageHelper.java +9 −38 Original line number Diff line number Diff line Loading @@ -51,7 +51,6 @@ import com.android.server.pm.pkg.mutate.PackageUserStateWrite; import com.android.server.utils.WatchedArrayMap; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.function.Predicate; Loading Loading @@ -588,48 +587,20 @@ public final class SuspendPackageHelper { @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) void sendPackagesSuspendedForUser(@NonNull Computer snapshot, @NonNull String intent, @NonNull String[] pkgList, @NonNull int[] uidList, int userId) { final List<List<String>> pkgsToSend = new ArrayList(pkgList.length); final List<IntArray> uidsToSend = new ArrayList(pkgList.length); final List<SparseArray<int[]>> allowListsToSend = new ArrayList(pkgList.length); final int[] userIds = new int[] {userId}; // Get allow lists for the pkg in the pkgList. Merge into the existed pkgs and uids if // allow lists are the same. for (int i = 0; i < pkgList.length; i++) { final String pkgName = pkgList[i]; final int uid = uidList[i]; SparseArray<int[]> allowList = mInjector.getAppsFilter().getVisibilityAllowList( snapshot, snapshot.getPackageStateInternal(pkgName, SYSTEM_UID), userIds, snapshot.getPackageStates()); if (allowList == null) { allowList = new SparseArray<>(0); } boolean merged = false; for (int j = 0; j < allowListsToSend.size(); j++) { if (Arrays.equals(allowListsToSend.get(j).get(userId), allowList.get(userId))) { pkgsToSend.get(j).add(pkgName); uidsToSend.get(j).add(uid); merged = true; break; } } if (!merged) { pkgsToSend.add(new ArrayList<>(Arrays.asList(pkgName))); uidsToSend.add(IntArray.wrap(new int[] {uid})); allowListsToSend.add(allowList); } } final List<BroadcastParams> lists = mBroadcastHelper.getBroadcastParams( snapshot, pkgList, uidList, userId); final Handler handler = mInjector.getHandler(); for (int i = 0; i < pkgsToSend.size(); i++) { for (int i = 0; i < lists.size(); i++) { final Bundle extras = new Bundle(3); final BroadcastParams list = lists.get(i); extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgsToSend.get(i).toArray(new String[pkgsToSend.get(i).size()])); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidsToSend.get(i).toArray()); final SparseArray<int[]> allowList = allowListsToSend.get(i).size() == 0 ? null : allowListsToSend.get(i); list.getPackageNames().toArray(new String[0])); extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, list.getUids().toArray()); final SparseArray<int[]> allowList = list.getAllowList().size() == 0 ? null : list.getAllowList(); handler.post(() -> mBroadcastHelper.sendPackageBroadcast(intent, null /* pkg */, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null /* targetPkg */, null /* finishedReceiver */, userIds, null /* instantUserIds */, null /* finishedReceiver */, new int[]{userId}, null /* instantUserIds */, allowList, null /* bOptions */)); } } Loading
services/tests/mockingservicestests/src/com/android/server/pm/BroadcastHelperTest.kt 0 → 100644 +117 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm import com.android.server.testutils.whenever import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.mockito.Mock import org.mockito.MockitoAnnotations @RunWith(JUnit4::class) class BroadcastHelperTest { companion object { const val TEST_PACKAGE_1 = "com.android.test.package1" const val TEST_PACKAGE_2 = "com.android.test.package2" const val TEST_UID_1 = 10100 const val TEST_UID_2 = 10101 const val TEST_USER_ID = 0 } lateinit var broadcastHelper: BroadcastHelper lateinit var packagesToChange: Array<String> lateinit var uidsToChange: IntArray @Mock lateinit var snapshot: Computer @Rule @JvmField val rule = MockSystemRule() @Before open fun setup() { MockitoAnnotations.initMocks(this) rule.system().stageNominalSystemState() broadcastHelper = BroadcastHelper(rule.mocks().injector) packagesToChange = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2) uidsToChange = intArrayOf(TEST_UID_1, TEST_UID_2) } @Test fun getBroadcastParams_withSameVisibilityAllowList_shouldGroup() { val allowList = intArrayOf(10001, 10002, 10003) mockVisibilityAllowList(TEST_PACKAGE_1, allowList) mockVisibilityAllowList(TEST_PACKAGE_2, allowList) val broadcastParams: List<BroadcastParams> = broadcastHelper.getBroadcastParams( snapshot, packagesToChange, uidsToChange, TEST_USER_ID) assertThat(broadcastParams).hasSize(1) assertThat(broadcastParams[0].packageNames).containsExactlyElementsIn( packagesToChange.toCollection(ArrayList())) assertThat(broadcastParams[0].uids.toArray()).asList().containsExactlyElementsIn( uidsToChange.toCollection(ArrayList())) } @Test fun getBroadcastParams_withDifferentVisibilityAllowList_shouldNotGroup() { val allowList1 = intArrayOf(10001, 10002, 10003) val allowList2 = intArrayOf(10001, 10002, 10007) mockVisibilityAllowList(TEST_PACKAGE_1, allowList1) mockVisibilityAllowList(TEST_PACKAGE_2, allowList2) val broadcastParams: List<BroadcastParams> = broadcastHelper.getBroadcastParams( snapshot, packagesToChange, uidsToChange, TEST_USER_ID) assertThat(broadcastParams).hasSize(2) broadcastParams.forEachIndexed { i, params -> val changedPackages = params.packageNames val changedUids = params.uids assertThat(changedPackages[0]).isEqualTo(packagesToChange[i]) assertThat(changedUids[0]).isEqualTo(uidsToChange[i]) } } @Test fun getBroadcastParams_withNullVisibilityAllowList_shouldNotGroup() { val allowList = intArrayOf(10001, 10002, 10003) mockVisibilityAllowList(TEST_PACKAGE_1, allowList) mockVisibilityAllowList(TEST_PACKAGE_2, null) val broadcastParams: List<BroadcastParams> = broadcastHelper.getBroadcastParams( snapshot, packagesToChange, uidsToChange, TEST_USER_ID) assertThat(broadcastParams).hasSize(2) broadcastParams.forEachIndexed { i, params -> val changedPackages = params.packageNames val changedUids = params.uids assertThat(changedPackages[0]).isEqualTo(packagesToChange[i]) assertThat(changedUids[0]).isEqualTo(uidsToChange[i]) } } private fun mockVisibilityAllowList(pkgName: String, list: IntArray?) { whenever(snapshot.getVisibilityAllowList(pkgName, TEST_USER_ID)) .thenReturn(list ?: IntArray(0)) } } No newline at end of file