diff options
19 files changed, 433 insertions, 8 deletions
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 7e0a9b69b7bd..3cbea87e135e 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -130,7 +130,6 @@ import android.util.Slog; import android.util.Xml; import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.Immutable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; import com.android.internal.pm.RoSystemFeatures; @@ -1020,6 +1019,33 @@ public class ApplicationPackageManager extends PackageManager { } } + @Override + public void setPageSizeAppCompatFlagsSettingsOverride(String packageName, boolean enabled) { + try { + mPM.setPageSizeAppCompatFlagsSettingsOverride(packageName, enabled); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + @Override + public boolean isPageSizeCompatEnabled(String packageName) { + try { + return mPM.isPageSizeCompatEnabled(packageName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + @Override + public String getPageSizeCompatWarningMessage(String packageName) { + try { + return mPM.getPageSizeCompatWarningMessage(packageName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + private static List<byte[]> encodeCertificates(List<Certificate> certs) throws CertificateEncodingException { if (certs == null) { diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index cccfdb0938e5..94784227049d 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -1449,6 +1449,97 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } } + /** + * Use this to report any errors during alignment checks + * + * @hide + */ + public static final int PAGE_SIZE_APP_COMPAT_FLAG_ERROR = -1; + + /** + * Initial value for mPageSizeAppCompatFlags + * + * @hide + */ + public static final int PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED = 0; + + /** + * if set, extract libs forcefully for 16 KB device and show warning dialog. + * + * @hide + */ + public static final int PAGE_SIZE_APP_COMPAT_FLAG_UNCOMPRESSED_LIBS_NOT_ALIGNED = 1 << 1; + + /** + * if set, load 4 KB aligned ELFs on 16 KB device in compat mode and show warning dialog. + * + * @hide + */ + public static final int PAGE_SIZE_APP_COMPAT_FLAG_ELF_NOT_ALIGNED = 1 << 2; + + /** + * Run in 16 KB app compat mode. This flag will be set explicitly through settings. If set, 16 + * KB app compat warning dialogs will still show up. + * + * @hide + */ + public static final int PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_ENABLED = 1 << 3; + + /** + * Disable 16 KB app compat mode through settings. It should only affect ELF loading as app is + * already installed. + * + * @hide + */ + public static final int PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_DISABLED = 1 << 4; + + /** + * Run in 16 KB app compat mode. This flag will be set explicitly through manifest. If set, hide + * the 16 KB app compat warning dialogs. This has the highest priority to enable compat mode. + * + * @hide + */ + public static final int PAGE_SIZE_APP_COMPAT_FLAG_MANIFEST_OVERRIDE_ENABLED = 1 << 5; + + /** + * Disable 16 KB app compat mode. This has the highest priority to disable compat mode. + * + * @hide + */ + public static final int PAGE_SIZE_APP_COMPAT_FLAG_MANIFEST_OVERRIDE_DISABLED = 1 << 6; + + /** + * Max value for page size app compat + * + * @hide + */ + public static final int PAGE_SIZE_APP_COMPAT_FLAG_MAX = 1 << 7; + + /** + * 16 KB app compat status for the app. App can have native shared libs which are not page + * aligned, LOAD segments inside the shared libs have to be page aligned. Apps can specify the + * override in manifest file as well. + */ + private @PageSizeAppCompatFlags int mPageSizeAppCompatFlags = + ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED; + + /** {@hide} */ + @IntDef( + prefix = {"PAGE_SIZE_APP_COMPAT_FLAG_"}, + value = { + PAGE_SIZE_APP_COMPAT_FLAG_ERROR, + PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED, + PAGE_SIZE_APP_COMPAT_FLAG_UNCOMPRESSED_LIBS_NOT_ALIGNED, + PAGE_SIZE_APP_COMPAT_FLAG_ELF_NOT_ALIGNED, + PAGE_SIZE_APP_COMPAT_FLAG_MANIFEST_OVERRIDE_ENABLED, + PAGE_SIZE_APP_COMPAT_FLAG_MANIFEST_OVERRIDE_DISABLED, + PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_ENABLED, + PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_DISABLED, + PAGE_SIZE_APP_COMPAT_FLAG_MAX, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface PageSizeAppCompatFlags {} + /** @hide */ public String classLoaderName; @@ -1777,7 +1868,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { pw.println(prefix + "enableOnBackInvokedCallback=" + isOnBackInvokedCallbackEnabled()); pw.println(prefix + "allowCrossUidActivitySwitchFromBelow=" + allowCrossUidActivitySwitchFromBelow); - + pw.println(prefix + "mPageSizeAppCompatFlags=" + mPageSizeAppCompatFlags); } pw.println(prefix + "createTimestamp=" + createTimestamp); if (mKnownActivityEmbeddingCerts != null) { @@ -1897,6 +1988,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } proto.write(ApplicationInfoProto.Detail.ALLOW_CROSS_UID_ACTIVITY_SWITCH_FROM_BELOW, allowCrossUidActivitySwitchFromBelow); + + proto.write(ApplicationInfoProto.Detail.ENABLE_PAGE_SIZE_APP_COMPAT, + mPageSizeAppCompatFlags); + proto.end(detailToken); } if (!ArrayUtils.isEmpty(mKnownActivityEmbeddingCerts)) { @@ -2024,6 +2119,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { localeConfigRes = orig.localeConfigRes; allowCrossUidActivitySwitchFromBelow = orig.allowCrossUidActivitySwitchFromBelow; createTimestamp = SystemClock.uptimeMillis(); + mPageSizeAppCompatFlags = orig.mPageSizeAppCompatFlags; } public String toString() { @@ -2128,6 +2224,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } dest.writeInt(localeConfigRes); dest.writeInt(allowCrossUidActivitySwitchFromBelow ? 1 : 0); + dest.writeInt(mPageSizeAppCompatFlags); sForStringSet.parcel(mKnownActivityEmbeddingCerts, dest, flags); } @@ -2228,6 +2325,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } localeConfigRes = source.readInt(); allowCrossUidActivitySwitchFromBelow = source.readInt() != 0; + mPageSizeAppCompatFlags = source.readInt(); mKnownActivityEmbeddingCerts = sForStringSet.unparcel(source); if (mKnownActivityEmbeddingCerts.isEmpty()) { @@ -2765,6 +2863,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { requestRawExternalStorageAccess = value; } + /** {@hide} */ + public void setPageSizeAppCompatFlags(@PageSizeAppCompatFlags int value) { + mPageSizeAppCompatFlags |= value; + } + /** * Replaces {@link #mAppClassNamesByProcess}. This takes over the ownership of the passed map. * Do not modify the argument at the callsite. diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 5d4babb8a36d..57c12403dec8 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -848,4 +848,10 @@ interface IPackageManager { int getAppMetadataSource(String packageName, int userId); ComponentName getDomainVerificationAgent(int userId); + + void setPageSizeAppCompatFlagsSettingsOverride(in String packageName, boolean enabled); + + boolean isPageSizeCompatEnabled(in String packageName); + + String getPageSizeCompatWarningMessage(in String packageName); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index b85111fca703..23d3693628e7 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -804,7 +804,6 @@ public abstract class PackageManager { @Deprecated private void __metadata() {} - //@formatter:on // End of generated code @@ -11008,6 +11007,41 @@ public abstract class PackageManager { } /** + * Set the page compat mode override for given package + * + * @hide + */ + @FlaggedApi(android.content.pm.Flags.FLAG_APP_COMPAT_OPTION_16KB) + public void setPageSizeAppCompatFlagsSettingsOverride(@NonNull String packageName, + boolean enabled) { + throw new UnsupportedOperationException( + "setPageSizeAppCompatFlagsSettingsOverride not implemented in subclass"); + } + + /** + * Check whether page size app compat mode is enabled for given package + * + * @hide + */ + @FlaggedApi(android.content.pm.Flags.FLAG_APP_COMPAT_OPTION_16KB) + public boolean isPageSizeCompatEnabled(@NonNull String packageName) { + throw new UnsupportedOperationException( + "isPageSizeCompatEnabled not implemented in subclass"); + } + + /** + * Get the page size app compat warning dialog to show at app launch time + * + * @hide + */ + @Nullable + @FlaggedApi(android.content.pm.Flags.FLAG_APP_COMPAT_OPTION_16KB) + public String getPageSizeCompatWarningMessage(@NonNull String packageName) { + throw new UnsupportedOperationException( + "getPageSizeCompatWarningMessage not implemented in subclass"); + } + + /** * Returns the harmful app warning string for the given app, or null if there is none set. * * @param packageName The full name of the desired package. diff --git a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java index 48d0d6c777de..5ec5762c0533 100644 --- a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java +++ b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java @@ -392,6 +392,10 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, private int memtagMode; @ApplicationInfo.NativeHeapZeroInitialized private int nativeHeapZeroInitialized; + + @ApplicationInfo.PageSizeAppCompatFlags private int mPageSizeAppCompatFlags = + ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED; + @Nullable @DataClass.ParcelWith(Parcelling.BuiltIn.ForBoolean.class) private Boolean requestRawExternalStorageAccess; @@ -1118,6 +1122,12 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, return nativeHeapZeroInitialized; } + @ApplicationInfo.PageSizeAppCompatFlags + @Override + public int getPageSizeAppCompatFlags() { + return mPageSizeAppCompatFlags; + } + @Override public int getNetworkSecurityConfigResourceId() { return networkSecurityConfigRes; @@ -2221,6 +2231,12 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, } @Override + public PackageImpl setPageSizeAppCompatFlags(@ApplicationInfo.PageSizeAppCompatFlags int flag) { + mPageSizeAppCompatFlags = flag; + return this; + } + + @Override public PackageImpl setNetworkSecurityConfigResourceId(int value) { networkSecurityConfigRes = value; return this; @@ -2703,6 +2719,7 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, appInfo.setKnownActivityEmbeddingCerts(mKnownActivityEmbeddingCerts); } appInfo.allowCrossUidActivitySwitchFromBelow = mAllowCrossUidActivitySwitchFromBelow; + appInfo.setPageSizeAppCompatFlags(mPageSizeAppCompatFlags); return appInfo; } @@ -3305,6 +3322,7 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, dest.writeInt(this.mIntentMatchingFlags); dest.writeIntArray(this.mAlternateLauncherIconResIds); dest.writeIntArray(this.mAlternateLauncherLabelResIds); + dest.writeInt(this.mPageSizeAppCompatFlags); } private void writeFeatureFlagState(@NonNull Parcel dest) { @@ -3499,6 +3517,7 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, this.mIntentMatchingFlags = in.readInt(); this.mAlternateLauncherIconResIds = in.createIntArray(); this.mAlternateLauncherLabelResIds = in.createIntArray(); + this.mPageSizeAppCompatFlags = in.readInt(); assignDerivedFields(); assignDerivedFields2(); diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java index 67b985a61455..5062d58d4dca 100644 --- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java +++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java @@ -31,7 +31,6 @@ import android.util.ArraySet; import android.util.SparseArray; import android.util.SparseIntArray; -import com.android.internal.R; import com.android.internal.pm.parsing.pkg.ParsedPackage; import com.android.internal.pm.pkg.component.ParsedActivity; import com.android.internal.pm.pkg.component.ParsedApexSystemService; @@ -280,6 +279,9 @@ public interface ParsingPackage { ParsingPackage setNativeHeapZeroInitialized( @ApplicationInfo.NativeHeapZeroInitialized int nativeHeapZeroInitialized); + /** Manifest option pageSizeCompat will populate this field */ + ParsingPackage setPageSizeAppCompatFlags(@ApplicationInfo.PageSizeAppCompatFlags int value); + ParsingPackage setRequestRawExternalStorageAccess( @Nullable Boolean requestRawExternalStorageAccess); diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java index 5fc1276dd9f9..0f93e6e8109b 100644 --- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java +++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java @@ -541,6 +541,7 @@ public class ParsingPackageUtils { pkg.setGwpAsanMode(-1); pkg.setMemtagMode(-1); + pkg.setPageSizeAppCompatFlags(ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED); afterParseBaseApplication(pkg); @@ -2182,6 +2183,13 @@ public class ParsingPackageUtils { pkg.setGwpAsanMode(sa.getInt(R.styleable.AndroidManifestApplication_gwpAsanMode, -1)); pkg.setMemtagMode(sa.getInt(R.styleable.AndroidManifestApplication_memtagMode, -1)); + + if (Flags.appCompatOption16kb()) { + pkg.setPageSizeAppCompatFlags( + sa.getInt(R.styleable.AndroidManifestApplication_pageSizeCompat, + ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED)); + } + if (sa.hasValue(R.styleable.AndroidManifestApplication_nativeHeapZeroInitialized)) { final boolean v = sa.getBoolean( R.styleable.AndroidManifestApplication_nativeHeapZeroInitialized, false); diff --git a/core/java/com/android/server/pm/pkg/AndroidPackage.java b/core/java/com/android/server/pm/pkg/AndroidPackage.java index d05f5e3950b4..70dd10f2c371 100644 --- a/core/java/com/android/server/pm/pkg/AndroidPackage.java +++ b/core/java/com/android/server/pm/pkg/AndroidPackage.java @@ -875,6 +875,14 @@ public interface AndroidPackage { int getMemtagMode(); /** + * @see ApplicationInfo#getPageSizeAppCompatFlags() + * @see R.styleable#AndroidManifestApplication_pageSizeCompat + * @hide + */ + @ApplicationInfo.PageSizeAppCompatFlags + int getPageSizeAppCompatFlags(); + + /** * TODO(b/135203078): Make all the Bundles immutable (and non-null by shared empty reference?) * @see R.styleable#AndroidManifestMetaData * @hide diff --git a/core/proto/android/content/package_item_info.proto b/core/proto/android/content/package_item_info.proto index b7408a4da381..facadeedd1f8 100644 --- a/core/proto/android/content/package_item_info.proto +++ b/core/proto/android/content/package_item_info.proto @@ -114,6 +114,7 @@ message ApplicationInfoProto { optional int32 enable_memtag = 20; optional bool native_heap_zero_init = 21; optional bool allow_cross_uid_activity_switch_from_below = 22; + optional int32 enable_page_size_app_compat = 23; } optional Detail detail = 17; repeated string overlay_paths = 18; diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 7ef539492aa4..cdf184c9c944 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1867,8 +1867,12 @@ 16 KB device. 4 KB natives libs will be loaded app-compat mode if they are eligible. @FlaggedApi(android.content.pm.Flags.FLAG_APP_COMPAT_OPTION_16KB) --> <attr name="pageSizeCompat"> - <enum name="enabled" value="5" /> - <enum name="disabled" value="6" /> + <!-- value for enabled must match with + ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_MANIFEST_OVERRIDE_ENABLED --> + <enum name="enabled" value="32" /> + <!-- value for disabled must match with + ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_MANIFEST_OVERRIDE_DISABLED --> + <enum name="disabled" value="64" /> </attr> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 413f0c3e0c58..d498b9191559 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -199,6 +199,21 @@ <!-- Displayed to confirm to the user that caller ID will not be restricted on the next call or in general. --> <string name="CLIRDefaultOffNextCallOff">Caller ID defaults to not restricted. Next call: Not restricted</string> + <!-- Message displayed in dialog when APK is not 16 KB aligned. [CHAR LIMIT=NONE] --> + <string name="page_size_compat_apk_warning">This app isn’t 16 KB compatible. APK alignment check failed. + This app will be run using page size compatible mode. For best compatibility, please recompile the application with 16 KB support. + For more information, see <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> </string> + + <!-- Message displayed in dialog when ELF is not 16 KB aligned. [CHAR LIMIT=NONE] --> + <string name="page_size_compat_elf_warning">This app isn’t 16 KB compatible. ELF alignment check failed. + This app will be run using page size compatible mode. For best compatibility, please recompile the application with 16 KB support. + For more information, see <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a></string> + + <!-- Message displayed in dialog when APK and ELF are not 16 KB aligned. [CHAR LIMIT=NONE] --> + <string name="page_size_compat_apk_and_elf_warning">This app isn’t 16 KB compatible. APK and ELF alignment checks failed. + This app will be run using page size compatible mode. For best compatibility, please recompile the application with 16 KB support. + For more information, see <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a></string> + <!-- Displayed to tell the user that caller ID is not provisioned for their SIM. --> <string name="serviceNotProvisioned">Service not provisioned.</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 0622d7224411..2f82011726ec 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3312,6 +3312,11 @@ <java-symbol type="string" name="language_selection_title" /> <java-symbol type="string" name="search_language_hint" /> + <!-- Strings for page size app compat dialog --> + <java-symbol type="string" name="page_size_compat_apk_warning" /> + <java-symbol type="string" name="page_size_compat_elf_warning" /> + <java-symbol type="string" name="page_size_compat_apk_and_elf_warning" /> + <!-- Work profile unlaunchable app alert dialog--> <java-symbol type="style" name="AlertDialogWithEmergencyButton"/> <java-symbol type="string" name="work_mode_emergency_call_button" /> diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 715633410575..442db10ab039 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -5875,6 +5875,67 @@ public class PackageManagerService implements PackageSender, TestUtilityService userId, callingPackage); } + @Override + public void setPageSizeAppCompatFlagsSettingsOverride(String packageName, boolean enabled) { + final int callingUid = Binder.getCallingUid(); + final int callingAppId = UserHandle.getAppId(callingUid); + + if (!PackageManagerServiceUtils.isSystemOrRoot(callingAppId)) { + throw new SecurityException("Caller must be the system or root."); + } + + int settingsMode = enabled + ? ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_ENABLED + : ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_DISABLED; + PackageStateMutator.Result result = + commitPackageStateMutation( + null, + packageName, + packageState -> + packageState + .setPageSizeAppCompatFlags(settingsMode)); + if (result.isSpecificPackageNull()) { + throw new IllegalArgumentException("Unknown package: " + packageName); + } + scheduleWriteSettings(); + } + + @Override + public boolean isPageSizeCompatEnabled(String packageName) { + final int callingUid = Binder.getCallingUid(); + final int callingAppId = UserHandle.getAppId(callingUid); + final int userId = UserHandle.getCallingUserId(); + + if (!PackageManagerServiceUtils.isSystemOrRoot(callingAppId)) { + throw new SecurityException("Caller must be the system or root."); + } + + PackageStateInternal packageState = + snapshotComputer().getPackageStateForInstalledAndFiltered( + packageName, callingUid, userId); + + return packageState == null ? false : packageState.isPageSizeAppCompatEnabled(); + } + + @Override + public String getPageSizeCompatWarningMessage(String packageName) { + final int callingUid = Binder.getCallingUid(); + final int callingAppId = UserHandle.getAppId(callingUid); + final int userId = UserHandle.getCallingUserId(); + + if (!PackageManagerServiceUtils.isSystemOrRoot(callingAppId)) { + throw new SecurityException("Caller must be the system or root."); + } + + PackageStateInternal packageState = + snapshotComputer().getPackageStateForInstalledAndFiltered( + packageName, callingUid, userId); + + return packageState == null + ? null + : packageState.getPageSizeCompatWarningMessage(mContext); + } + @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USERS) @Override public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 9428de700385..fb16b862b275 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -27,6 +27,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.ComponentName; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.SharedLibraryInfo; @@ -221,6 +222,8 @@ public class PackageSetting extends SettingBase implements PackageStateInternal /** @see PackageState#getCategoryOverride() */ private int categoryOverride = ApplicationInfo.CATEGORY_UNDEFINED; + private int mPageSizeAppCompatFlags = ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED; + @NonNull private final PackageStateUnserialized pkgState = new PackageStateUnserialized(this); @@ -863,6 +866,8 @@ public class PackageSetting extends SettingBase implements PackageStateInternal } copyMimeGroups(other.mimeGroups); + mPageSizeAppCompatFlags = other.mPageSizeAppCompatFlags; + pkgState.updateFrom(other.pkgState); onChanged(); } @@ -1617,6 +1622,34 @@ public class PackageSetting extends SettingBase implements PackageStateInternal return this; } + /** + * @see Set page size app compat mode. + */ + public PackageSetting setPageSizeAppCompatFlags(int mode) { + if (mode < 0 || mode >= ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_MAX) { + throw new IllegalArgumentException("Invalid page size compat mode specified"); + } + + // OR assignment is used here to avoid overriding the mode set by the manifest. + this.mPageSizeAppCompatFlags |= mode; + + // Only one bit of the following can be set at same time. Both are needed to detect app + // compat 'disabled' state from settings vs bit was never set. + if (ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_ENABLED == mode) { + this.mPageSizeAppCompatFlags &= + ~ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_DISABLED; + } else if (ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_DISABLED == mode) { + this.mPageSizeAppCompatFlags &= + ~ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_ENABLED; + } + onChanged(); + return this; + } + + public int getPageSizeAppCompatFlags() { + return mPageSizeAppCompatFlags; + } + public PackageSetting setLegacyNativeLibraryPath( String legacyNativeLibraryPathString) { this.legacyNativeLibraryPath = legacyNativeLibraryPathString; @@ -1787,6 +1820,63 @@ public class PackageSetting extends SettingBase implements PackageStateInternal return getBoolean(Booleans.SCANNED_AS_STOPPED_SYSTEM_APP); } + /** Returns true if ELF files will be loaded in Page size compatibility mode */ + @Override + public boolean isPageSizeAppCompatEnabled() { + // If manifest or settings has disabled the compat mode, don't run app in compat mode. + boolean manifestOverrideDisabled = (mPageSizeAppCompatFlags + & ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_MANIFEST_OVERRIDE_DISABLED) != 0; + boolean settingsOverrideDisabled = (mPageSizeAppCompatFlags + & ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_DISABLED) != 0; + if (manifestOverrideDisabled || settingsOverrideDisabled) { + return false; + } + + int mask = + ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_ELF_NOT_ALIGNED + | ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_MANIFEST_OVERRIDE_ENABLED + | ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_SETTINGS_OVERRIDE_ENABLED; + return (mPageSizeAppCompatFlags & mask) != 0; + } + + /** + * Returns dialog string based on alignment of uncompressed shared libs inside the APK and ELF + * alignment. + */ + @Override + public String getPageSizeCompatWarningMessage(Context context) { + boolean manifestOverrideEnabled = (mPageSizeAppCompatFlags + & ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_MANIFEST_OVERRIDE_ENABLED) != 0; + boolean settingsOverrideEnabled = (mPageSizeAppCompatFlags + & ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_MANIFEST_OVERRIDE_ENABLED) != 0; + if (manifestOverrideEnabled || settingsOverrideEnabled) { + return null; + } + + boolean uncompressedLibsNotAligned = (mPageSizeAppCompatFlags + & ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_UNCOMPRESSED_LIBS_NOT_ALIGNED) != 0; + boolean elfNotAligned = (mPageSizeAppCompatFlags + & ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_ELF_NOT_ALIGNED) != 0; + + if (uncompressedLibsNotAligned && elfNotAligned) { + return context.getText( + com.android.internal.R.string.page_size_compat_apk_and_elf_warning) + .toString(); + } + + if (uncompressedLibsNotAligned) { + return context.getText(com.android.internal.R.string.page_size_compat_apk_warning) + .toString(); + } + + if (elfNotAligned) { + return context.getText(com.android.internal.R.string.page_size_compat_elf_warning) + .toString(); + } + + return null; + } + // Code below generated by codegen v1.0.23. @@ -1952,7 +2042,6 @@ public class PackageSetting extends SettingBase implements PackageStateInternal @Deprecated private void __metadata() {} - //@formatter:on // End of generated code diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 1f672a093b38..485a28070bc5 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3313,6 +3313,11 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile if (pkg.getBaseRevisionCode() != 0) { serializer.attributeInt(null, "baseRevisionCode", pkg.getBaseRevisionCode()); } + if (pkg.getPageSizeAppCompatFlags() + != ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED) { + serializer.attributeInt(null, "pageSizeCompat", pkg.getPageSizeAppCompatFlags()); + } + serializer.attributeFloat(null, "loadingProgress", pkg.getLoadingProgress()); serializer.attributeLongHex(null, "loadingCompletedTime", pkg.getLoadingCompletedTime()); @@ -4129,6 +4134,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile boolean isScannedAsStoppedSystemApp = false; boolean isSdkLibrary = false; int baseRevisionCode = 0; + int PageSizeCompat = 0; try { name = parser.getAttributeValue(null, ATTR_NAME); realName = parser.getAttributeValue(null, "realName"); @@ -4175,6 +4181,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile appMetadataSource = parser.getAttributeInt(null, "appMetadataSource", PackageManager.APP_METADATA_SOURCE_UNKNOWN); baseRevisionCode = parser.getAttributeInt(null, "baseRevisionCode", 0); + PageSizeCompat = parser.getAttributeInt(null, "pageSizeCompat", + ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED); isScannedAsStoppedSystemApp = parser.getAttributeBoolean(null, "scannedAsStoppedSystemApp", false); @@ -4330,7 +4338,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile .setTargetSdkVersion(targetSdkVersion) .setBaseRevisionCode(baseRevisionCode) .setRestrictUpdateHash(restrictUpdateHash) - .setScannedAsStoppedSystemApp(isScannedAsStoppedSystemApp); + .setScannedAsStoppedSystemApp(isScannedAsStoppedSystemApp) + .setPageSizeAppCompatFlags(PageSizeCompat); // Handle legacy string here for single-user mode final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED); if (enabledStr != null) { @@ -5211,6 +5220,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile pw.print(" (override=true)"); } pw.println(); + pw.print(prefix); + pw.print(" pageSizeCompat="); + pw.print(ps.getPageSizeAppCompatFlags()); + pw.println(); if (!ps.getPkg().getQueriesPackages().isEmpty()) { pw.append(prefix).append(" queriesPackages=") .println(ps.getPkg().getQueriesPackages()); diff --git a/services/core/java/com/android/server/pm/pkg/PackageState.java b/services/core/java/com/android/server/pm/pkg/PackageState.java index bbc17c83cfac..33fc066a62ee 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageState.java +++ b/services/core/java/com/android/server/pm/pkg/PackageState.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.annotation.Size; import android.annotation.SystemApi; import android.annotation.UserIdInt; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -198,6 +199,21 @@ public interface PackageState { int getCategoryOverride(); /** + * Returns true if ELF files will be loaded in Page size compatibility mode + * + * @hide + */ + boolean isPageSizeAppCompatEnabled(); + + /** + * Returns dialog string based on alignment of uncompressed shared libs inside the APK and ELF + * alignment. + * + * @hide + */ + String getPageSizeCompatWarningMessage(Context context); + + /** * The install time CPU override, if any. This value is written at install time * and doesn't change during the life of an install. If non-null, * {@link #getPrimaryCpuAbiLegacy()} will also contain the same value. diff --git a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java index 253eb4006122..a46c4a695d60 100644 --- a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java +++ b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java @@ -257,6 +257,16 @@ public class PackageStateMutator { @NonNull @Override + public PackageStateWrite setPageSizeAppCompatFlags( + @ApplicationInfo.PageSizeAppCompatFlags int mode) { + if (mState != null) { + mState.setPageSizeAppCompatFlags(mode); + } + return this; + } + + @NonNull + @Override public PackageStateWrite setUpdateAvailable(boolean updateAvailable) { if (mState != null) { mState.setUpdateAvailable(updateAvailable); diff --git a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java index 55d96f3aee08..f8f8695b2832 100644 --- a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java +++ b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java @@ -46,6 +46,10 @@ public interface PackageStateWrite { @NonNull PackageStateWrite setCategoryOverride(@ApplicationInfo.Category int category); + /** set 16Kb App compat mode. @see ApplicationInfo.PageSizeAppCompatFlags */ + @NonNull + PackageStateWrite setPageSizeAppCompatFlags(@ApplicationInfo.PageSizeAppCompatFlags int mode); + @NonNull PackageStateWrite setUpdateAvailable(boolean updateAvailable); diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt index 3fdb53f5ab59..31f03704a756 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt @@ -289,6 +289,7 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag AndroidPackage::getEmergencyInstaller, AndroidPackage::isAllowCrossUidActivitySwitchFromBelow, AndroidPackage::getIntentMatchingFlags, + AndroidPackage::getPageSizeAppCompatFlags, ) override fun extraParams() = listOf( |