Implement uninstall behaviour for archiving
Test: ArchiveManagerTest Bug: 282952870 Change-Id: I8d9d432afa313866e9810a52b48b9c6277e80ff2
This commit is contained in:
@@ -16,14 +16,28 @@
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.LauncherActivityInfo;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.VersionedPackage;
|
||||
import android.os.Binder;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.pm.pkg.ArchiveState;
|
||||
import com.android.server.pm.pkg.ArchiveState.ArchiveActivityInfo;
|
||||
import com.android.server.pm.pkg.PackageStateInternal;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -35,37 +49,103 @@ import java.util.Objects;
|
||||
*/
|
||||
final class ArchiveManager {
|
||||
|
||||
private final Context mContext;
|
||||
private final PackageManagerService mPm;
|
||||
|
||||
ArchiveManager(PackageManagerService mPm) {
|
||||
@Nullable
|
||||
private LauncherApps mLauncherApps;
|
||||
|
||||
ArchiveManager(Context context, PackageManagerService mPm) {
|
||||
this.mContext = context;
|
||||
this.mPm = mPm;
|
||||
}
|
||||
|
||||
void archiveApp(
|
||||
@NonNull String packageName,
|
||||
@NonNull String callerPackageName,
|
||||
int userId,
|
||||
@NonNull UserHandle user,
|
||||
@NonNull IntentSender intentSender) throws PackageManager.NameNotFoundException {
|
||||
Objects.requireNonNull(packageName);
|
||||
Objects.requireNonNull(callerPackageName);
|
||||
Objects.requireNonNull(user);
|
||||
Objects.requireNonNull(intentSender);
|
||||
|
||||
Computer snapshot = mPm.snapshotComputer();
|
||||
int callingUid = Binder.getCallingUid();
|
||||
int userId = user.getIdentifier();
|
||||
String callingPackageName = snapshot.getNameForUid(callingUid);
|
||||
snapshot.enforceCrossUserPermission(callingUid, userId, true, true, "archiveApp");
|
||||
snapshot.enforceCrossUserPermission(callingUid, userId, true, true,
|
||||
"archiveApp");
|
||||
verifyCaller(callerPackageName, callingPackageName);
|
||||
|
||||
PackageStateInternal ps = snapshot.getPackageStateInternal(packageName);
|
||||
PackageStateInternal ps = getPackageState(packageName, snapshot, callingUid, user);
|
||||
verifyInstallOwnership(packageName, callingPackageName, ps.getInstallSource());
|
||||
|
||||
List<LauncherActivityInfo> mainActivities = getLauncherApps().getActivityList(
|
||||
ps.getPackageName(),
|
||||
new UserHandle(userId));
|
||||
// TODO(b/291569242) Verify that this list is not empty and return failure with intentsender
|
||||
|
||||
storeArchiveState(ps, mainActivities, userId);
|
||||
|
||||
// TODO(b/278553670) Add special strings for the delete dialog
|
||||
mPm.mInstallerService.uninstall(
|
||||
new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
|
||||
callerPackageName, DELETE_KEEP_DATA, intentSender, userId);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static PackageStateInternal getPackageState(String packageName,
|
||||
Computer snapshot, int callingUid, UserHandle user)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
PackageStateInternal ps = snapshot.getPackageStateFiltered(packageName, callingUid,
|
||||
user.getIdentifier());
|
||||
if (ps == null) {
|
||||
throw new PackageManager.NameNotFoundException(
|
||||
TextUtils.formatSimple("Package %s not found.", packageName));
|
||||
}
|
||||
return ps;
|
||||
}
|
||||
|
||||
verifyInstallOwnership(packageName, callingPackageName, ps);
|
||||
private LauncherApps getLauncherApps() {
|
||||
if (mLauncherApps == null) {
|
||||
mLauncherApps = mContext.getSystemService(LauncherApps.class);
|
||||
}
|
||||
return mLauncherApps;
|
||||
}
|
||||
|
||||
// TODO(b/278553670) Complete implementations
|
||||
throw new UnsupportedOperationException("Method not implemented.");
|
||||
private void storeArchiveState(PackageStateInternal ps,
|
||||
List<LauncherActivityInfo> mainActivities, int userId)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
List<ArchiveActivityInfo> activityInfos = new ArrayList<>();
|
||||
for (int i = 0; i < mainActivities.size(); i++) {
|
||||
// TODO(b/278553670) Extract and store launcher icons
|
||||
ArchiveActivityInfo activityInfo = new ArchiveActivityInfo(
|
||||
mainActivities.get(i).getLabel().toString(),
|
||||
Path.of("/TODO"), null);
|
||||
activityInfos.add(activityInfo);
|
||||
}
|
||||
// TODO(b/278553670) Adapt installer check verifyInstallOwnership and check for null there
|
||||
InstallSource installSource = ps.getInstallSource();
|
||||
String installerPackageName = installSource.mUpdateOwnerPackageName != null
|
||||
? installSource.mUpdateOwnerPackageName : installSource.mInstallerPackageName;
|
||||
|
||||
synchronized (mPm.mLock) {
|
||||
getPackageSetting(ps.getPackageName(), userId).modifyUserState(userId).setArchiveState(
|
||||
new ArchiveState(activityInfos, installerPackageName));
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@GuardedBy("mPm.mLock")
|
||||
private PackageSetting getPackageSetting(String packageName, int userId)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
|
||||
if (ps == null || !ps.getUserStateOrDefault(userId).isInstalled()) {
|
||||
throw new PackageManager.NameNotFoundException(
|
||||
TextUtils.formatSimple("Package %s not found.", packageName));
|
||||
}
|
||||
return ps;
|
||||
}
|
||||
|
||||
private static void verifyCaller(String callerPackageName, String callingPackageName) {
|
||||
@@ -80,14 +160,14 @@ final class ArchiveManager {
|
||||
}
|
||||
|
||||
private static void verifyInstallOwnership(String packageName, String callingPackageName,
|
||||
PackageStateInternal ps) {
|
||||
if (!TextUtils.equals(ps.getInstallSource().mInstallerPackageName,
|
||||
InstallSource installSource) {
|
||||
if (!TextUtils.equals(installSource.mInstallerPackageName,
|
||||
callingPackageName)) {
|
||||
throw new SecurityException(
|
||||
TextUtils.formatSimple("Caller is not the installer of record for %s.",
|
||||
packageName));
|
||||
}
|
||||
String updateOwnerPackageName = ps.getInstallSource().mUpdateOwnerPackageName;
|
||||
String updateOwnerPackageName = installSource.mUpdateOwnerPackageName;
|
||||
if (updateOwnerPackageName != null
|
||||
&& !TextUtils.equals(updateOwnerPackageName, callingPackageName)) {
|
||||
throw new SecurityException(
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 android.content.pm.PackageManager.DELETE_KEEP_DATA;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.LauncherActivityInfo;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.VersionedPackage;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.server.pm.pkg.ArchiveState;
|
||||
import com.android.server.pm.pkg.PackageStateInternal;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ArchiveManagerTest {
|
||||
|
||||
private static final String PACKAGE = "com.example";
|
||||
private static final String CALLER_PACKAGE = "com.vending";
|
||||
|
||||
@Rule
|
||||
public final MockSystemRule mMockSystem = new MockSystemRule();
|
||||
|
||||
@Mock
|
||||
private IntentSender mIntentSender;
|
||||
@Mock
|
||||
private Computer mComputer;
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private LauncherApps mLauncherApps;
|
||||
@Mock
|
||||
private PackageInstallerService mInstallerService;
|
||||
@Mock
|
||||
private PackageStateInternal mPackageState;
|
||||
|
||||
private final InstallSource mInstallSource =
|
||||
InstallSource.create(
|
||||
CALLER_PACKAGE,
|
||||
CALLER_PACKAGE,
|
||||
CALLER_PACKAGE,
|
||||
Binder.getCallingUid(),
|
||||
CALLER_PACKAGE,
|
||||
/* installerAttributionTag= */ null,
|
||||
/* packageSource= */ 0);
|
||||
|
||||
private final List<LauncherActivityInfo> mLauncherActivityInfos = createLauncherActivities();
|
||||
|
||||
private PackageSetting mPackageSetting;
|
||||
|
||||
private PackageManagerService mPm;
|
||||
private ArchiveManager mArchiveManager;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mMockSystem.system().stageNominalSystemState();
|
||||
when(mMockSystem.mocks().getInjector().getPackageInstallerService()).thenReturn(
|
||||
mInstallerService);
|
||||
mPm = spy(new PackageManagerService(mMockSystem.mocks().getInjector(),
|
||||
/* factoryTest= */false,
|
||||
MockSystem.Companion.getDEFAULT_VERSION_INFO().fingerprint,
|
||||
/* isEngBuild= */ false,
|
||||
/* isUserDebugBuild= */false,
|
||||
Build.VERSION_CODES.CUR_DEVELOPMENT,
|
||||
Build.VERSION.INCREMENTAL));
|
||||
|
||||
when(mComputer.getPackageStateFiltered(eq(PACKAGE), anyInt(), anyInt())).thenReturn(
|
||||
mPackageState);
|
||||
when(mPackageState.getPackageName()).thenReturn(PACKAGE);
|
||||
when(mPackageState.getInstallSource()).thenReturn(mInstallSource);
|
||||
mPackageSetting = createBasicPackageSetting();
|
||||
when(mMockSystem.mocks().getSettings().getPackageLPr(eq(PACKAGE))).thenReturn(
|
||||
mPackageSetting);
|
||||
when(mContext.getSystemService(LauncherApps.class)).thenReturn(mLauncherApps);
|
||||
when(mLauncherApps.getActivityList(eq(PACKAGE), eq(UserHandle.CURRENT))).thenReturn(
|
||||
mLauncherActivityInfos);
|
||||
doReturn(mComputer).when(mPm).snapshotComputer();
|
||||
when(mComputer.getNameForUid(eq(Binder.getCallingUid()))).thenReturn(CALLER_PACKAGE);
|
||||
mArchiveManager = new ArchiveManager(mContext, mPm);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void archiveApp_callerPackageNameIncorrect() {
|
||||
Exception e = assertThrows(
|
||||
SecurityException.class,
|
||||
() -> mArchiveManager.archiveApp(PACKAGE, "different", UserHandle.CURRENT,
|
||||
mIntentSender)
|
||||
);
|
||||
assertThat(e).hasMessageThat().isEqualTo(
|
||||
String.format(
|
||||
"The callerPackageName %s set by the caller doesn't match the "
|
||||
+ "caller's own package name %s.",
|
||||
"different",
|
||||
CALLER_PACKAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void archiveApp_packageNotInstalled() {
|
||||
when(mMockSystem.mocks().getSettings().getPackageLPr(eq(PACKAGE))).thenReturn(
|
||||
null);
|
||||
|
||||
Exception e = assertThrows(
|
||||
PackageManager.NameNotFoundException.class,
|
||||
() -> mArchiveManager.archiveApp(PACKAGE, CALLER_PACKAGE, UserHandle.CURRENT,
|
||||
mIntentSender)
|
||||
);
|
||||
assertThat(e).hasMessageThat().isEqualTo(String.format("Package %s not found.", PACKAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void archiveApp_packageNotInstalledForUser() {
|
||||
mPackageSetting.modifyUserState(UserHandle.CURRENT.getIdentifier()).setInstalled(false);
|
||||
|
||||
Exception e = assertThrows(
|
||||
PackageManager.NameNotFoundException.class,
|
||||
() -> mArchiveManager.archiveApp(PACKAGE, CALLER_PACKAGE, UserHandle.CURRENT,
|
||||
mIntentSender)
|
||||
);
|
||||
assertThat(e).hasMessageThat().isEqualTo(String.format("Package %s not found.", PACKAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void archiveApp_callerNotInstallerOfRecord() {
|
||||
InstallSource otherInstallSource =
|
||||
InstallSource.create(
|
||||
CALLER_PACKAGE,
|
||||
CALLER_PACKAGE,
|
||||
/* installerPackageName= */ "different",
|
||||
Binder.getCallingUid(),
|
||||
CALLER_PACKAGE,
|
||||
/* installerAttributionTag= */ null,
|
||||
/* packageSource= */ 0);
|
||||
when(mPackageState.getInstallSource()).thenReturn(otherInstallSource);
|
||||
|
||||
Exception e = assertThrows(
|
||||
SecurityException.class,
|
||||
() -> mArchiveManager.archiveApp(PACKAGE, CALLER_PACKAGE, Process.myUserHandle(),
|
||||
mIntentSender)
|
||||
);
|
||||
assertThat(e).hasMessageThat().isEqualTo(
|
||||
String.format("Caller is not the installer of record for %s.", PACKAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void archiveApp_callerNotUpdateOwner() {
|
||||
InstallSource otherInstallSource =
|
||||
InstallSource.create(
|
||||
CALLER_PACKAGE,
|
||||
CALLER_PACKAGE,
|
||||
CALLER_PACKAGE,
|
||||
Binder.getCallingUid(),
|
||||
/* updateOwnerPackageName= */ "different",
|
||||
/* installerAttributionTag= */ null,
|
||||
/* packageSource= */ 0);
|
||||
when(mPackageState.getInstallSource()).thenReturn(otherInstallSource);
|
||||
|
||||
Exception e = assertThrows(
|
||||
SecurityException.class,
|
||||
() -> mArchiveManager.archiveApp(PACKAGE, CALLER_PACKAGE, UserHandle.CURRENT,
|
||||
mIntentSender)
|
||||
);
|
||||
assertThat(e).hasMessageThat().isEqualTo(
|
||||
String.format("Caller is not the update owner for %s.", PACKAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void archiveApp_success() throws PackageManager.NameNotFoundException {
|
||||
List<ArchiveState.ArchiveActivityInfo> activityInfos = new ArrayList<>();
|
||||
for (LauncherActivityInfo mainActivity : createLauncherActivities()) {
|
||||
// TODO(b/278553670) Extract and store launcher icons
|
||||
ArchiveState.ArchiveActivityInfo activityInfo = new ArchiveState.ArchiveActivityInfo(
|
||||
mainActivity.getLabel().toString(),
|
||||
Path.of("/TODO"), null);
|
||||
activityInfos.add(activityInfo);
|
||||
}
|
||||
|
||||
mArchiveManager.archiveApp(PACKAGE, CALLER_PACKAGE, UserHandle.CURRENT, mIntentSender);
|
||||
verify(mInstallerService).uninstall(
|
||||
eq(new VersionedPackage(PACKAGE, PackageManager.VERSION_CODE_HIGHEST)),
|
||||
eq(CALLER_PACKAGE), eq(DELETE_KEEP_DATA), eq(mIntentSender),
|
||||
eq(UserHandle.CURRENT.getIdentifier()));
|
||||
assertThat(mPackageSetting.readUserState(
|
||||
UserHandle.CURRENT.getIdentifier()).getArchiveState()).isEqualTo(
|
||||
new ArchiveState(activityInfos, CALLER_PACKAGE));
|
||||
}
|
||||
|
||||
private static List<LauncherActivityInfo> createLauncherActivities() {
|
||||
LauncherActivityInfo activity1 = mock(LauncherActivityInfo.class);
|
||||
when(activity1.getLabel()).thenReturn("activity1");
|
||||
LauncherActivityInfo activity2 = mock(LauncherActivityInfo.class);
|
||||
when(activity2.getLabel()).thenReturn("activity2");
|
||||
return List.of(activity1, activity2);
|
||||
}
|
||||
|
||||
private PackageSetting createBasicPackageSetting() {
|
||||
return new PackageSettingBuilder()
|
||||
.setName(PACKAGE).setCodePath("/data/app/" + PACKAGE + "-randompath")
|
||||
.setInstallState(UserHandle.CURRENT.getIdentifier(), /* installed= */ true)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Binder;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.server.pm.pkg.PackageStateInternal;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ArchiveManagerTest {
|
||||
|
||||
private static final String PACKAGE = "com.example";
|
||||
private static final String CALLER_PACKAGE = "com.vending";
|
||||
private static final int USER_ID = 1;
|
||||
|
||||
@Mock private IntentSender mIntentSender;
|
||||
@Mock private PackageManagerService mPm;
|
||||
@Mock private Computer mComputer;
|
||||
@Mock private PackageStateInternal mPackageState;
|
||||
private InstallSource mInstallSource =
|
||||
InstallSource.create(
|
||||
CALLER_PACKAGE,
|
||||
CALLER_PACKAGE,
|
||||
CALLER_PACKAGE,
|
||||
Binder.getCallingUid(),
|
||||
CALLER_PACKAGE,
|
||||
/* installerAttributionTag= */ null,
|
||||
/* packageSource= */ 0);
|
||||
|
||||
private ArchiveManager mArchiveManager;
|
||||
private int mCallingUid;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mArchiveManager = new ArchiveManager(mPm);
|
||||
mCallingUid = Binder.getCallingUid();
|
||||
when(mPm.snapshotComputer()).thenReturn(mComputer);
|
||||
when(mComputer.getNameForUid(eq(mCallingUid))).thenReturn(CALLER_PACKAGE);
|
||||
when(mComputer.getPackageStateInternal(eq(PACKAGE))).thenReturn(mPackageState);
|
||||
when(mPackageState.getInstallSource()).thenReturn(mInstallSource);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void archiveApp_callerPackageNameIncorrect() {
|
||||
Exception e = assertThrows(
|
||||
SecurityException.class,
|
||||
() -> mArchiveManager.archiveApp(PACKAGE, "different", USER_ID, mIntentSender)
|
||||
);
|
||||
assertThat(e).hasMessageThat().isEqualTo(
|
||||
String.format(
|
||||
"The callerPackageName %s set by the caller doesn't match the "
|
||||
+ "caller's own package name %s.",
|
||||
"different",
|
||||
CALLER_PACKAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void archiveApp_packageNotInstalled() {
|
||||
when(mComputer.getPackageStateInternal(eq(PACKAGE))).thenReturn(null);
|
||||
|
||||
Exception e = assertThrows(
|
||||
PackageManager.NameNotFoundException.class,
|
||||
() -> mArchiveManager.archiveApp(PACKAGE, CALLER_PACKAGE, USER_ID, mIntentSender)
|
||||
);
|
||||
assertThat(e).hasMessageThat().isEqualTo(String.format("Package %s not found.", PACKAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void archiveApp_callerNotInstallerOfRecord() {
|
||||
InstallSource otherInstallSource =
|
||||
InstallSource.create(
|
||||
CALLER_PACKAGE,
|
||||
CALLER_PACKAGE,
|
||||
/* installerPackageName= */ "different",
|
||||
Binder.getCallingUid(),
|
||||
CALLER_PACKAGE,
|
||||
/* installerAttributionTag= */ null,
|
||||
/* packageSource= */ 0);
|
||||
when(mPackageState.getInstallSource()).thenReturn(otherInstallSource);
|
||||
|
||||
Exception e = assertThrows(
|
||||
SecurityException.class,
|
||||
() -> mArchiveManager.archiveApp(PACKAGE, CALLER_PACKAGE, USER_ID, mIntentSender)
|
||||
);
|
||||
assertThat(e).hasMessageThat().isEqualTo(
|
||||
String.format("Caller is not the installer of record for %s.", PACKAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void archiveApp_callerNotUpdateOwner() {
|
||||
InstallSource otherInstallSource =
|
||||
InstallSource.create(
|
||||
CALLER_PACKAGE,
|
||||
CALLER_PACKAGE,
|
||||
CALLER_PACKAGE,
|
||||
Binder.getCallingUid(),
|
||||
/* updateOwnerPackageName= */ "different",
|
||||
/* installerAttributionTag= */ null,
|
||||
/* packageSource= */ 0);
|
||||
when(mPackageState.getInstallSource()).thenReturn(otherInstallSource);
|
||||
|
||||
Exception e = assertThrows(
|
||||
SecurityException.class,
|
||||
() -> mArchiveManager.archiveApp(PACKAGE, CALLER_PACKAGE, USER_ID, mIntentSender)
|
||||
);
|
||||
assertThat(e).hasMessageThat().isEqualTo(
|
||||
String.format("Caller is not the update owner for %s.", PACKAGE));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user