Loading services/core/java/com/android/server/pm/ComputerEngine.java +3 −2 Original line number Diff line number Diff line Loading @@ -3121,7 +3121,7 @@ public class ComputerEngine implements Computer { final ResolveInfo ri = query.get(j); if (DEBUG_PREFERRED || debug) { Slog.v(TAG, "Match for " + ri.activityInfo + ": 0x" + Integer.toHexString(match)); + ": 0x" + Integer.toHexString(ri.match)); } if (ri.match > match) { match = ri.match; Loading Loading @@ -3213,7 +3213,8 @@ public class ComputerEngine implements Computer { // clear it and re-ask the user their preference, if we're looking for // an "always" type entry. if (always && !pa.mPref.sameSet(query, excludeSetupWizardHomeActivity)) { if (always && !pa.mPref.sameSet(query, excludeSetupWizardHomeActivity, userId)) { if (pa.mPref.isSuperset(query, excludeSetupWizardHomeActivity)) { if (allowSetMutation) { // some components of the set are no longer present in Loading services/core/java/com/android/server/pm/PreferredComponent.java +13 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.pm; import android.content.ComponentName; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.util.Slog; Loading @@ -27,6 +28,7 @@ import android.util.TypedXmlSerializer; import com.android.internal.util.XmlUtils; import com.android.server.LocalServices; import com.android.server.pm.pkg.PackageUserState; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; Loading Loading @@ -197,7 +199,7 @@ public class PreferredComponent { } } public boolean sameSet(List<ResolveInfo> query, boolean excludeSetupWizardPackage) { public boolean sameSet(List<ResolveInfo> query, boolean excludeSetupWizardPackage, int userId) { if (mSetPackages == null) { return query == null; } Loading @@ -206,6 +208,7 @@ public class PreferredComponent { } final int NQ = query.size(); final int NS = mSetPackages.length; final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); int numMatch = 0; for (int i=0; i<NQ; i++) { ResolveInfo ri = query.get(i); Loading @@ -218,6 +221,15 @@ public class PreferredComponent { continue; } // Avoid showing the disambiguation dialog if the package which is installed with // reason INSTALL_REASON_DEVICE_SETUP. final PackageUserState pkgUserState = pmi.getPackageStateInternal(ai.packageName).getUserStates().get(userId); if (pkgUserState != null && pkgUserState.getInstallReason() == PackageManager.INSTALL_REASON_DEVICE_SETUP) { continue; } for (int j=0; j<NS; j++) { if (mSetPackages[j].equals(ai.packageName) && mSetClasses[j].equals(ai.name)) { Loading services/core/java/com/android/server/pm/Settings.java +7 −6 Original line number Diff line number Diff line Loading @@ -55,11 +55,7 @@ import android.content.pm.parsing.component.ParsedIntentInfo; import android.content.pm.parsing.component.ParsedMainComponent; import android.content.pm.parsing.component.ParsedPermission; import android.content.pm.parsing.component.ParsedProcess; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; import android.content.pm.pkg.PackageUserStateUtils; import com.android.server.pm.pkg.SuspendParams; import android.net.Uri; import android.os.Binder; import android.os.Build; Loading Loading @@ -117,6 +113,9 @@ import com.android.server.pm.permission.LegacyPermissionDataProvider; import com.android.server.pm.permission.LegacyPermissionSettings; import com.android.server.pm.permission.LegacyPermissionState; import com.android.server.pm.permission.LegacyPermissionState.PermissionState; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; import com.android.server.pm.pkg.SuspendParams; import com.android.server.pm.verify.domain.DomainVerificationLegacySettings; import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; import com.android.server.pm.verify.domain.DomainVerificationPersistence; Loading Loading @@ -3293,7 +3292,7 @@ public final class Settings implements Watchable, Snappable { int systemMatch = 0; int thirdPartyMatch = 0; final int numMatches = (ri == null ? 0 : ri.size()); if (numMatches <= 1) { if (numMatches < 1) { Slog.w(TAG, "No potential matches found for " + intent + " while setting preferred " + cn.flattenToShortString()); return; Loading Loading @@ -4762,7 +4761,9 @@ public final class Settings implements Watchable, Snappable { pw.print(" instant="); pw.print(ps.getInstantApp(user.id)); pw.print(" virtual="); pw.println(ps.getVirtualPreload(user.id)); pw.print(ps.getVirtualPreload(user.id)); pw.print(" installReason="); pw.println(ps.getInstallReason(user.id)); if (ps.getSuspended(user.id)) { pw.print(prefix); Loading services/tests/servicestests/src/com/android/server/pm/PreferredComponentTest.java 0 → 100644 +153 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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 static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import android.content.ComponentName; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.util.SparseArray; import com.android.server.LocalServices; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateImpl; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.ArrayList; import java.util.List; @Presubmit @RunWith(JUnit4.class) public class PreferredComponentTest { private PackageManagerInternal mMockPackageManagerInternal; @Before public void setUp() { mMockPackageManagerInternal = mock(PackageManagerInternal.class); LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal); } @Test public void testPreferredComponent_sameSet_withAppInstalledByDeviceSetup() { // Assume we have two ResolveInfos that handle the same Intent. final int userId = UserHandle.USER_SYSTEM; final List<ResolveInfo> query = new ArrayList<>(); query.add(createResolveInfo(0, userId)); query.add(createResolveInfo(1, userId)); // ResolveInfo(0) is already set as the preferred one when only it exists. final ComponentName component = query.get(0).getComponentInfo().getComponentName(); final PreferredActivity pa = new PreferredActivity(new IntentFilter("TEST_ACTION"), 0 /* match */, new ComponentName[]{component}, component, true /* always */); // Assume ResolveInfo(0) is preinstalled, and ResolveInfo(1) is installed when device setup. final PackageUserState pkgUserState0 = new PackageUserStateImpl().setInstallReason( PackageManager.INSTALL_REASON_UNKNOWN); final PackageUserState pkgUserState1 = new PackageUserStateImpl().setInstallReason( PackageManager.INSTALL_REASON_DEVICE_SETUP); final PackageStateInternal psInt0 = mock(PackageStateInternal.class); final PackageStateInternal psInt1 = mock(PackageStateInternal.class); final SparseArray<Object> userStates0 = mock(SparseArray.class); final SparseArray<Object> userStates1 = mock(SparseArray.class); doReturn(psInt0).when(mMockPackageManagerInternal).getPackageStateInternal("foo_bar0"); doReturn(psInt1).when(mMockPackageManagerInternal).getPackageStateInternal("foo_bar1"); doReturn(userStates0).when(psInt0).getUserStates(); doReturn(userStates1).when(psInt1).getUserStates(); doReturn(pkgUserState0).when(userStates0).get(anyInt()); doReturn(pkgUserState1).when(userStates1).get(anyInt()); // Check if ResolveInfo(1) which is installed by device setup affects the preferred set and // this may trigger disambiguation dialog. assertTrue(pa.mPref.sameSet(query, true /* excludeSetupWizardPackage */, userId)); } @Test public void testPreferredComponent_notSameSet_withAppNotInstalledByDeviceSetup() { // Assume we have two ResolveInfos that handle the same Intent. final int userId = UserHandle.USER_SYSTEM; final List<ResolveInfo> query = new ArrayList<>(); query.add(createResolveInfo(0, userId)); query.add(createResolveInfo(1, userId)); // ResolveInfo(0) is already set as the preferred one when only it exists. final ComponentName component = query.get(0).getComponentInfo().getComponentName(); final PreferredActivity pa = new PreferredActivity(new IntentFilter("TEST_ACTION"), 0 /* match */, new ComponentName[]{component}, component, true /* always */); // Assume ResolveInfo(0) is preinstalled, and ResolveInfo(1) is installed by user. final PackageUserState pkgUserState0 = new PackageUserStateImpl().setInstallReason( PackageManager.INSTALL_REASON_UNKNOWN); final PackageUserState pkgUserState1 = new PackageUserStateImpl().setInstallReason( PackageManager.INSTALL_REASON_USER); final PackageStateInternal psInt0 = mock(PackageStateInternal.class); final PackageStateInternal psInt1 = mock(PackageStateInternal.class); final SparseArray<Object> userStates0 = mock(SparseArray.class); final SparseArray<Object> userStates1 = mock(SparseArray.class); doReturn(psInt0).when(mMockPackageManagerInternal).getPackageStateInternal("foo_bar0"); doReturn(psInt1).when(mMockPackageManagerInternal).getPackageStateInternal("foo_bar1"); doReturn(userStates0).when(psInt0).getUserStates(); doReturn(userStates1).when(psInt1).getUserStates(); doReturn(pkgUserState0).when(userStates0).get(anyInt()); doReturn(pkgUserState1).when(userStates1).get(anyInt()); // Check if ResolveInfo(1) which is installed by user affects the preferred set and // this may trigger disambiguation dialog. assertFalse(pa.mPref.sameSet(query, true /* excludeSetupWizardPackage */, userId)); } private static ResolveInfo createResolveInfo(int i, int userId) { final ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = createActivityInfo(i); resolveInfo.targetUserId = userId; return resolveInfo; } private static ActivityInfo createActivityInfo(int i) { final ActivityInfo ai = new ActivityInfo(); ai.name = "activity_name" + i; ai.packageName = "foo_bar" + i; ai.enabled = true; ai.exported = true; ai.permission = null; ai.applicationInfo = createApplicationInfo(i, ai.packageName); return ai; } private static ApplicationInfo createApplicationInfo(int i, String packageName) { final ApplicationInfo ai = new ApplicationInfo(); ai.name = "app_name" + i; ai.packageName = packageName; ai.enabled = true; return ai; } } Loading
services/core/java/com/android/server/pm/ComputerEngine.java +3 −2 Original line number Diff line number Diff line Loading @@ -3121,7 +3121,7 @@ public class ComputerEngine implements Computer { final ResolveInfo ri = query.get(j); if (DEBUG_PREFERRED || debug) { Slog.v(TAG, "Match for " + ri.activityInfo + ": 0x" + Integer.toHexString(match)); + ": 0x" + Integer.toHexString(ri.match)); } if (ri.match > match) { match = ri.match; Loading Loading @@ -3213,7 +3213,8 @@ public class ComputerEngine implements Computer { // clear it and re-ask the user their preference, if we're looking for // an "always" type entry. if (always && !pa.mPref.sameSet(query, excludeSetupWizardHomeActivity)) { if (always && !pa.mPref.sameSet(query, excludeSetupWizardHomeActivity, userId)) { if (pa.mPref.isSuperset(query, excludeSetupWizardHomeActivity)) { if (allowSetMutation) { // some components of the set are no longer present in Loading
services/core/java/com/android/server/pm/PreferredComponent.java +13 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.pm; import android.content.ComponentName; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.util.Slog; Loading @@ -27,6 +28,7 @@ import android.util.TypedXmlSerializer; import com.android.internal.util.XmlUtils; import com.android.server.LocalServices; import com.android.server.pm.pkg.PackageUserState; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; Loading Loading @@ -197,7 +199,7 @@ public class PreferredComponent { } } public boolean sameSet(List<ResolveInfo> query, boolean excludeSetupWizardPackage) { public boolean sameSet(List<ResolveInfo> query, boolean excludeSetupWizardPackage, int userId) { if (mSetPackages == null) { return query == null; } Loading @@ -206,6 +208,7 @@ public class PreferredComponent { } final int NQ = query.size(); final int NS = mSetPackages.length; final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); int numMatch = 0; for (int i=0; i<NQ; i++) { ResolveInfo ri = query.get(i); Loading @@ -218,6 +221,15 @@ public class PreferredComponent { continue; } // Avoid showing the disambiguation dialog if the package which is installed with // reason INSTALL_REASON_DEVICE_SETUP. final PackageUserState pkgUserState = pmi.getPackageStateInternal(ai.packageName).getUserStates().get(userId); if (pkgUserState != null && pkgUserState.getInstallReason() == PackageManager.INSTALL_REASON_DEVICE_SETUP) { continue; } for (int j=0; j<NS; j++) { if (mSetPackages[j].equals(ai.packageName) && mSetClasses[j].equals(ai.name)) { Loading
services/core/java/com/android/server/pm/Settings.java +7 −6 Original line number Diff line number Diff line Loading @@ -55,11 +55,7 @@ import android.content.pm.parsing.component.ParsedIntentInfo; import android.content.pm.parsing.component.ParsedMainComponent; import android.content.pm.parsing.component.ParsedPermission; import android.content.pm.parsing.component.ParsedProcess; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; import android.content.pm.pkg.PackageUserStateUtils; import com.android.server.pm.pkg.SuspendParams; import android.net.Uri; import android.os.Binder; import android.os.Build; Loading Loading @@ -117,6 +113,9 @@ import com.android.server.pm.permission.LegacyPermissionDataProvider; import com.android.server.pm.permission.LegacyPermissionSettings; import com.android.server.pm.permission.LegacyPermissionState; import com.android.server.pm.permission.LegacyPermissionState.PermissionState; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; import com.android.server.pm.pkg.SuspendParams; import com.android.server.pm.verify.domain.DomainVerificationLegacySettings; import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; import com.android.server.pm.verify.domain.DomainVerificationPersistence; Loading Loading @@ -3293,7 +3292,7 @@ public final class Settings implements Watchable, Snappable { int systemMatch = 0; int thirdPartyMatch = 0; final int numMatches = (ri == null ? 0 : ri.size()); if (numMatches <= 1) { if (numMatches < 1) { Slog.w(TAG, "No potential matches found for " + intent + " while setting preferred " + cn.flattenToShortString()); return; Loading Loading @@ -4762,7 +4761,9 @@ public final class Settings implements Watchable, Snappable { pw.print(" instant="); pw.print(ps.getInstantApp(user.id)); pw.print(" virtual="); pw.println(ps.getVirtualPreload(user.id)); pw.print(ps.getVirtualPreload(user.id)); pw.print(" installReason="); pw.println(ps.getInstallReason(user.id)); if (ps.getSuspended(user.id)) { pw.print(prefix); Loading
services/tests/servicestests/src/com/android/server/pm/PreferredComponentTest.java 0 → 100644 +153 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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 static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import android.content.ComponentName; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.util.SparseArray; import com.android.server.LocalServices; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateImpl; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.ArrayList; import java.util.List; @Presubmit @RunWith(JUnit4.class) public class PreferredComponentTest { private PackageManagerInternal mMockPackageManagerInternal; @Before public void setUp() { mMockPackageManagerInternal = mock(PackageManagerInternal.class); LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal); } @Test public void testPreferredComponent_sameSet_withAppInstalledByDeviceSetup() { // Assume we have two ResolveInfos that handle the same Intent. final int userId = UserHandle.USER_SYSTEM; final List<ResolveInfo> query = new ArrayList<>(); query.add(createResolveInfo(0, userId)); query.add(createResolveInfo(1, userId)); // ResolveInfo(0) is already set as the preferred one when only it exists. final ComponentName component = query.get(0).getComponentInfo().getComponentName(); final PreferredActivity pa = new PreferredActivity(new IntentFilter("TEST_ACTION"), 0 /* match */, new ComponentName[]{component}, component, true /* always */); // Assume ResolveInfo(0) is preinstalled, and ResolveInfo(1) is installed when device setup. final PackageUserState pkgUserState0 = new PackageUserStateImpl().setInstallReason( PackageManager.INSTALL_REASON_UNKNOWN); final PackageUserState pkgUserState1 = new PackageUserStateImpl().setInstallReason( PackageManager.INSTALL_REASON_DEVICE_SETUP); final PackageStateInternal psInt0 = mock(PackageStateInternal.class); final PackageStateInternal psInt1 = mock(PackageStateInternal.class); final SparseArray<Object> userStates0 = mock(SparseArray.class); final SparseArray<Object> userStates1 = mock(SparseArray.class); doReturn(psInt0).when(mMockPackageManagerInternal).getPackageStateInternal("foo_bar0"); doReturn(psInt1).when(mMockPackageManagerInternal).getPackageStateInternal("foo_bar1"); doReturn(userStates0).when(psInt0).getUserStates(); doReturn(userStates1).when(psInt1).getUserStates(); doReturn(pkgUserState0).when(userStates0).get(anyInt()); doReturn(pkgUserState1).when(userStates1).get(anyInt()); // Check if ResolveInfo(1) which is installed by device setup affects the preferred set and // this may trigger disambiguation dialog. assertTrue(pa.mPref.sameSet(query, true /* excludeSetupWizardPackage */, userId)); } @Test public void testPreferredComponent_notSameSet_withAppNotInstalledByDeviceSetup() { // Assume we have two ResolveInfos that handle the same Intent. final int userId = UserHandle.USER_SYSTEM; final List<ResolveInfo> query = new ArrayList<>(); query.add(createResolveInfo(0, userId)); query.add(createResolveInfo(1, userId)); // ResolveInfo(0) is already set as the preferred one when only it exists. final ComponentName component = query.get(0).getComponentInfo().getComponentName(); final PreferredActivity pa = new PreferredActivity(new IntentFilter("TEST_ACTION"), 0 /* match */, new ComponentName[]{component}, component, true /* always */); // Assume ResolveInfo(0) is preinstalled, and ResolveInfo(1) is installed by user. final PackageUserState pkgUserState0 = new PackageUserStateImpl().setInstallReason( PackageManager.INSTALL_REASON_UNKNOWN); final PackageUserState pkgUserState1 = new PackageUserStateImpl().setInstallReason( PackageManager.INSTALL_REASON_USER); final PackageStateInternal psInt0 = mock(PackageStateInternal.class); final PackageStateInternal psInt1 = mock(PackageStateInternal.class); final SparseArray<Object> userStates0 = mock(SparseArray.class); final SparseArray<Object> userStates1 = mock(SparseArray.class); doReturn(psInt0).when(mMockPackageManagerInternal).getPackageStateInternal("foo_bar0"); doReturn(psInt1).when(mMockPackageManagerInternal).getPackageStateInternal("foo_bar1"); doReturn(userStates0).when(psInt0).getUserStates(); doReturn(userStates1).when(psInt1).getUserStates(); doReturn(pkgUserState0).when(userStates0).get(anyInt()); doReturn(pkgUserState1).when(userStates1).get(anyInt()); // Check if ResolveInfo(1) which is installed by user affects the preferred set and // this may trigger disambiguation dialog. assertFalse(pa.mPref.sameSet(query, true /* excludeSetupWizardPackage */, userId)); } private static ResolveInfo createResolveInfo(int i, int userId) { final ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = createActivityInfo(i); resolveInfo.targetUserId = userId; return resolveInfo; } private static ActivityInfo createActivityInfo(int i) { final ActivityInfo ai = new ActivityInfo(); ai.name = "activity_name" + i; ai.packageName = "foo_bar" + i; ai.enabled = true; ai.exported = true; ai.permission = null; ai.applicationInfo = createApplicationInfo(i, ai.packageName); return ai; } private static ApplicationInfo createApplicationInfo(int i, String packageName) { final ApplicationInfo ai = new ApplicationInfo(); ai.name = "app_name" + i; ai.packageName = packageName; ai.enabled = true; return ai; } }