Merge changes from topic "compos-cherry-pick" into stage-aosp-master am: 9ade5e2ffb am: 631842eb58 am: 9dc21480ac
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15638982 Change-Id: I6b526d79ea5dc1c365be72b7dbf13fe4d7e27bcd
This commit is contained in:
committed by
Automerger Merge Worker
commit
332347aa1c
@@ -260,6 +260,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
|||||||
new Lifecycle(context, this));
|
new Lifecycle(context, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StagingManager getStagingManager() {
|
||||||
|
return mStagingManager;
|
||||||
|
}
|
||||||
|
|
||||||
boolean okToSendBroadcasts() {
|
boolean okToSendBroadcasts() {
|
||||||
return mOkToSendBroadcasts;
|
return mOkToSendBroadcasts;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,6 +186,7 @@ import android.content.pm.IPackageManager;
|
|||||||
import android.content.pm.IPackageManagerNative;
|
import android.content.pm.IPackageManagerNative;
|
||||||
import android.content.pm.IPackageMoveObserver;
|
import android.content.pm.IPackageMoveObserver;
|
||||||
import android.content.pm.IPackageStatsObserver;
|
import android.content.pm.IPackageStatsObserver;
|
||||||
|
import android.content.pm.IStagedApexObserver;
|
||||||
import android.content.pm.IncrementalStatesInfo;
|
import android.content.pm.IncrementalStatesInfo;
|
||||||
import android.content.pm.InstallSourceInfo;
|
import android.content.pm.InstallSourceInfo;
|
||||||
import android.content.pm.InstantAppInfo;
|
import android.content.pm.InstantAppInfo;
|
||||||
@@ -227,6 +228,7 @@ import android.content.pm.ServiceInfo;
|
|||||||
import android.content.pm.SharedLibraryInfo;
|
import android.content.pm.SharedLibraryInfo;
|
||||||
import android.content.pm.Signature;
|
import android.content.pm.Signature;
|
||||||
import android.content.pm.SigningInfo;
|
import android.content.pm.SigningInfo;
|
||||||
|
import android.content.pm.StagedApexInfo;
|
||||||
import android.content.pm.SuspendDialogInfo;
|
import android.content.pm.SuspendDialogInfo;
|
||||||
import android.content.pm.TestUtilityService;
|
import android.content.pm.TestUtilityService;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
@@ -27003,6 +27005,29 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
public boolean hasSystemFeature(String featureName, int version) {
|
public boolean hasSystemFeature(String featureName, int version) {
|
||||||
return PackageManagerService.this.hasSystemFeature(featureName, version);
|
return PackageManagerService.this.hasSystemFeature(featureName, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerStagedApexObserver(IStagedApexObserver observer) {
|
||||||
|
mInstallerService.getStagingManager().registerStagedApexObserver(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterStagedApexObserver(IStagedApexObserver observer) {
|
||||||
|
mInstallerService.getStagingManager().unregisterStagedApexObserver(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getStagedApexModuleNames() {
|
||||||
|
return mInstallerService.getStagingManager()
|
||||||
|
.getStagedApexModuleNames().toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public StagedApexInfo getStagedApexInfo(String moduleName) {
|
||||||
|
return mInstallerService.getStagingManager().getStagedApexInfo(moduleName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AndroidPackage getPackage(String packageName) {
|
private AndroidPackage getPackage(String packageName) {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import android.content.pm.PackageManagerInternal;
|
|||||||
import android.content.pm.PackageParser.PackageParserException;
|
import android.content.pm.PackageParser.PackageParserException;
|
||||||
import android.content.pm.PackageParser.SigningDetails;
|
import android.content.pm.PackageParser.SigningDetails;
|
||||||
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
|
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
|
||||||
|
import android.content.pm.StagedApexInfo;
|
||||||
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
|
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
|
||||||
import android.content.rollback.RollbackInfo;
|
import android.content.rollback.RollbackInfo;
|
||||||
import android.content.rollback.RollbackManager;
|
import android.content.rollback.RollbackManager;
|
||||||
@@ -209,6 +210,23 @@ public class StagingManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void registerStagedApexObserver(IStagedApexObserver observer) {
|
void registerStagedApexObserver(IStagedApexObserver observer) {
|
||||||
|
if (observer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (observer.asBinder() != null) {
|
||||||
|
try {
|
||||||
|
observer.asBinder().linkToDeath(new IBinder.DeathRecipient() {
|
||||||
|
@Override
|
||||||
|
public void binderDied() {
|
||||||
|
synchronized (mStagedApexObservers) {
|
||||||
|
mStagedApexObservers.remove(observer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
} catch (RemoteException re) {
|
||||||
|
Slog.w(TAG, re.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (mStagedApexObservers) {
|
synchronized (mStagedApexObservers) {
|
||||||
mStagedApexObservers.add(observer);
|
mStagedApexObservers.add(observer);
|
||||||
}
|
}
|
||||||
@@ -1222,7 +1240,7 @@ public class StagingManager {
|
|||||||
* Returns ApexInfo of the {@code moduleInfo} provided if it is staged, otherwise returns null.
|
* Returns ApexInfo of the {@code moduleInfo} provided if it is staged, otherwise returns null.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
ApexInfo getStagedApexInfo(String moduleName) {
|
StagedApexInfo getStagedApexInfo(String moduleName) {
|
||||||
synchronized (mStagedSessions) {
|
synchronized (mStagedSessions) {
|
||||||
for (int i = 0; i < mStagedSessions.size(); i++) {
|
for (int i = 0; i < mStagedSessions.size(); i++) {
|
||||||
final StagedSession session = mStagedSessions.valueAt(i);
|
final StagedSession session = mStagedSessions.valueAt(i);
|
||||||
@@ -1230,9 +1248,14 @@ public class StagingManager {
|
|||||||
|| session.hasParentSessionId() || !session.containsApexSession()) {
|
|| session.hasParentSessionId() || !session.containsApexSession()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ApexInfo result = getStagedApexInfos(session).get(moduleName);
|
ApexInfo ai = getStagedApexInfos(session).get(moduleName);
|
||||||
if (result != null) {
|
if (ai != null) {
|
||||||
return result;
|
StagedApexInfo info = new StagedApexInfo();
|
||||||
|
info.moduleName = ai.moduleName;
|
||||||
|
info.diskImagePath = ai.modulePath;
|
||||||
|
info.versionCode = ai.versionCode;
|
||||||
|
info.versionName = ai.versionName;
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import android.content.pm.IStagedApexObserver;
|
|||||||
import android.content.pm.PackageInstaller;
|
import android.content.pm.PackageInstaller;
|
||||||
import android.content.pm.PackageInstaller.SessionInfo;
|
import android.content.pm.PackageInstaller.SessionInfo;
|
||||||
import android.content.pm.PackageInstaller.SessionInfo.StagedSessionErrorCode;
|
import android.content.pm.PackageInstaller.SessionInfo.StagedSessionErrorCode;
|
||||||
|
import android.content.pm.StagedApexInfo;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.os.storage.IStorageManager;
|
import android.os.storage.IStorageManager;
|
||||||
@@ -693,12 +694,15 @@ public class StagingManagerTest {
|
|||||||
when(mApexManager.getStagedApexInfos(any())).thenReturn(fakeApexInfos);
|
when(mApexManager.getStagedApexInfos(any())).thenReturn(fakeApexInfos);
|
||||||
|
|
||||||
// Verify null is returned if module name is not found
|
// Verify null is returned if module name is not found
|
||||||
ApexInfo result = mStagingManager.getStagedApexInfo("not found");
|
StagedApexInfo result = mStagingManager.getStagedApexInfo("not found");
|
||||||
assertThat(result).isNull();
|
assertThat(result).isNull();
|
||||||
verify(mApexManager, times(1)).getStagedApexInfos(any());
|
verify(mApexManager, times(1)).getStagedApexInfos(any());
|
||||||
// Otherwise, the correct object is returned
|
// Otherwise, the correct object is returned
|
||||||
result = mStagingManager.getStagedApexInfo("module1");
|
result = mStagingManager.getStagedApexInfo("module1");
|
||||||
assertThat(result).isEqualTo(fakeApexInfos[0]);
|
assertThat(result.moduleName).isEqualTo(fakeApexInfos[0].moduleName);
|
||||||
|
assertThat(result.diskImagePath).isEqualTo(fakeApexInfos[0].modulePath);
|
||||||
|
assertThat(result.versionCode).isEqualTo(fakeApexInfos[0].versionCode);
|
||||||
|
assertThat(result.versionName).isEqualTo(fakeApexInfos[0].versionName);
|
||||||
verify(mApexManager, times(2)).getStagedApexInfos(any());
|
verify(mApexManager, times(2)).getStagedApexInfos(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ android_test_helper_app {
|
|||||||
":test.rebootless_apex_v1",
|
":test.rebootless_apex_v1",
|
||||||
":test.rebootless_apex_v2",
|
":test.rebootless_apex_v2",
|
||||||
],
|
],
|
||||||
|
platform_apis: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
java_test_host {
|
java_test_host {
|
||||||
|
|||||||
@@ -17,16 +17,27 @@
|
|||||||
package com.android.tests.stagedinstallinternal;
|
package com.android.tests.stagedinstallinternal;
|
||||||
|
|
||||||
import static com.android.cts.install.lib.InstallUtils.getPackageInstaller;
|
import static com.android.cts.install.lib.InstallUtils.getPackageInstaller;
|
||||||
|
import static com.android.cts.install.lib.InstallUtils.waitForSessionReady;
|
||||||
import static com.android.cts.shim.lib.ShimPackage.SHIM_APEX_PACKAGE_NAME;
|
import static com.android.cts.shim.lib.ShimPackage.SHIM_APEX_PACKAGE_NAME;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static com.google.common.truth.Truth.assertWithMessage;
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.timeout;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.content.pm.ApexStagedEvent;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.IPackageManagerNative;
|
||||||
|
import android.content.pm.IStagedApexObserver;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageInstaller;
|
import android.content.pm.PackageInstaller;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.StagedApexInfo;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry;
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
|
||||||
@@ -39,6 +50,8 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.JUnit4;
|
import org.junit.runners.JUnit4;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
@@ -401,9 +414,73 @@ public class StagedInstallInternalTest {
|
|||||||
AssertionError.class,
|
AssertionError.class,
|
||||||
"Staged session " + sessionId + " already contains " + SHIM_APEX_PACKAGE_NAME,
|
"Staged session " + sessionId + " already contains " + SHIM_APEX_PACKAGE_NAME,
|
||||||
Install.single(APEX_V2));
|
Install.single(APEX_V2));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetStagedModuleNames() throws Exception {
|
||||||
|
// Before staging a session
|
||||||
|
String[] result = getPackageManagerNative().getStagedApexModuleNames();
|
||||||
|
assertThat(result).hasLength(0);
|
||||||
|
// Stage an apex
|
||||||
|
int sessionId = Install.single(APEX_V2).setStaged().commit();
|
||||||
|
waitForSessionReady(sessionId);
|
||||||
|
result = getPackageManagerNative().getStagedApexModuleNames();
|
||||||
|
assertThat(result).hasLength(1);
|
||||||
|
assertThat(result).isEqualTo(new String[]{SHIM_APEX_PACKAGE_NAME});
|
||||||
|
// Abandon the session
|
||||||
|
InstallUtils.openPackageInstallerSession(sessionId).abandon();
|
||||||
|
result = getPackageManagerNative().getStagedApexModuleNames();
|
||||||
|
assertThat(result).hasLength(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetStagedApexInfo() throws Exception {
|
||||||
|
// Ask for non-existing module
|
||||||
|
StagedApexInfo result = getPackageManagerNative().getStagedApexInfo("not found");
|
||||||
|
assertThat(result).isNull();
|
||||||
|
// Stage an apex
|
||||||
|
int sessionId = Install.single(APEX_V2).setStaged().commit();
|
||||||
|
waitForSessionReady(sessionId);
|
||||||
|
// Query proper module name
|
||||||
|
result = getPackageManagerNative().getStagedApexInfo(SHIM_APEX_PACKAGE_NAME);
|
||||||
|
assertThat(result.moduleName).isEqualTo(SHIM_APEX_PACKAGE_NAME);
|
||||||
|
InstallUtils.openPackageInstallerSession(sessionId).abandon();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MockStagedApexObserver extends IStagedApexObserver.Stub {
|
||||||
|
@Override
|
||||||
|
public void onApexStaged(ApexStagedEvent event) {
|
||||||
|
assertThat(event).isNotNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStagedApexObserver() throws Exception {
|
||||||
|
MockStagedApexObserver realObserver = new MockStagedApexObserver();
|
||||||
|
IStagedApexObserver observer = spy(realObserver);
|
||||||
|
assertThat(observer).isNotNull();
|
||||||
|
getPackageManagerNative().registerStagedApexObserver(observer);
|
||||||
|
|
||||||
|
// Stage an apex and verify observer was called
|
||||||
|
int sessionId = Install.single(APEX_V2).setStaged().commit();
|
||||||
|
waitForSessionReady(sessionId);
|
||||||
|
ArgumentCaptor<ApexStagedEvent> captor = ArgumentCaptor.forClass(ApexStagedEvent.class);
|
||||||
|
verify(observer, timeout(5000)).onApexStaged(captor.capture());
|
||||||
|
assertThat(captor.getValue().stagedApexModuleNames).isEqualTo(
|
||||||
|
new String[] {SHIM_APEX_PACKAGE_NAME});
|
||||||
|
|
||||||
|
// Abandon and verify observer is called
|
||||||
|
Mockito.clearInvocations(observer);
|
||||||
|
InstallUtils.openPackageInstallerSession(sessionId).abandon();
|
||||||
|
verify(observer, timeout(5000)).onApexStaged(captor.capture());
|
||||||
|
assertThat(captor.getValue().stagedApexModuleNames).hasLength(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IPackageManagerNative getPackageManagerNative() {
|
||||||
|
IBinder binder = ServiceManager.waitForService("package_native");
|
||||||
|
assertThat(binder).isNotNull();
|
||||||
|
return IPackageManagerNative.Stub.asInterface(binder);
|
||||||
|
}
|
||||||
private static void assertSessionApplied(int sessionId) {
|
private static void assertSessionApplied(int sessionId) {
|
||||||
assertSessionState(sessionId, (session) -> {
|
assertSessionState(sessionId, (session) -> {
|
||||||
assertThat(session.isStagedSessionApplied()).isTrue();
|
assertThat(session.isStagedSessionApplied()).isTrue();
|
||||||
|
|||||||
@@ -478,6 +478,21 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
|
|||||||
runPhase("testRebootlessUpdate_hasStagedSessionWithSameApex_fails");
|
runPhase("testRebootlessUpdate_hasStagedSessionWithSameApex_fails");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetStagedModuleNames() throws Exception {
|
||||||
|
runPhase("testGetStagedModuleNames");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetStagedApexInfo() throws Exception {
|
||||||
|
runPhase("testGetStagedApexInfo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStagedApexObserver() throws Exception {
|
||||||
|
runPhase("testStagedApexObserver");
|
||||||
|
}
|
||||||
|
|
||||||
private List<String> getStagingDirectories() throws DeviceNotAvailableException {
|
private List<String> getStagingDirectories() throws DeviceNotAvailableException {
|
||||||
String baseDir = "/data/app-staging";
|
String baseDir = "/data/app-staging";
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user