Merge "Avoid showing the disambiguation dialog"
This commit is contained in:
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user