summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/pm/ArchivedActivityParcel.aidl3
-rw-r--r--core/proto/android/service/package.proto3
-rw-r--r--services/core/java/com/android/server/pm/PackageArchiver.java18
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java3
-rw-r--r--services/core/java/com/android/server/pm/Settings.java27
-rw-r--r--services/core/java/com/android/server/pm/pkg/ArchiveState.java32
-rw-r--r--services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java21
-rw-r--r--services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageUserStateTest.java16
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java4
9 files changed, 101 insertions, 26 deletions
diff --git a/core/java/android/content/pm/ArchivedActivityParcel.aidl b/core/java/android/content/pm/ArchivedActivityParcel.aidl
index 7ab7ed1cc5df..74953fff40d8 100644
--- a/core/java/android/content/pm/ArchivedActivityParcel.aidl
+++ b/core/java/android/content/pm/ArchivedActivityParcel.aidl
@@ -16,9 +16,12 @@
package android.content.pm;
+import android.content.ComponentName;
+
/** @hide */
parcelable ArchivedActivityParcel {
String title;
+ ComponentName originalComponentName;
// PNG compressed bitmaps.
byte[] iconBitmap;
byte[] monochromeIconBitmap;
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
index eb14db070f9f..068f4dd07ccb 100644
--- a/core/proto/android/service/package.proto
+++ b/core/proto/android/service/package.proto
@@ -115,6 +115,9 @@ message PackageProto {
// Only set if the app defined a monochrome icon.
optional string monochrome_icon_bitmap_path = 3;
+
+ // The component name of the original activity (pre-archival).
+ optional string original_component_name = 4;
}
/** Information about main activities. */
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index f59188e9fd93..0fb1f7a0780c 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -196,8 +196,12 @@ public class PackageArchiver {
for (int i = 0, size = mainActivities.length; i < size; ++i) {
var mainActivity = mainActivities[i];
Path iconPath = storeIconForParcel(packageName, mainActivity, userId, i);
- ArchiveActivityInfo activityInfo = new ArchiveActivityInfo(
- mainActivity.title, iconPath, null);
+ ArchiveActivityInfo activityInfo =
+ new ArchiveActivityInfo(
+ mainActivity.title,
+ mainActivity.originalComponentName,
+ iconPath,
+ null);
archiveActivityInfos.add(activityInfo);
}
@@ -215,8 +219,12 @@ public class PackageArchiver {
for (int i = 0, size = mainActivities.size(); i < size; i++) {
LauncherActivityInfo mainActivity = mainActivities.get(i);
Path iconPath = storeIcon(packageName, mainActivity, userId, i);
- ArchiveActivityInfo activityInfo = new ArchiveActivityInfo(
- mainActivity.getLabel().toString(), iconPath, null);
+ ArchiveActivityInfo activityInfo =
+ new ArchiveActivityInfo(
+ mainActivity.getLabel().toString(),
+ mainActivity.getComponentName(),
+ iconPath,
+ null);
archiveActivityInfos.add(activityInfo);
}
@@ -593,6 +601,7 @@ public class PackageArchiver {
}
var archivedActivity = new ArchivedActivityParcel();
archivedActivity.title = info.getTitle();
+ archivedActivity.originalComponentName = info.getOriginalComponentName();
archivedActivity.iconBitmap = bytesFromBitmapFile(info.getIconBitmap());
archivedActivity.monochromeIconBitmap = bytesFromBitmapFile(
info.getMonochromeIconBitmap());
@@ -624,6 +633,7 @@ public class PackageArchiver {
}
var archivedActivity = new ArchivedActivityParcel();
archivedActivity.title = info.getLabel().toString();
+ archivedActivity.originalComponentName = info.getComponentName();
archivedActivity.iconBitmap =
info.getActivityInfo().getIconResource() == 0 ? null : bytesFromBitmap(
drawableToBitmap(info.getIcon(/* density= */ 0)));
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 2e6006465bd9..215a31910da5 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -1201,6 +1201,9 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
long activityInfoToken = proto.start(
PackageProto.UserInfoProto.ArchiveState.ACTIVITY_INFOS);
proto.write(ArchiveActivityInfo.TITLE, activityInfo.getTitle());
+ proto.write(
+ ArchiveActivityInfo.ORIGINAL_COMPONENT_NAME,
+ activityInfo.getOriginalComponentName().flattenToString());
if (activityInfo.getIconBitmap() != null) {
proto.write(ArchiveActivityInfo.ICON_BITMAP_PATH,
activityInfo.getIconBitmap().toAbsolutePath().toString());
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6e3b538c4849..64411d3738f8 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -368,6 +368,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
private static final String ATTR_VALUE = "value";
private static final String ATTR_FIRST_INSTALL_TIME = "first-install-time";
private static final String ATTR_ARCHIVE_ACTIVITY_TITLE = "activity-title";
+ private static final String ATTR_ARCHIVE_ORIGINAL_COMPONENT_NAME = "original-component-name";
private static final String ATTR_ARCHIVE_INSTALLER_TITLE = "installer-title";
private static final String ATTR_ARCHIVE_ICON_PATH = "icon-path";
private static final String ATTR_ARCHIVE_MONOCHROME_ICON_PATH = "monochrome-icon-path";
@@ -2068,6 +2069,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
if (tagName.equals(TAG_ARCHIVE_ACTIVITY_INFO)) {
String title = parser.getAttributeValue(null,
ATTR_ARCHIVE_ACTIVITY_TITLE);
+ String originalComponentName =
+ parser.getAttributeValue(null, ATTR_ARCHIVE_ORIGINAL_COMPONENT_NAME);
String iconAttribute = parser.getAttributeValue(null,
ATTR_ARCHIVE_ICON_PATH);
Path iconPath = iconAttribute == null ? null : Path.of(iconAttribute);
@@ -2076,17 +2079,27 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
Path monochromeIconPath = monochromeAttribute == null ? null : Path.of(
monochromeAttribute);
- if (title == null || iconPath == null) {
- Slog.wtf(TAG,
- TextUtils.formatSimple("Missing attributes in tag %s. %s: %s, %s: %s",
- TAG_ARCHIVE_ACTIVITY_INFO, ATTR_ARCHIVE_ACTIVITY_TITLE, title,
+ if (title == null || originalComponentName == null || iconPath == null) {
+ Slog.wtf(
+ TAG,
+ TextUtils.formatSimple(
+ "Missing attributes in tag %s. %s: %s, %s: %s, %s: %s",
+ TAG_ARCHIVE_ACTIVITY_INFO,
+ ATTR_ARCHIVE_ACTIVITY_TITLE,
+ title,
+ ATTR_ARCHIVE_ORIGINAL_COMPONENT_NAME,
+ originalComponentName,
ATTR_ARCHIVE_ICON_PATH,
iconPath));
continue;
}
activityInfos.add(
- new ArchiveState.ArchiveActivityInfo(title, iconPath, monochromeIconPath));
+ new ArchiveState.ArchiveActivityInfo(
+ title,
+ ComponentName.unflattenFromString(originalComponentName),
+ iconPath,
+ monochromeIconPath));
}
}
return activityInfos;
@@ -2458,6 +2471,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
for (ArchiveState.ArchiveActivityInfo activityInfo : archiveState.getActivityInfos()) {
serializer.startTag(null, TAG_ARCHIVE_ACTIVITY_INFO);
serializer.attribute(null, ATTR_ARCHIVE_ACTIVITY_TITLE, activityInfo.getTitle());
+ serializer.attribute(
+ null,
+ ATTR_ARCHIVE_ORIGINAL_COMPONENT_NAME,
+ activityInfo.getOriginalComponentName().flattenToString());
if (activityInfo.getIconBitmap() != null) {
serializer.attribute(null, ATTR_ARCHIVE_ICON_PATH,
activityInfo.getIconBitmap().toAbsolutePath().toString());
diff --git a/services/core/java/com/android/server/pm/pkg/ArchiveState.java b/services/core/java/com/android/server/pm/pkg/ArchiveState.java
index 4916a4a6d72a..1e40d44bd4ca 100644
--- a/services/core/java/com/android/server/pm/pkg/ArchiveState.java
+++ b/services/core/java/com/android/server/pm/pkg/ArchiveState.java
@@ -16,9 +16,11 @@
package com.android.server.pm.pkg;
+import android.content.ComponentName;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import com.android.internal.util.AnnotationValidations;
import com.android.internal.util.DataClass;
import java.nio.file.Path;
@@ -56,6 +58,10 @@ public class ArchiveState {
@NonNull
private final String mTitle;
+ /** The component name of the original activity (pre-archival). */
+ @NonNull
+ private final ComponentName mOriginalComponentName;
+
/**
* The path to the stored icon of the activity in the app's locale. Null if the app does
* not define any icon (default icon would be shown on the launcher).
@@ -96,11 +102,13 @@ public class ArchiveState {
@DataClass.Generated.Member
public ArchiveActivityInfo(
@NonNull String title,
+ @NonNull ComponentName originalComponentName,
@Nullable Path iconBitmap,
@Nullable Path monochromeIconBitmap) {
this.mTitle = title;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mTitle);
+ this.mOriginalComponentName = originalComponentName;
+ AnnotationValidations.validate(NonNull.class, null, mTitle);
+ AnnotationValidations.validate(NonNull.class, null, mOriginalComponentName);
this.mIconBitmap = iconBitmap;
this.mMonochromeIconBitmap = monochromeIconBitmap;
@@ -116,6 +124,14 @@ public class ArchiveState {
}
/**
+ * The component name of the original activity (pre-archival).
+ */
+ @DataClass.Generated.Member
+ public @NonNull ComponentName getOriginalComponentName() {
+ return mOriginalComponentName;
+ }
+
+ /**
* The path to the stored icon of the activity in the app's locale. Null if the app does
* not define any icon (default icon would be shown on the launcher).
*/
@@ -140,6 +156,7 @@ public class ArchiveState {
return "ArchiveActivityInfo { " +
"title = " + mTitle + ", " +
+ "originalComponentName = " + mOriginalComponentName + ", " +
"iconBitmap = " + mIconBitmap + ", " +
"monochromeIconBitmap = " + mMonochromeIconBitmap +
" }";
@@ -159,6 +176,7 @@ public class ArchiveState {
//noinspection PointlessBooleanExpression
return true
&& java.util.Objects.equals(mTitle, that.mTitle)
+ && java.util.Objects.equals(mOriginalComponentName, that.mOriginalComponentName)
&& java.util.Objects.equals(mIconBitmap, that.mIconBitmap)
&& java.util.Objects.equals(mMonochromeIconBitmap, that.mMonochromeIconBitmap);
}
@@ -171,6 +189,7 @@ public class ArchiveState {
int _hash = 1;
_hash = 31 * _hash + java.util.Objects.hashCode(mTitle);
+ _hash = 31* _hash + java.util.Objects.hashCode(mOriginalComponentName);
_hash = 31 * _hash + java.util.Objects.hashCode(mIconBitmap);
_hash = 31 * _hash + java.util.Objects.hashCode(mMonochromeIconBitmap);
return _hash;
@@ -180,7 +199,8 @@ public class ArchiveState {
time = 1693590309015L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/ArchiveState.java",
- inputSignatures = "private final @android.annotation.NonNull java.lang.String mTitle\nprivate final @android.annotation.Nullable java.nio.file.Path mIconBitmap\nprivate final @android.annotation.Nullable java.nio.file.Path mMonochromeIconBitmap\nclass ArchiveActivityInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)")
+ inputSignatures =
+ "private final @android.annotation.NonNull java.lang.String mTitle\nprivate final @android.annotation.NonNull android.content.ComponentName mOriginalComponentName\nprivate final @android.annotation.Nullable java.nio.file.Path mIconBitmap\nprivate final @android.annotation.Nullable java.nio.file.Path mMonochromeIconBitmap\nclass ArchiveActivityInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)")
@Deprecated
private void __metadata() {}
@@ -224,11 +244,9 @@ public class ArchiveState {
@NonNull List<ArchiveActivityInfo> activityInfos,
@NonNull String installerTitle) {
this.mActivityInfos = activityInfos;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mActivityInfos);
+ AnnotationValidations.validate(NonNull.class, null, mActivityInfos);
this.mInstallerTitle = installerTitle;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mInstallerTitle);
+ AnnotationValidations.validate(NonNull.class, null, mInstallerTitle);
// onConstructed(); // You can define this method to get a callback
}
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
index 2889c749f679..326218ce997c 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -41,6 +41,7 @@ import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.app.PropertyInvalidatedCache;
+import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.SuspendDialogInfo;
@@ -871,12 +872,20 @@ public class PackageManagerSettingsTests {
.setUid(packageSetting.getAppId())
.hideAsFinal());
- ArchiveState archiveState = new ArchiveState(
- List.of(new ArchiveState.ArchiveActivityInfo("title1", Path.of("/path1"),
- Path.of("/monochromePath1")),
- new ArchiveState.ArchiveActivityInfo("title2", Path.of("/path2"),
- Path.of("/monochromePath2"))),
- "installerTitle");
+ ArchiveState archiveState =
+ new ArchiveState(
+ List.of(
+ new ArchiveState.ArchiveActivityInfo(
+ "title1",
+ new ComponentName("pkg1", "class1"),
+ Path.of("/path1"),
+ Path.of("/monochromePath1")),
+ new ArchiveState.ArchiveActivityInfo(
+ "title2",
+ new ComponentName("pkg2", "class2"),
+ Path.of("/path2"),
+ Path.of("/monochromePath2"))),
+ "installerTitle");
packageSetting.modifyUserState(UserHandle.SYSTEM.getIdentifier()).setArchiveState(
archiveState);
settings.mPackages.put(PACKAGE_NAME_1, packageSetting);
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageUserStateTest.java
index 58ae7406580e..87a297b0e86f 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageUserStateTest.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
+import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.SuspendDialogInfo;
import android.content.pm.overlay.OverlayPaths;
@@ -192,8 +193,8 @@ public class PackageUserStateTest {
return new SuspendParams(dialogInfo, appExtras, launcherExtras);
}
- private static PersistableBundle createPersistableBundle(String lKey, long lValue, String sKey,
- String sValue, String dKey, double dValue) {
+ private static PersistableBundle createPersistableBundle(
+ String lKey, long lValue, String sKey, String sValue, String dKey, double dValue) {
final PersistableBundle result = new PersistableBundle(3);
if (lKey != null) {
result.putLong("com.unit_test." + lKey, lValue);
@@ -320,6 +321,7 @@ public class PackageUserStateTest {
assertEquals(0L, state.getLastPackageUsageTimeInMills()[i]);
}
}
+
private static void assertLastPackageUsageSet(
PackageStateUnserialized state, int reason, long value) throws Exception {
for (int i = state.getLastPackageUsageTimeInMills().length - 1; i >= 0; --i) {
@@ -330,6 +332,7 @@ public class PackageUserStateTest {
}
}
}
+
@Test
public void testPackageUseReasons() throws Exception {
PackageSetting packageSetting = Mockito.mock(PackageSetting.class);
@@ -377,6 +380,7 @@ public class PackageUserStateTest {
assertTrue(testState.setOverlayPaths(new OverlayPaths.Builder().build()));
assertFalse(testState.setOverlayPaths(null));
}
+
@Test
public void testSharedLibOverlayPaths() {
final PackageUserStateImpl testState = new PackageUserStateImpl();
@@ -401,8 +405,12 @@ public class PackageUserStateTest {
@Test
public void archiveState() {
PackageUserStateImpl packageUserState = new PackageUserStateImpl();
- ArchiveState.ArchiveActivityInfo archiveActivityInfo = new ArchiveState.ArchiveActivityInfo(
- "appTitle", Path.of("/path1"), Path.of("/path2"));
+ ArchiveState.ArchiveActivityInfo archiveActivityInfo =
+ new ArchiveState.ArchiveActivityInfo(
+ "appTitle",
+ new ComponentName("pkg", "class"),
+ Path.of("/path1"),
+ Path.of("/path2"));
ArchiveState archiveState = new ArchiveState(List.of(archiveActivityInfo),
"installerTitle");
packageUserState.setArchiveState(archiveState);
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
index eb50556821eb..610ea903767e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
@@ -35,6 +35,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
@@ -427,6 +428,7 @@ public class PackageArchiverTest {
for (LauncherActivityInfo mainActivity : createLauncherActivities()) {
ArchiveState.ArchiveActivityInfo activityInfo = new ArchiveState.ArchiveActivityInfo(
mainActivity.getLabel().toString(),
+ mainActivity.getComponentName(),
ICON_PATH, null);
activityInfos.add(activityInfo);
}
@@ -437,9 +439,11 @@ public class PackageArchiverTest {
ActivityInfo activityInfo = mock(ActivityInfo.class);
LauncherActivityInfo activity1 = mock(LauncherActivityInfo.class);
when(activity1.getLabel()).thenReturn("activity1");
+ when(activity1.getComponentName()).thenReturn(new ComponentName("pkg1", "class1"));
when(activity1.getActivityInfo()).thenReturn(activityInfo);
LauncherActivityInfo activity2 = mock(LauncherActivityInfo.class);
when(activity2.getLabel()).thenReturn("activity2");
+ when(activity2.getComponentName()).thenReturn(new ComponentName("pkg2", "class2"));
when(activity2.getActivityInfo()).thenReturn(activityInfo);
return List.of(activity1, activity2);
}