Loading core/proto/android/service/package.proto +25 −0 Original line number Original line Diff line number Diff line Loading @@ -101,6 +101,30 @@ message PackageProto { COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4; COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4; } } // Information about the state of an archived app. // All fields are gathered at the time of archival. message ArchiveState { option (android.msg_privacy).dest = DEST_AUTOMATIC; message ArchiveActivityInfo { // Corresponds to android:label in the app's locale at the time of archival. optional string title = 1; // Icon of the archived app. optional string icon_bitmap_path = 2; // Only set if the app defined a monochrome icon. optional string monochrome_icon_bitmap_path = 3; } /** Information about main activities. */ repeated ArchiveActivityInfo activity_infos = 1; // Corresponds to android:label of the installer responsible for the unarchival of the // app. Stored in the installer's locale at the time of archival. optional string installer_title = 2; } optional int32 id = 1; optional int32 id = 1; optional InstallType install_type = 2; optional InstallType install_type = 2; // Is the app restricted by owner / admin // Is the app restricted by owner / admin Loading @@ -114,6 +138,7 @@ message PackageProto { optional int32 distraction_flags = 10; optional int32 distraction_flags = 10; // UTC timestamp of first install for the user // UTC timestamp of first install for the user optional int32 first_install_time_ms = 11; optional int32 first_install_time_ms = 11; optional ArchiveState archive_state = 12; } } message InstallSourceProto { message InstallSourceProto { Loading services/core/java/com/android/server/pm/DeletePackageHelper.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -633,7 +633,8 @@ final class DeletePackageHelper { null /*harmfulAppWarning*/, null /*harmfulAppWarning*/, null /*splashScreenTheme*/, null /*splashScreenTheme*/, 0 /*firstInstallTime*/, 0 /*firstInstallTime*/, PackageManager.USER_MIN_ASPECT_RATIO_UNSET); PackageManager.USER_MIN_ASPECT_RATIO_UNSET, null /*archiveState*/); } } mPm.mSettings.writeKernelMappingLPr(ps); mPm.mSettings.writeKernelMappingLPr(ps); } } Loading services/core/java/com/android/server/pm/PackageSetting.java +36 −6 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/pm/Settings.java +102 −3 Original line number Original line Diff line number Diff line Loading @@ -107,6 +107,7 @@ import com.android.server.pm.permission.LegacyPermissionSettings; import com.android.server.pm.permission.LegacyPermissionState; import com.android.server.pm.permission.LegacyPermissionState; import com.android.server.pm.permission.LegacyPermissionState.PermissionState; import com.android.server.pm.permission.LegacyPermissionState.PermissionState; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.ArchiveState; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; import com.android.server.pm.pkg.PackageUserStateInternal; Loading Loading @@ -153,6 +154,7 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.PrintWriter; import java.nio.charset.Charset; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.text.SimpleDateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; Loading Loading @@ -316,6 +318,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile private static final String TAG_SUSPEND_PARAMS = "suspend-params"; private static final String TAG_SUSPEND_PARAMS = "suspend-params"; private static final String TAG_MIME_GROUP = "mime-group"; private static final String TAG_MIME_GROUP = "mime-group"; private static final String TAG_MIME_TYPE = "mime-type"; private static final String TAG_MIME_TYPE = "mime-type"; private static final String TAG_ARCHIVE_STATE = "archive-state"; private static final String TAG_ARCHIVE_ACTIVITY_INFO = "archive-activity-info"; public static final String ATTR_NAME = "name"; public static final String ATTR_NAME = "name"; public static final String ATTR_PACKAGE = "package"; public static final String ATTR_PACKAGE = "package"; Loading Loading @@ -362,6 +366,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile private static final String ATTR_DATABASE_VERSION = "databaseVersion"; private static final String ATTR_DATABASE_VERSION = "databaseVersion"; private static final String ATTR_VALUE = "value"; private static final String ATTR_VALUE = "value"; private static final String ATTR_FIRST_INSTALL_TIME = "first-install-time"; 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_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"; private final Handler mHandler; private final Handler mHandler; Loading Loading @@ -1131,7 +1139,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile null /*harmfulAppWarning*/, null /*harmfulAppWarning*/, null /*splashscreenTheme*/, null /*splashscreenTheme*/, 0 /*firstInstallTime*/, 0 /*firstInstallTime*/, PackageManager.USER_MIN_ASPECT_RATIO_UNSET PackageManager.USER_MIN_ASPECT_RATIO_UNSET, null /*archiveState*/ ); ); } } } } Loading Loading @@ -1807,7 +1816,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile null /*harmfulAppWarning*/, null /*harmfulAppWarning*/, null /* splashScreenTheme*/, null /* splashScreenTheme*/, 0 /*firstInstallTime*/, 0 /*firstInstallTime*/, PackageManager.USER_MIN_ASPECT_RATIO_UNSET PackageManager.USER_MIN_ASPECT_RATIO_UNSET, null /*archiveState*/ ); ); } } return; return; Loading Loading @@ -1911,6 +1921,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile PersistableBundle suspendedAppExtras = null; PersistableBundle suspendedAppExtras = null; PersistableBundle suspendedLauncherExtras = null; PersistableBundle suspendedLauncherExtras = null; SuspendDialogInfo oldSuspendDialogInfo = null; SuspendDialogInfo oldSuspendDialogInfo = null; ArchiveState archiveState = null; int packageDepth = parser.getDepth(); int packageDepth = parser.getDepth(); ArrayMap<String, SuspendParams> suspendParamsMap = null; ArrayMap<String, SuspendParams> suspendParamsMap = null; Loading Loading @@ -1952,6 +1963,9 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile suspendParamsMap.put(suspendingPackage, suspendParamsMap.put(suspendingPackage, SuspendParams.restoreFromXml(parser)); SuspendParams.restoreFromXml(parser)); break; break; case TAG_ARCHIVE_STATE: archiveState = parseArchiveState(parser); break; default: default: Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag " Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag " + TAG_PACKAGE); + TAG_PACKAGE); Loading Loading @@ -1982,7 +1996,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile uninstallReason, harmfulAppWarning, splashScreenTheme, uninstallReason, harmfulAppWarning, splashScreenTheme, firstInstallTime != 0 ? firstInstallTime : firstInstallTime != 0 ? firstInstallTime : origFirstInstallTimes.getOrDefault(name, 0L), origFirstInstallTimes.getOrDefault(name, 0L), minAspectRatio); minAspectRatio, archiveState); mDomainVerificationManager.setLegacyUserState(name, userId, verifState); mDomainVerificationManager.setLegacyUserState(name, userId, verifState); } else if (tagName.equals("preferred-activities")) { } else if (tagName.equals("preferred-activities")) { Loading Loading @@ -2011,6 +2025,64 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile } } } } private static ArchiveState parseArchiveState(TypedXmlPullParser parser) throws XmlPullParserException, IOException { String installerTitle = parser.getAttributeValue(null, ATTR_ARCHIVE_INSTALLER_TITLE); List<ArchiveState.ArchiveActivityInfo> activityInfos = parseArchiveActivityInfos(parser); if (installerTitle == null) { Slog.wtf(TAG, "parseArchiveState: installerTitle is null"); return null; } if (activityInfos.size() < 1) { Slog.wtf(TAG, "parseArchiveState: activityInfos is empty"); return null; } return new ArchiveState(activityInfos, installerTitle); } private static List<ArchiveState.ArchiveActivityInfo> parseArchiveActivityInfos( TypedXmlPullParser parser) throws XmlPullParserException, IOException { List<ArchiveState.ArchiveActivityInfo> activityInfos = new ArrayList<>(); int type; int outerDepth = parser.getDepth(); String tagName; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } tagName = parser.getName(); if (tagName.equals(TAG_ARCHIVE_ACTIVITY_INFO)) { String title = parser.getAttributeValue(null, ATTR_ARCHIVE_ACTIVITY_TITLE); Path iconPath = Path.of(parser.getAttributeValue(null, ATTR_ARCHIVE_ICON_PATH)); Path monochromeIconPath = Path.of(parser.getAttributeValue(null, ATTR_ARCHIVE_MONOCHROME_ICON_PATH)); 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, ATTR_ARCHIVE_ICON_PATH, iconPath)); continue; } activityInfos.add( new ArchiveState.ArchiveActivityInfo(title, iconPath, monochromeIconPath)); } } return activityInfos; } void setBlockUninstallLPw(int userId, String packageName, boolean blockUninstall) { void setBlockUninstallLPw(int userId, String packageName, boolean blockUninstall) { ArraySet<String> packages = mBlockUninstallPackages.get(userId); ArraySet<String> packages = mBlockUninstallPackages.get(userId); if (blockUninstall) { if (blockUninstall) { Loading Loading @@ -2323,6 +2395,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile } } serializer.endTag(null, TAG_DISABLED_COMPONENTS); serializer.endTag(null, TAG_DISABLED_COMPONENTS); } } writeArchiveStateLPr(serializer, ustate.getArchiveState()); serializer.endTag(null, TAG_PACKAGE); serializer.endTag(null, TAG_PACKAGE); } } Loading Loading @@ -2361,6 +2434,28 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile } } } } private void writeArchiveStateLPr(TypedXmlSerializer serializer, ArchiveState archiveState) throws IOException { if (archiveState == null) { return; } serializer.startTag(null, TAG_ARCHIVE_STATE); serializer.attribute(null, ATTR_ARCHIVE_INSTALLER_TITLE, archiveState.getInstallerTitle()); 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_ICON_PATH, activityInfo.getIconBitmap().toAbsolutePath().toString()); if (activityInfo.getMonochromeIconBitmap() != null) { serializer.attribute(null, ATTR_ARCHIVE_MONOCHROME_ICON_PATH, activityInfo.getMonochromeIconBitmap().toAbsolutePath().toString()); } serializer.endTag(null, TAG_ARCHIVE_ACTIVITY_INFO); } serializer.endTag(null, TAG_ARCHIVE_STATE); } void readInstallPermissionsLPr(TypedXmlPullParser parser, void readInstallPermissionsLPr(TypedXmlPullParser parser, LegacyPermissionState permissionsState, List<UserInfo> users) LegacyPermissionState permissionsState, List<UserInfo> users) throws IOException, XmlPullParserException { throws IOException, XmlPullParserException { Loading Loading @@ -5203,6 +5298,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile } } } } } } ArchiveState archiveState = userState.getArchiveState(); if (archiveState != null) { pw.print(archiveState.toString()); } } } } } Loading services/core/java/com/android/server/pm/pkg/ArchiveState.java 0 → 100644 +306 −0 Original line number Original line Diff line number Diff line /* * 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.pkg; import android.annotation.NonNull; import android.annotation.Nullable; import com.android.internal.util.DataClass; import java.nio.file.Path; import java.util.List; /** * Information about the state of an archived app. All fields are gathered at the time of * archival. * * @hide */ @DataClass(genEqualsHashCode = true, genToString = true) public class ArchiveState { /** * Information about main activities. * * <p> This list has at least one entry. In the vast majority of cases, this list has only one * entry. */ @NonNull private final List<ArchiveActivityInfo> mActivityInfos; /** * Corresponds to android:label of the installer responsible for the unarchival of the app. * Stored in the installer's locale . */ @NonNull private final String mInstallerTitle; /** Information about a main activity of an archived app. */ @DataClass(genEqualsHashCode = true, genToString = true) public static class ArchiveActivityInfo { /** Corresponds to the activity's android:label in the app's locale. */ @NonNull private final String mTitle; /** The path to the stored icon of the activity in the app's locale. */ @NonNull private final Path mIconBitmap; /** See {@link #mIconBitmap}. Only set if the app defined a monochrome icon. */ @Nullable private final Path mMonochromeIconBitmap; // Code below generated by codegen v1.0.23. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code // // To regenerate run: // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/ArchiveState.java // // To exclude the generated code from IntelliJ auto-formatting enable (one-time): // Settings > Editor > Code Style > Formatter Control //@formatter:off /** * Creates a new ArchiveActivityInfo. * * @param title * Corresponds to the activity's android:label in the app's locale. * @param iconBitmap * The path to the stored icon of the activity in the app's locale. * @param monochromeIconBitmap * See {@link #mIconBitmap}. Only set if the app defined a monochrome icon. */ @DataClass.Generated.Member public ArchiveActivityInfo( @NonNull String title, @NonNull Path iconBitmap, @Nullable Path monochromeIconBitmap) { this.mTitle = title; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mTitle); this.mIconBitmap = iconBitmap; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mIconBitmap); this.mMonochromeIconBitmap = monochromeIconBitmap; // onConstructed(); // You can define this method to get a callback } /** * Corresponds to the activity's android:label in the app's locale. */ @DataClass.Generated.Member public @NonNull String getTitle() { return mTitle; } /** * The path to the stored icon of the activity in the app's locale. */ @DataClass.Generated.Member public @NonNull Path getIconBitmap() { return mIconBitmap; } /** * See {@link #mIconBitmap}. Only set if the app defined a monochrome icon. */ @DataClass.Generated.Member public @Nullable Path getMonochromeIconBitmap() { return mMonochromeIconBitmap; } @Override @DataClass.Generated.Member public String toString() { // You can override field toString logic by defining methods like: // String fieldNameToString() { ... } return "ArchiveActivityInfo { " + "title = " + mTitle + ", " + "iconBitmap = " + mIconBitmap + ", " + "monochromeIconBitmap = " + mMonochromeIconBitmap + " }"; } @Override @DataClass.Generated.Member public boolean equals(@Nullable Object o) { // You can override field equality logic by defining either of the methods like: // boolean fieldNameEquals(ArchiveActivityInfo other) { ... } // boolean fieldNameEquals(FieldType otherValue) { ... } if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @SuppressWarnings("unchecked") ArchiveActivityInfo that = (ArchiveActivityInfo) o; //noinspection PointlessBooleanExpression return true && java.util.Objects.equals(mTitle, that.mTitle) && java.util.Objects.equals(mIconBitmap, that.mIconBitmap) && java.util.Objects.equals(mMonochromeIconBitmap, that.mMonochromeIconBitmap); } @Override @DataClass.Generated.Member public int hashCode() { // You can override field hashCode logic by defining methods like: // int fieldNameHashCode() { ... } int _hash = 1; _hash = 31 * _hash + java.util.Objects.hashCode(mTitle); _hash = 31 * _hash + java.util.Objects.hashCode(mIconBitmap); _hash = 31 * _hash + java.util.Objects.hashCode(mMonochromeIconBitmap); return _hash; } @DataClass.Generated( time = 1689169065133L, 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.NonNull 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() {} //@formatter:on // End of generated code } // Code below generated by codegen v1.0.23. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code // // To regenerate run: // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/ArchiveState.java // // To exclude the generated code from IntelliJ auto-formatting enable (one-time): // Settings > Editor > Code Style > Formatter Control //@formatter:off /** * Creates a new ArchiveState. * * @param activityInfos * Information about main activities. * * <p> This list has at least one entry. In the vast majority of cases, this list has only one * entry. * @param installerTitle * Corresponds to android:label of the installer responsible for the unarchival of the app. * Stored in the installer's locale . */ @DataClass.Generated.Member public ArchiveState( @NonNull List<ArchiveActivityInfo> activityInfos, @NonNull String installerTitle) { this.mActivityInfos = activityInfos; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mActivityInfos); this.mInstallerTitle = installerTitle; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mInstallerTitle); // onConstructed(); // You can define this method to get a callback } /** * Information about main activities. * * <p> This list has at least one entry. In the vast majority of cases, this list has only one * entry. */ @DataClass.Generated.Member public @NonNull List<ArchiveActivityInfo> getActivityInfos() { return mActivityInfos; } /** * Corresponds to android:label of the installer responsible for the unarchival of the app. * Stored in the installer's locale . */ @DataClass.Generated.Member public @NonNull String getInstallerTitle() { return mInstallerTitle; } @Override @DataClass.Generated.Member public String toString() { // You can override field toString logic by defining methods like: // String fieldNameToString() { ... } return "ArchiveState { " + "activityInfos = " + mActivityInfos + ", " + "installerTitle = " + mInstallerTitle + " }"; } @Override @DataClass.Generated.Member public boolean equals(@Nullable Object o) { // You can override field equality logic by defining either of the methods like: // boolean fieldNameEquals(ArchiveState other) { ... } // boolean fieldNameEquals(FieldType otherValue) { ... } if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @SuppressWarnings("unchecked") ArchiveState that = (ArchiveState) o; //noinspection PointlessBooleanExpression return true && java.util.Objects.equals(mActivityInfos, that.mActivityInfos) && java.util.Objects.equals(mInstallerTitle, that.mInstallerTitle); } @Override @DataClass.Generated.Member public int hashCode() { // You can override field hashCode logic by defining methods like: // int fieldNameHashCode() { ... } int _hash = 1; _hash = 31 * _hash + java.util.Objects.hashCode(mActivityInfos); _hash = 31 * _hash + java.util.Objects.hashCode(mInstallerTitle); return _hash; } @DataClass.Generated( time = 1689169065144L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/ArchiveState.java", inputSignatures = "private final @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.ArchiveActivityInfo> mActivityInfos\nprivate final @android.annotation.NonNull java.lang.String mInstallerTitle\nclass ArchiveState extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)") @Deprecated private void __metadata() {} //@formatter:on // End of generated code } Loading
core/proto/android/service/package.proto +25 −0 Original line number Original line Diff line number Diff line Loading @@ -101,6 +101,30 @@ message PackageProto { COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4; COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4; } } // Information about the state of an archived app. // All fields are gathered at the time of archival. message ArchiveState { option (android.msg_privacy).dest = DEST_AUTOMATIC; message ArchiveActivityInfo { // Corresponds to android:label in the app's locale at the time of archival. optional string title = 1; // Icon of the archived app. optional string icon_bitmap_path = 2; // Only set if the app defined a monochrome icon. optional string monochrome_icon_bitmap_path = 3; } /** Information about main activities. */ repeated ArchiveActivityInfo activity_infos = 1; // Corresponds to android:label of the installer responsible for the unarchival of the // app. Stored in the installer's locale at the time of archival. optional string installer_title = 2; } optional int32 id = 1; optional int32 id = 1; optional InstallType install_type = 2; optional InstallType install_type = 2; // Is the app restricted by owner / admin // Is the app restricted by owner / admin Loading @@ -114,6 +138,7 @@ message PackageProto { optional int32 distraction_flags = 10; optional int32 distraction_flags = 10; // UTC timestamp of first install for the user // UTC timestamp of first install for the user optional int32 first_install_time_ms = 11; optional int32 first_install_time_ms = 11; optional ArchiveState archive_state = 12; } } message InstallSourceProto { message InstallSourceProto { Loading
services/core/java/com/android/server/pm/DeletePackageHelper.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -633,7 +633,8 @@ final class DeletePackageHelper { null /*harmfulAppWarning*/, null /*harmfulAppWarning*/, null /*splashScreenTheme*/, null /*splashScreenTheme*/, 0 /*firstInstallTime*/, 0 /*firstInstallTime*/, PackageManager.USER_MIN_ASPECT_RATIO_UNSET); PackageManager.USER_MIN_ASPECT_RATIO_UNSET, null /*archiveState*/); } } mPm.mSettings.writeKernelMappingLPr(ps); mPm.mSettings.writeKernelMappingLPr(ps); } } Loading
services/core/java/com/android/server/pm/PackageSetting.java +36 −6 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/pm/Settings.java +102 −3 Original line number Original line Diff line number Diff line Loading @@ -107,6 +107,7 @@ import com.android.server.pm.permission.LegacyPermissionSettings; import com.android.server.pm.permission.LegacyPermissionState; import com.android.server.pm.permission.LegacyPermissionState; import com.android.server.pm.permission.LegacyPermissionState.PermissionState; import com.android.server.pm.permission.LegacyPermissionState.PermissionState; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.ArchiveState; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; import com.android.server.pm.pkg.PackageUserStateInternal; Loading Loading @@ -153,6 +154,7 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.PrintWriter; import java.nio.charset.Charset; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.text.SimpleDateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; Loading Loading @@ -316,6 +318,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile private static final String TAG_SUSPEND_PARAMS = "suspend-params"; private static final String TAG_SUSPEND_PARAMS = "suspend-params"; private static final String TAG_MIME_GROUP = "mime-group"; private static final String TAG_MIME_GROUP = "mime-group"; private static final String TAG_MIME_TYPE = "mime-type"; private static final String TAG_MIME_TYPE = "mime-type"; private static final String TAG_ARCHIVE_STATE = "archive-state"; private static final String TAG_ARCHIVE_ACTIVITY_INFO = "archive-activity-info"; public static final String ATTR_NAME = "name"; public static final String ATTR_NAME = "name"; public static final String ATTR_PACKAGE = "package"; public static final String ATTR_PACKAGE = "package"; Loading Loading @@ -362,6 +366,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile private static final String ATTR_DATABASE_VERSION = "databaseVersion"; private static final String ATTR_DATABASE_VERSION = "databaseVersion"; private static final String ATTR_VALUE = "value"; private static final String ATTR_VALUE = "value"; private static final String ATTR_FIRST_INSTALL_TIME = "first-install-time"; 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_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"; private final Handler mHandler; private final Handler mHandler; Loading Loading @@ -1131,7 +1139,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile null /*harmfulAppWarning*/, null /*harmfulAppWarning*/, null /*splashscreenTheme*/, null /*splashscreenTheme*/, 0 /*firstInstallTime*/, 0 /*firstInstallTime*/, PackageManager.USER_MIN_ASPECT_RATIO_UNSET PackageManager.USER_MIN_ASPECT_RATIO_UNSET, null /*archiveState*/ ); ); } } } } Loading Loading @@ -1807,7 +1816,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile null /*harmfulAppWarning*/, null /*harmfulAppWarning*/, null /* splashScreenTheme*/, null /* splashScreenTheme*/, 0 /*firstInstallTime*/, 0 /*firstInstallTime*/, PackageManager.USER_MIN_ASPECT_RATIO_UNSET PackageManager.USER_MIN_ASPECT_RATIO_UNSET, null /*archiveState*/ ); ); } } return; return; Loading Loading @@ -1911,6 +1921,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile PersistableBundle suspendedAppExtras = null; PersistableBundle suspendedAppExtras = null; PersistableBundle suspendedLauncherExtras = null; PersistableBundle suspendedLauncherExtras = null; SuspendDialogInfo oldSuspendDialogInfo = null; SuspendDialogInfo oldSuspendDialogInfo = null; ArchiveState archiveState = null; int packageDepth = parser.getDepth(); int packageDepth = parser.getDepth(); ArrayMap<String, SuspendParams> suspendParamsMap = null; ArrayMap<String, SuspendParams> suspendParamsMap = null; Loading Loading @@ -1952,6 +1963,9 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile suspendParamsMap.put(suspendingPackage, suspendParamsMap.put(suspendingPackage, SuspendParams.restoreFromXml(parser)); SuspendParams.restoreFromXml(parser)); break; break; case TAG_ARCHIVE_STATE: archiveState = parseArchiveState(parser); break; default: default: Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag " Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag " + TAG_PACKAGE); + TAG_PACKAGE); Loading Loading @@ -1982,7 +1996,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile uninstallReason, harmfulAppWarning, splashScreenTheme, uninstallReason, harmfulAppWarning, splashScreenTheme, firstInstallTime != 0 ? firstInstallTime : firstInstallTime != 0 ? firstInstallTime : origFirstInstallTimes.getOrDefault(name, 0L), origFirstInstallTimes.getOrDefault(name, 0L), minAspectRatio); minAspectRatio, archiveState); mDomainVerificationManager.setLegacyUserState(name, userId, verifState); mDomainVerificationManager.setLegacyUserState(name, userId, verifState); } else if (tagName.equals("preferred-activities")) { } else if (tagName.equals("preferred-activities")) { Loading Loading @@ -2011,6 +2025,64 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile } } } } private static ArchiveState parseArchiveState(TypedXmlPullParser parser) throws XmlPullParserException, IOException { String installerTitle = parser.getAttributeValue(null, ATTR_ARCHIVE_INSTALLER_TITLE); List<ArchiveState.ArchiveActivityInfo> activityInfos = parseArchiveActivityInfos(parser); if (installerTitle == null) { Slog.wtf(TAG, "parseArchiveState: installerTitle is null"); return null; } if (activityInfos.size() < 1) { Slog.wtf(TAG, "parseArchiveState: activityInfos is empty"); return null; } return new ArchiveState(activityInfos, installerTitle); } private static List<ArchiveState.ArchiveActivityInfo> parseArchiveActivityInfos( TypedXmlPullParser parser) throws XmlPullParserException, IOException { List<ArchiveState.ArchiveActivityInfo> activityInfos = new ArrayList<>(); int type; int outerDepth = parser.getDepth(); String tagName; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } tagName = parser.getName(); if (tagName.equals(TAG_ARCHIVE_ACTIVITY_INFO)) { String title = parser.getAttributeValue(null, ATTR_ARCHIVE_ACTIVITY_TITLE); Path iconPath = Path.of(parser.getAttributeValue(null, ATTR_ARCHIVE_ICON_PATH)); Path monochromeIconPath = Path.of(parser.getAttributeValue(null, ATTR_ARCHIVE_MONOCHROME_ICON_PATH)); 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, ATTR_ARCHIVE_ICON_PATH, iconPath)); continue; } activityInfos.add( new ArchiveState.ArchiveActivityInfo(title, iconPath, monochromeIconPath)); } } return activityInfos; } void setBlockUninstallLPw(int userId, String packageName, boolean blockUninstall) { void setBlockUninstallLPw(int userId, String packageName, boolean blockUninstall) { ArraySet<String> packages = mBlockUninstallPackages.get(userId); ArraySet<String> packages = mBlockUninstallPackages.get(userId); if (blockUninstall) { if (blockUninstall) { Loading Loading @@ -2323,6 +2395,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile } } serializer.endTag(null, TAG_DISABLED_COMPONENTS); serializer.endTag(null, TAG_DISABLED_COMPONENTS); } } writeArchiveStateLPr(serializer, ustate.getArchiveState()); serializer.endTag(null, TAG_PACKAGE); serializer.endTag(null, TAG_PACKAGE); } } Loading Loading @@ -2361,6 +2434,28 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile } } } } private void writeArchiveStateLPr(TypedXmlSerializer serializer, ArchiveState archiveState) throws IOException { if (archiveState == null) { return; } serializer.startTag(null, TAG_ARCHIVE_STATE); serializer.attribute(null, ATTR_ARCHIVE_INSTALLER_TITLE, archiveState.getInstallerTitle()); 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_ICON_PATH, activityInfo.getIconBitmap().toAbsolutePath().toString()); if (activityInfo.getMonochromeIconBitmap() != null) { serializer.attribute(null, ATTR_ARCHIVE_MONOCHROME_ICON_PATH, activityInfo.getMonochromeIconBitmap().toAbsolutePath().toString()); } serializer.endTag(null, TAG_ARCHIVE_ACTIVITY_INFO); } serializer.endTag(null, TAG_ARCHIVE_STATE); } void readInstallPermissionsLPr(TypedXmlPullParser parser, void readInstallPermissionsLPr(TypedXmlPullParser parser, LegacyPermissionState permissionsState, List<UserInfo> users) LegacyPermissionState permissionsState, List<UserInfo> users) throws IOException, XmlPullParserException { throws IOException, XmlPullParserException { Loading Loading @@ -5203,6 +5298,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile } } } } } } ArchiveState archiveState = userState.getArchiveState(); if (archiveState != null) { pw.print(archiveState.toString()); } } } } } Loading
services/core/java/com/android/server/pm/pkg/ArchiveState.java 0 → 100644 +306 −0 Original line number Original line Diff line number Diff line /* * 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.pkg; import android.annotation.NonNull; import android.annotation.Nullable; import com.android.internal.util.DataClass; import java.nio.file.Path; import java.util.List; /** * Information about the state of an archived app. All fields are gathered at the time of * archival. * * @hide */ @DataClass(genEqualsHashCode = true, genToString = true) public class ArchiveState { /** * Information about main activities. * * <p> This list has at least one entry. In the vast majority of cases, this list has only one * entry. */ @NonNull private final List<ArchiveActivityInfo> mActivityInfos; /** * Corresponds to android:label of the installer responsible for the unarchival of the app. * Stored in the installer's locale . */ @NonNull private final String mInstallerTitle; /** Information about a main activity of an archived app. */ @DataClass(genEqualsHashCode = true, genToString = true) public static class ArchiveActivityInfo { /** Corresponds to the activity's android:label in the app's locale. */ @NonNull private final String mTitle; /** The path to the stored icon of the activity in the app's locale. */ @NonNull private final Path mIconBitmap; /** See {@link #mIconBitmap}. Only set if the app defined a monochrome icon. */ @Nullable private final Path mMonochromeIconBitmap; // Code below generated by codegen v1.0.23. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code // // To regenerate run: // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/ArchiveState.java // // To exclude the generated code from IntelliJ auto-formatting enable (one-time): // Settings > Editor > Code Style > Formatter Control //@formatter:off /** * Creates a new ArchiveActivityInfo. * * @param title * Corresponds to the activity's android:label in the app's locale. * @param iconBitmap * The path to the stored icon of the activity in the app's locale. * @param monochromeIconBitmap * See {@link #mIconBitmap}. Only set if the app defined a monochrome icon. */ @DataClass.Generated.Member public ArchiveActivityInfo( @NonNull String title, @NonNull Path iconBitmap, @Nullable Path monochromeIconBitmap) { this.mTitle = title; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mTitle); this.mIconBitmap = iconBitmap; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mIconBitmap); this.mMonochromeIconBitmap = monochromeIconBitmap; // onConstructed(); // You can define this method to get a callback } /** * Corresponds to the activity's android:label in the app's locale. */ @DataClass.Generated.Member public @NonNull String getTitle() { return mTitle; } /** * The path to the stored icon of the activity in the app's locale. */ @DataClass.Generated.Member public @NonNull Path getIconBitmap() { return mIconBitmap; } /** * See {@link #mIconBitmap}. Only set if the app defined a monochrome icon. */ @DataClass.Generated.Member public @Nullable Path getMonochromeIconBitmap() { return mMonochromeIconBitmap; } @Override @DataClass.Generated.Member public String toString() { // You can override field toString logic by defining methods like: // String fieldNameToString() { ... } return "ArchiveActivityInfo { " + "title = " + mTitle + ", " + "iconBitmap = " + mIconBitmap + ", " + "monochromeIconBitmap = " + mMonochromeIconBitmap + " }"; } @Override @DataClass.Generated.Member public boolean equals(@Nullable Object o) { // You can override field equality logic by defining either of the methods like: // boolean fieldNameEquals(ArchiveActivityInfo other) { ... } // boolean fieldNameEquals(FieldType otherValue) { ... } if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @SuppressWarnings("unchecked") ArchiveActivityInfo that = (ArchiveActivityInfo) o; //noinspection PointlessBooleanExpression return true && java.util.Objects.equals(mTitle, that.mTitle) && java.util.Objects.equals(mIconBitmap, that.mIconBitmap) && java.util.Objects.equals(mMonochromeIconBitmap, that.mMonochromeIconBitmap); } @Override @DataClass.Generated.Member public int hashCode() { // You can override field hashCode logic by defining methods like: // int fieldNameHashCode() { ... } int _hash = 1; _hash = 31 * _hash + java.util.Objects.hashCode(mTitle); _hash = 31 * _hash + java.util.Objects.hashCode(mIconBitmap); _hash = 31 * _hash + java.util.Objects.hashCode(mMonochromeIconBitmap); return _hash; } @DataClass.Generated( time = 1689169065133L, 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.NonNull 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() {} //@formatter:on // End of generated code } // Code below generated by codegen v1.0.23. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code // // To regenerate run: // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/ArchiveState.java // // To exclude the generated code from IntelliJ auto-formatting enable (one-time): // Settings > Editor > Code Style > Formatter Control //@formatter:off /** * Creates a new ArchiveState. * * @param activityInfos * Information about main activities. * * <p> This list has at least one entry. In the vast majority of cases, this list has only one * entry. * @param installerTitle * Corresponds to android:label of the installer responsible for the unarchival of the app. * Stored in the installer's locale . */ @DataClass.Generated.Member public ArchiveState( @NonNull List<ArchiveActivityInfo> activityInfos, @NonNull String installerTitle) { this.mActivityInfos = activityInfos; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mActivityInfos); this.mInstallerTitle = installerTitle; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mInstallerTitle); // onConstructed(); // You can define this method to get a callback } /** * Information about main activities. * * <p> This list has at least one entry. In the vast majority of cases, this list has only one * entry. */ @DataClass.Generated.Member public @NonNull List<ArchiveActivityInfo> getActivityInfos() { return mActivityInfos; } /** * Corresponds to android:label of the installer responsible for the unarchival of the app. * Stored in the installer's locale . */ @DataClass.Generated.Member public @NonNull String getInstallerTitle() { return mInstallerTitle; } @Override @DataClass.Generated.Member public String toString() { // You can override field toString logic by defining methods like: // String fieldNameToString() { ... } return "ArchiveState { " + "activityInfos = " + mActivityInfos + ", " + "installerTitle = " + mInstallerTitle + " }"; } @Override @DataClass.Generated.Member public boolean equals(@Nullable Object o) { // You can override field equality logic by defining either of the methods like: // boolean fieldNameEquals(ArchiveState other) { ... } // boolean fieldNameEquals(FieldType otherValue) { ... } if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @SuppressWarnings("unchecked") ArchiveState that = (ArchiveState) o; //noinspection PointlessBooleanExpression return true && java.util.Objects.equals(mActivityInfos, that.mActivityInfos) && java.util.Objects.equals(mInstallerTitle, that.mInstallerTitle); } @Override @DataClass.Generated.Member public int hashCode() { // You can override field hashCode logic by defining methods like: // int fieldNameHashCode() { ... } int _hash = 1; _hash = 31 * _hash + java.util.Objects.hashCode(mActivityInfos); _hash = 31 * _hash + java.util.Objects.hashCode(mInstallerTitle); return _hash; } @DataClass.Generated( time = 1689169065144L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/ArchiveState.java", inputSignatures = "private final @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.ArchiveActivityInfo> mActivityInfos\nprivate final @android.annotation.NonNull java.lang.String mInstallerTitle\nclass ArchiveState extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)") @Deprecated private void __metadata() {} //@formatter:on // End of generated code }