diff options
30 files changed, 813 insertions, 129 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 93cb7e45a047..c89d690f211f 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -32238,6 +32238,7 @@ package android.os { field public static final String DISALLOW_BLUETOOTH = "no_bluetooth"; field public static final String DISALLOW_BLUETOOTH_SHARING = "no_bluetooth_sharing"; field public static final String DISALLOW_CAMERA_TOGGLE = "disallow_camera_toggle"; + field public static final String DISALLOW_CELLULAR_2G = "no_cellular_2g"; field public static final String DISALLOW_CHANGE_WIFI_STATE = "no_change_wifi_state"; field public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth"; field public static final String DISALLOW_CONFIG_BRIGHTNESS = "no_config_brightness"; diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 563ab8149bd1..068b40ad5270 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -339,10 +339,6 @@ package android.os { method public boolean shouldBypassCache(@NonNull Q); } - public interface Parcelable { - method public default int getStability(); - } - public class Process { method public static final int getAppUidForSdkSandboxUid(int); method public static final boolean isSdkSandboxUid(int); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index e6555ddfa0cf..4a0d7711769d 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -9554,6 +9554,7 @@ package android.os { } public interface Parcelable { + method public default int getStability(); field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0 field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1 } @@ -9562,7 +9563,6 @@ package android.os { ctor public ParcelableHolder(int); method public int describeContents(); method @Nullable public <T extends android.os.Parcelable> T getParcelable(@NonNull Class<T>); - method public int getStability(); method public void readFromParcel(@NonNull android.os.Parcel); method public void setParcelable(@Nullable android.os.Parcelable); method public void writeToParcel(@NonNull android.os.Parcel, int); @@ -13553,6 +13553,7 @@ package android.telephony { field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; field public static final int ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G = 3; // 0x3 field public static final int ALLOWED_NETWORK_TYPES_REASON_POWER = 1; // 0x1 + field public static final int ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS = 4; // 0x4 field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2 field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1 field public static final int CALL_WAITING_STATUS_FDN_CHECK_FAILURE = 5; // 0x5 diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index da18e19d6812..6d5c741e7dc7 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -1219,25 +1219,40 @@ public class Binder implements IBinder { @UnsupportedAppUsage private boolean execTransact(int code, long dataObj, long replyObj, int flags) { + + Parcel data = Parcel.obtain(dataObj); + Parcel reply = Parcel.obtain(replyObj); + // At that point, the parcel request headers haven't been parsed so we do not know what // {@link WorkSource} the caller has set. Use calling UID as the default. - final int callingUid = Binder.getCallingUid(); - final long origWorkSource = ThreadLocalWorkSource.setUid(callingUid); + // + // TODO: this is wrong - we should attribute along the entire call route + // also this attribution logic should move to native code - it only works + // for Java now + // + // This attribution support is not generic and therefore not support in RPC mode + final int callingUid = data.isForRpc() ? -1 : Binder.getCallingUid(); + final long origWorkSource = callingUid == -1 + ? -1 : ThreadLocalWorkSource.setUid(callingUid); + try { - return execTransactInternal(code, dataObj, replyObj, flags, callingUid); + return execTransactInternal(code, data, reply, flags, callingUid); } finally { - ThreadLocalWorkSource.restore(origWorkSource); + reply.recycle(); + data.recycle(); + + if (callingUid != -1) { + ThreadLocalWorkSource.restore(origWorkSource); + } } } - private boolean execTransactInternal(int code, long dataObj, long replyObj, int flags, + private boolean execTransactInternal(int code, Parcel data, Parcel reply, int flags, int callingUid) { // Make sure the observer won't change while processing a transaction. final BinderInternal.Observer observer = sObserver; final CallSession callSession = observer != null ? observer.callStarted(this, code, UNSET_WORKSOURCE) : null; - Parcel data = Parcel.obtain(dataObj); - Parcel reply = Parcel.obtain(replyObj); // Theoretically, we should call transact, which will call onTransact, // but all that does is rewind it, and we just got these from an IPC, // so we'll just call it directly. @@ -1268,8 +1283,10 @@ public class Binder implements IBinder { final boolean tracingEnabled = tagEnabled && transactionTraceName != null; try { + // TODO - this logic should not be in Java - it should be in native + // code in libbinder so that it works for all binder users. final BinderCallHeavyHitterWatcher heavyHitterWatcher = sHeavyHitterWatcher; - if (heavyHitterWatcher != null) { + if (heavyHitterWatcher != null && callingUid != -1) { // Notify the heavy hitter watcher, if it's enabled. heavyHitterWatcher.onTransaction(callingUid, getClass(), code); } @@ -1277,7 +1294,10 @@ public class Binder implements IBinder { Trace.traceBegin(Trace.TRACE_TAG_AIDL, transactionTraceName); } - if ((flags & FLAG_COLLECT_NOTED_APP_OPS) != 0) { + // TODO - this logic should not be in Java - it should be in native + // code in libbinder so that it works for all binder users. Further, + // this should not re-use flags. + if ((flags & FLAG_COLLECT_NOTED_APP_OPS) != 0 && callingUid != -1) { AppOpsManager.startNotedAppOpsCollection(callingUid); try { res = onTransact(code, data, reply, flags); @@ -1320,8 +1340,6 @@ public class Binder implements IBinder { } checkParcel(this, code, reply, "Unreasonably large binder reply buffer"); - reply.recycle(); - data.recycle(); } // Just in case -- we are done with the IPC, so there should be no more strict diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index cb7e6f71a8fd..20602ce3dca2 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -107,20 +107,42 @@ public class GraphicsEnvironment { private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER = 2; private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_OFF = 3; + // System properties related to ANGLE and legacy GLES graphics drivers. + private static final String PROPERTY_EGL_SYSTEM_DRIVER = "ro.hardware.egl"; + // TODO (b/224558229): Properly add this to the list of system properties for a device: + private static final String PROPERTY_EGL_LEGACY_DRIVER = "ro.hardware.egl_legacy"; + // Values for ANGLE_GL_DRIVER_ALL_ANGLE private static final int ANGLE_GL_DRIVER_ALL_ANGLE_ON = 1; private static final int ANGLE_GL_DRIVER_ALL_ANGLE_OFF = 0; + private static final int ANGLE_GL_DRIVER_ALL_LEGACY = -1; // Values for ANGLE_GL_DRIVER_SELECTION_VALUES private static final String ANGLE_GL_DRIVER_CHOICE_DEFAULT = "default"; private static final String ANGLE_GL_DRIVER_CHOICE_ANGLE = "angle"; + private static final String ANGLE_GL_DRIVER_CHOICE_LEGACY = "legacy"; + // The following value is a deprecated choice for "legacy" private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native"; + // Values returned by getDriverForPackage() and getDefaultDriverToUse() (avoid returning + // strings for performance reasons) + private static final int ANGLE_GL_DRIVER_TO_USE_LEGACY = 0; + private static final int ANGLE_GL_DRIVER_TO_USE_ANGLE = 1; + private ClassLoader mClassLoader; private String mLibrarySearchPaths; private String mLibraryPermittedPaths; private GameManager mGameManager; + private boolean mAngleIsSystemDriver = false; + private boolean mNoLegacyDriver = false; + // When ANGLE is the system driver, this is the name of the legacy driver. + // + // IMPORTANT: When ANGLE is the system driver, and if there is a fallback "legacy" GLES driver + // (e.g. from the GPU provider), the name of that driver must be set here, unles and until + // PROPERTY_EGL_LEGACY_DRIVER has been properly plumbed and this becomes broadly available. + private String mEglLegacyDriver = ""; + private int mAngleOptInIndex = -1; /** @@ -138,6 +160,23 @@ public class GraphicsEnvironment { setupGpuLayers(context, coreSettings, pm, packageName, appInfoWithMetaData); Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); + // Determine if ANGLE is the system driver, as this will determine other logic + final String eglSystemDriver = SystemProperties.get(PROPERTY_EGL_SYSTEM_DRIVER); + Log.v(TAG, "GLES system driver is '" + eglSystemDriver + "'"); + mAngleIsSystemDriver = eglSystemDriver.equals(ANGLE_DRIVER_NAME); + if (mAngleIsSystemDriver) { + // Lookup the legacy driver, to send down to the EGL loader + final String eglLegacyDriver = SystemProperties.get(PROPERTY_EGL_LEGACY_DRIVER); + if (eglLegacyDriver.isEmpty()) { + mNoLegacyDriver = true; + mEglLegacyDriver = eglSystemDriver; + } + } else { + mEglLegacyDriver = eglSystemDriver; + } + Log.v(TAG, "Legacy GLES driver is '" + mEglLegacyDriver + "'"); + + // Setup ANGLE and pass down ANGLE details to the C++ code Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupAngle"); boolean useAngle = false; if (setupAngle(context, coreSettings, pm, packageName)) { @@ -145,6 +184,9 @@ public class GraphicsEnvironment { useAngle = true; setGpuStats(ANGLE_DRIVER_NAME, ANGLE_DRIVER_VERSION_NAME, ANGLE_DRIVER_VERSION_CODE, 0, packageName, getVulkanVersion(pm)); + } else if (mNoLegacyDriver) { + Log.e(TAG, "Unexpected problem with the ANGLE for use with: '" + packageName + "'"); + useAngle = true; } } Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); @@ -188,28 +230,15 @@ public class GraphicsEnvironment { /** * Query to determine if ANGLE should be used */ - private boolean shouldUseAngle(Context context, Bundle coreSettings, - String packageName) { + private boolean shouldUseAngle(Context context, Bundle coreSettings, String packageName) { if (TextUtils.isEmpty(packageName)) { - Log.v(TAG, "No package name specified, ANGLE should not be used"); - return false; + Log.v(TAG, "No package name specified; use the system driver"); + return mAngleIsSystemDriver ? true : false; } - final String devOptIn = getDriverForPackage(context, coreSettings, packageName); - Log.v(TAG, "ANGLE Developer option for '" + packageName + "' " - + "set to: '" + devOptIn + "'"); - - // We only want to use ANGLE if the developer has explicitly chosen something other than - // default driver. - final boolean forceAngle = devOptIn.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE); - final boolean forceNative = devOptIn.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE); - if (forceAngle || forceNative) { - Log.v(TAG, "ANGLE developer option for " + packageName + ": " + devOptIn); - } - - final boolean gameModeEnabledAngle = isAngleEnabledByGameMode(context, packageName); - - return !forceNative && (forceAngle || gameModeEnabledAngle); + final int driverToUse = getDriverForPackage(context, coreSettings, packageName); + boolean yesOrNo = driverToUse == ANGLE_GL_DRIVER_TO_USE_ANGLE; + return yesOrNo; } private int getVulkanVersion(PackageManager pm) { @@ -417,34 +446,69 @@ public class GraphicsEnvironment { return ai; } - private String getDriverForPackage(Context context, Bundle bundle, String packageName) { + /** + * Return the appropriate "default" driver, unless overridden by isAngleEnabledByGameMode(). + */ + private int getDefaultDriverToUse(Context context, String packageName) { + if (mAngleIsSystemDriver || isAngleEnabledByGameMode(context, packageName)) { + return ANGLE_GL_DRIVER_TO_USE_ANGLE; + } else { + return ANGLE_GL_DRIVER_TO_USE_LEGACY; + } + } + + /* + * Determine which GLES "driver" should be used for the package, taking into account the + * following factors (in priority order): + * + * 1) The semi-global switch (i.e. Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE; which is set by + * the "angle_gl_driver_all_angle" setting; which forces a driver for all processes that + * start after the Java run time is up), if it forces a choice; otherwise ... + * 2) The per-application switch (i.e. Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS and + * Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES; which corresponds to the + * “angle_gl_driver_selection_pkgs” and “angle_gl_driver_selection_values” settings); if it + * forces a choice; otherwise ... + * 3) Use ANGLE if isAngleEnabledByGameMode() returns true; otherwise ... + * 4) The global switch (i.e. use the system driver, whether ANGLE or legacy; + * a.k.a. mAngleIsSystemDriver, which is set by the device’s “ro.hardware.egl” property) + * + * Factors 1 and 2 are decided by this method. Factors 3 and 4 are decided by + * getDefaultDriverToUse(). + */ + private int getDriverForPackage(Context context, Bundle bundle, String packageName) { + // Check the semi-global switch (i.e. once system has booted enough) for whether ANGLE + // should be forced on or off for "all appplications" final int allUseAngle; if (bundle != null) { - allUseAngle = - bundle.getInt(Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE); + allUseAngle = bundle.getInt(Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE); } else { ContentResolver contentResolver = context.getContentResolver(); allUseAngle = Settings.Global.getInt(contentResolver, - Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE, - ANGLE_GL_DRIVER_ALL_ANGLE_OFF); + Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE, ANGLE_GL_DRIVER_ALL_ANGLE_OFF); } if (allUseAngle == ANGLE_GL_DRIVER_ALL_ANGLE_ON) { Log.v(TAG, "Turn on ANGLE for all applications."); - return ANGLE_GL_DRIVER_CHOICE_ANGLE; + return ANGLE_GL_DRIVER_TO_USE_ANGLE; + } + if (allUseAngle == ANGLE_GL_DRIVER_ALL_LEGACY) { + Log.v(TAG, "Disable ANGLE for all applications."); + return ANGLE_GL_DRIVER_TO_USE_LEGACY; } // Make sure we have a good package name if (TextUtils.isEmpty(packageName)) { - return ANGLE_GL_DRIVER_CHOICE_DEFAULT; + return getDefaultDriverToUse(context, packageName); } + // Get the per-application settings lists final ContentResolver contentResolver = context.getContentResolver(); - final List<String> optInPackages = - getGlobalSettingsString(contentResolver, bundle, - Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS); - final List<String> optInValues = - getGlobalSettingsString(contentResolver, bundle, - Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES); + final List<String> optInPackages = getGlobalSettingsString( + contentResolver, bundle, Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS); + final List<String> optInValues = getGlobalSettingsString( + contentResolver, bundle, Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES); + Log.v(TAG, "Currently set values for:"); + Log.v(TAG, " angle_gl_driver_selection_pkgs = " + optInPackages); + Log.v(TAG, " angle_gl_driver_selection_values =" + optInValues); // Make sure we have good settings to use if (optInPackages.size() != optInValues.size()) { @@ -454,17 +518,40 @@ public class GraphicsEnvironment { + optInPackages.size() + ", " + "number of values: " + optInValues.size()); - return ANGLE_GL_DRIVER_CHOICE_DEFAULT; + return getDefaultDriverToUse(context, packageName); } + // See if this application is listed in the per-application settings lists final int pkgIndex = getPackageIndex(packageName, optInPackages); if (pkgIndex < 0) { - return ANGLE_GL_DRIVER_CHOICE_DEFAULT; + // The application is NOT listed in the per-application settings lists; and so use the + // system driver (i.e. either ANGLE or the Legacy driver) + Log.v(TAG, "getDriverForPackage(): No per-application setting"); + return getDefaultDriverToUse(context, packageName); } mAngleOptInIndex = pkgIndex; - return optInValues.get(pkgIndex); + Log.v(TAG, + "getDriverForPackage(): using per-application switch: " + + optInValues.get(pkgIndex)); + // The application IS listed in the per-application settings lists; and so use the + // setting--choosing the current system driver if the setting is "default" (i.e. either + // ANGLE or the Legacy driver) + String rtnValue = optInValues.get(pkgIndex); + Log.v(TAG, + "ANGLE Developer option for '" + packageName + "' " + + "set to: '" + rtnValue + "'"); + if (rtnValue.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE)) { + return ANGLE_GL_DRIVER_TO_USE_ANGLE; + } else if (rtnValue.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE) + || rtnValue.equals(ANGLE_GL_DRIVER_CHOICE_LEGACY)) { + return ANGLE_GL_DRIVER_TO_USE_LEGACY; + } else { + // The user either chose default or an invalid value; go with the default driver or what + // the game dashboard indicates + return getDefaultDriverToUse(context, packageName); + } } /** @@ -514,7 +601,13 @@ public class GraphicsEnvironment { } /** - * Pass ANGLE details down to trigger enable logic + * Determine whether ANGLE should be used, set it up if so, and pass ANGLE details down to + * the C++ GraphicsEnv class. + * + * If ANGLE will be used, GraphicsEnv::setAngleInfo() will be called to enable ANGLE to be + * properly used. Otherwise, GraphicsEnv::setLegacyDriverInfo() will be called to + * enable the legacy GLES driver (e.g. when ANGLE is the system driver) to be identified and + * used. * * @param context * @param bundle @@ -527,6 +620,7 @@ public class GraphicsEnvironment { String packageName) { if (!shouldUseAngle(context, bundle, packageName)) { + setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver); return false; } @@ -541,6 +635,7 @@ public class GraphicsEnvironment { angleInfo = pm.getApplicationInfo(anglePkgName, 0); } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "ANGLE debug package '" + anglePkgName + "' not installed"); + setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver); return false; } } @@ -550,16 +645,18 @@ public class GraphicsEnvironment { anglePkgName = getAnglePackageName(pm); if (TextUtils.isEmpty(anglePkgName)) { Log.w(TAG, "Failed to find ANGLE package."); + setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver); return false; } - Log.i(TAG, "ANGLE package enabled: " + anglePkgName); + Log.v(TAG, "ANGLE package enabled: " + anglePkgName); try { // Production ANGLE libraries must be pre-installed as a system app angleInfo = pm.getApplicationInfo(anglePkgName, PackageManager.MATCH_SYSTEM_ONLY); } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "ANGLE package '" + anglePkgName + "' not installed"); + setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver); return false; } } @@ -573,21 +670,15 @@ public class GraphicsEnvironment { + "!/lib/" + abi; - if (DEBUG) Log.v(TAG, "ANGLE package libs: " + paths); + if (DEBUG) { + Log.v(TAG, "ANGLE package libs: " + paths); + } - // We need to call setAngleInfo() with the package name and the developer option value - //(native/angle/other). Then later when we are actually trying to load a driver, - //GraphicsEnv::getShouldUseAngle() has seen the package name before and can confidently - //answer yes/no based on the previously set developer option value. - final String devOptIn; + // If we make it to here, ANGLE will be used. Call setAngleInfo() with the package name, + // and features to use. final String[] features = getAngleEglFeatures(context, bundle); - final boolean gameModeEnabledAngle = isAngleEnabledByGameMode(context, packageName); - if (gameModeEnabledAngle) { - devOptIn = ANGLE_GL_DRIVER_CHOICE_ANGLE; - } else { - devOptIn = getDriverForPackage(context, bundle, packageName); - } - setAngleInfo(paths, packageName, devOptIn, features); + setAngleInfo( + paths, packageName, mAngleIsSystemDriver, ANGLE_GL_DRIVER_CHOICE_ANGLE, features); return true; } @@ -876,8 +967,10 @@ public class GraphicsEnvironment { private static native void setDriverPathAndSphalLibraries(String path, String sphalLibraries); private static native void setGpuStats(String driverPackageName, String driverVersionName, long driverVersionCode, long driverBuildTime, String appPackageName, int vulkanVersion); - private static native void setAngleInfo(String path, String appPackage, String devOptIn, - String[] features); + private static native void setAngleInfo(String path, String appPackage, + boolean angleIsSystemDriver, String devOptIn, String[] features); + private static native void setLegacyDriverInfo( + String appPackage, boolean angleIsSystemDriver, String legacyDriverName); private static native boolean getShouldUseAngle(String packageName); private static native boolean setInjectLayersPrSetDumpable(); diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index a6ae663dabb0..7e15f07be05a 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -368,6 +368,8 @@ public final class Parcel { @FastNative private static native void nativeMarkForBinder(long nativePtr, IBinder binder); @CriticalNative + private static native boolean nativeIsForRpc(long nativePtr); + @CriticalNative private static native int nativeDataSize(long nativePtr); @CriticalNative private static native int nativeDataAvail(long nativePtr); @@ -560,9 +562,11 @@ public final class Parcel { */ public final void recycle() { if (mRecycled) { - Log.w(TAG, "Recycle called on unowned Parcel. (recycle twice?) Here: " + Log.wtf(TAG, "Recycle called on unowned Parcel. (recycle twice?) Here: " + Log.getStackTraceString(new Throwable()) + " Original recycle call (if DEBUG_RECYCLE): ", mStack); + + return; } mRecycled = true; @@ -645,6 +649,15 @@ public final class Parcel { nativeMarkForBinder(mNativePtr, binder); } + /** + * Whether this Parcel is written for an RPC transaction. + * + * @hide + */ + public final boolean isForRpc() { + return nativeIsForRpc(mNativePtr); + } + /** @hide */ @ParcelFlags @TestApi diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java index 8a8045714d46..a2b0486c1df5 100644 --- a/core/java/android/os/Parcelable.java +++ b/core/java/android/os/Parcelable.java @@ -188,7 +188,7 @@ public interface Parcelable { * @return true if this parcelable is stable. * @hide */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS) default @Stability int getStability() { return PARCELABLE_STABILITY_LOCAL; } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 0ffdfc6cbcb1..4b9f8921d34f 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1485,6 +1485,22 @@ public class UserManager { public static final String KEY_RESTRICTIONS_PENDING = "restrictions_pending"; /** + * Specifies if a user is not allowed to use 2g networks. + * + * <p>This restriction can only be set by a device owner or a profile owner of an + * organization-owned managed profile on the parent profile. + * In all cases, the setting applies globally on the device and will prevent the device from + * scanning for or connecting to 2g networks, except in the case of an emergency. + * + * <p>The default value is <code>false</code>. + * + * @see DevicePolicyManager#addUserRestriction(ComponentName, String) + * @see DevicePolicyManager#clearUserRestriction(ComponentName, String) + * @see #getUserRestrictions() + */ + public static final String DISALLOW_CELLULAR_2G = "no_cellular_2g"; + + /** * List of key values that can be passed into the various user restriction related methods * in {@link UserManager} & {@link DevicePolicyManager}. * Note: This is slightly different from the real set of user restrictions listed in {@link @@ -1565,6 +1581,7 @@ public class UserManager { DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI, DISALLOW_WIFI_DIRECT, DISALLOW_ADD_WIFI_CONFIG, + DISALLOW_CELLULAR_2G, }) @Retention(RetentionPolicy.SOURCE) public @interface UserRestrictionKey {} diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index df6b827f5cb3..ba7df25c5d7c 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -14410,6 +14410,18 @@ public final class Settings { public static final String ANGLE_EGL_FEATURES = "angle_egl_features"; /** + * Comma-separated list of package names that ANGLE may have issues with + * @hide + */ + public static final String ANGLE_DEFERLIST = "angle_deferlist"; + + /** + * Integer mode of the logic for applying `angle_deferlist` + * @hide + */ + public static final String ANGLE_DEFERLIST_MODE = "angle_deferlist_mode"; + + /** * Show the "ANGLE In Use" dialog box to the user when ANGLE is the OpenGL driver. * The value is a boolean (1 or 0). * @hide diff --git a/core/java/com/android/internal/security/TEST_MAPPING b/core/java/com/android/internal/security/TEST_MAPPING index 9a5e90e8681f..803760c55e71 100644 --- a/core/java/com/android/internal/security/TEST_MAPPING +++ b/core/java/com/android/internal/security/TEST_MAPPING @@ -1,6 +1,17 @@ { "presubmit": [ { + "name": "FrameworksCoreTests", + "options": [ + { + "include-filter": "com.android.internal.security." + }, + { + "include-annotation": "android.platform.test.annotations.Presubmit" + } + ] + }, + { "name": "ApkVerityTest", "file_patterns": ["VerityUtils\\.java"] } diff --git a/core/java/com/android/internal/security/VerityUtils.java b/core/java/com/android/internal/security/VerityUtils.java index 76f7b2180b34..7f45c098daba 100644 --- a/core/java/com/android/internal/security/VerityUtils.java +++ b/core/java/com/android/internal/security/VerityUtils.java @@ -23,10 +23,28 @@ import android.system.Os; import android.system.OsConstants; import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import com.android.internal.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import com.android.internal.org.bouncycastle.cms.CMSException; +import com.android.internal.org.bouncycastle.cms.CMSProcessableByteArray; +import com.android.internal.org.bouncycastle.cms.CMSSignedData; +import com.android.internal.org.bouncycastle.cms.SignerInformation; +import com.android.internal.org.bouncycastle.cms.SignerInformationVerifier; +import com.android.internal.org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import com.android.internal.org.bouncycastle.operator.OperatorCreationException; + import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; /** Provides fsverity related operations. */ public abstract class VerityUtils { @@ -90,8 +108,100 @@ public abstract class VerityUtils { return (retval == 1); } - /** Returns hash of a root node for the fs-verity enabled file. */ - public static byte[] getFsverityRootHash(@NonNull String filePath) { + /** + * Verifies the signature over the fs-verity digest using the provided certificate. + * + * This method should only be used by any existing fs-verity use cases that require + * PKCS#7 signature verification, if backward compatibility is necessary. + * + * Since PKCS#7 is too flexible, for the current specific need, only specific configuration + * will be accepted: + * <ul> + * <li>Must use SHA256 as the digest algorithm + * <li>Must use rsaEncryption as signature algorithm + * <li>Must be detached / without content + * <li>Must not include any signed or unsigned attributes + * </ul> + * + * It is up to the caller to provide an appropriate/trusted certificate. + * + * @param signatureBlock byte array of a PKCS#7 detached signature + * @param digest fs-verity digest with the common configuration using sha256 + * @param derCertInputStream an input stream of a X.509 certificate in DER + * @return whether the verification succeeds + */ + public static boolean verifyPkcs7DetachedSignature(@NonNull byte[] signatureBlock, + @NonNull byte[] digest, @NonNull InputStream derCertInputStream) { + if (digest.length != 32) { + Slog.w(TAG, "Only sha256 is currently supported"); + return false; + } + + try { + CMSSignedData signedData = new CMSSignedData( + new CMSProcessableByteArray(toFormattedDigest(digest)), + signatureBlock); + + if (!signedData.isDetachedSignature()) { + Slog.w(TAG, "Expect only detached siganture"); + return false; + } + if (!signedData.getCertificates().getMatches(null).isEmpty()) { + Slog.w(TAG, "Expect no certificate in signature"); + return false; + } + if (!signedData.getCRLs().getMatches(null).isEmpty()) { + Slog.w(TAG, "Expect no CRL in signature"); + return false; + } + + X509Certificate trustedCert = (X509Certificate) CertificateFactory.getInstance("X.509") + .generateCertificate(derCertInputStream); + SignerInformationVerifier verifier = new JcaSimpleSignerInfoVerifierBuilder() + .build(trustedCert); + + // Verify any signature with the trusted certificate. + for (SignerInformation si : signedData.getSignerInfos().getSigners()) { + // To be the most strict while dealing with the complicated PKCS#7 signature, reject + // everything we don't need. + if (si.getSignedAttributes() != null && si.getSignedAttributes().size() > 0) { + Slog.w(TAG, "Unexpected signed attributes"); + return false; + } + if (si.getUnsignedAttributes() != null && si.getUnsignedAttributes().size() > 0) { + Slog.w(TAG, "Unexpected unsigned attributes"); + return false; + } + if (!NISTObjectIdentifiers.id_sha256.getId().equals(si.getDigestAlgOID())) { + Slog.w(TAG, "Unsupported digest algorithm OID: " + si.getDigestAlgOID()); + return false; + } + if (!PKCSObjectIdentifiers.rsaEncryption.getId().equals(si.getEncryptionAlgOID())) { + Slog.w(TAG, "Unsupported encryption algorithm OID: " + + si.getEncryptionAlgOID()); + return false; + } + + if (si.verify(verifier)) { + return true; + } + } + return false; + } catch (CertificateException | CMSException | OperatorCreationException e) { + Slog.w(TAG, "Error occurred during the PKCS#7 signature verification", e); + } + return false; + } + + /** + * Returns fs-verity digest for the file if enabled, otherwise returns null. The digest is a + * hash of root hash of fs-verity's Merkle tree with extra metadata. + * + * @see <a href="https://www.kernel.org/doc/html/latest/filesystems/fsverity.html#file-digest-computation"> + * File digest computation in Linux kernel documentation</a> + * @return Bytes of fs-verity digest + */ + public static byte[] getFsverityDigest(@NonNull String filePath) { byte[] result = new byte[HASH_SIZE_BYTES]; int retval = measureFsverityNative(filePath, result); if (retval < 0) { @@ -103,6 +213,19 @@ public abstract class VerityUtils { return result; } + /** @hide */ + @VisibleForTesting + public static byte[] toFormattedDigest(byte[] digest) { + // Construct fsverity_formatted_digest used in fs-verity's built-in signature verification. + ByteBuffer buffer = ByteBuffer.allocate(12 + digest.length); // struct size + sha256 size + buffer.order(ByteOrder.LITTLE_ENDIAN); + buffer.put("FSVerity".getBytes(StandardCharsets.US_ASCII)); + buffer.putShort((short) 1); // FS_VERITY_HASH_ALG_SHA256 + buffer.putShort((short) digest.length); + buffer.put(digest); + return buffer.array(); + } + private static native int enableFsverityNative(@NonNull String filePath, @NonNull byte[] pkcs7Signature); private static native int measureFsverityNative(@NonNull String filePath, diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 5498769fcf8f..e032fa2d5547 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -326,7 +326,6 @@ cc_library_shared { header_libs: [ "bionic_libc_platform_headers", "dnsproxyd_protocol_headers", - "libandroid_runtime_vm_headers", ], }, host: { @@ -415,24 +414,3 @@ cc_library_shared { never: true, }, } - -cc_library_headers { - name: "libandroid_runtime_vm_headers", - host_supported: true, - vendor_available: true, - // TODO(b/153609531): remove when libbinder is not native_bridge_supported - native_bridge_supported: true, - // Allow only modules from the following list to create threads that can be - // attached to the JVM. This list should be a subset of the dependencies of - // libandroid_runtime. - visibility: [ - "//frameworks/native/libs/binder", - ], - export_include_dirs: ["include_vm"], - header_libs: [ - "jni_headers", - ], - export_header_lib_headers: [ - "jni_headers", - ], -} diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index eba6cca76389..6a051c39cab0 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -22,7 +22,6 @@ #include <android-base/properties.h> #include <android/graphics/jni_runtime.h> #include <android_runtime/AndroidRuntime.h> -#include <android_runtime/vm.h> #include <assert.h> #include <binder/IBinder.h> #include <binder/IPCThreadState.h> diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index f44e829d49d7..78e2d3164993 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -50,7 +50,7 @@ void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName, } void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, - jstring devOptIn, jobjectArray featuresObj) { + jboolean angleIsSystemDriver, jstring devOptIn, jobjectArray featuresObj) { ScopedUtfChars pathChars(env, path); ScopedUtfChars appNameChars(env, appName); ScopedUtfChars devOptInChars(env, devOptIn); @@ -74,7 +74,18 @@ void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appNa } android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(), - devOptInChars.c_str(), features); + angleIsSystemDriver, devOptInChars.c_str(), + features); +} + +void setLegacyDriverInfo_native(JNIEnv* env, jobject clazz, jstring appName, + jboolean angleIsSystemDriver, jstring legacyDriverName) { + ScopedUtfChars appNameChars(env, appName); + ScopedUtfChars legacyDriverNameChars(env, legacyDriverName); + + android::GraphicsEnv::getInstance().setLegacyDriverInfo(appNameChars.c_str(), + angleIsSystemDriver, + legacyDriverNameChars.c_str()); } bool shouldUseAngle_native(JNIEnv* env, jobject clazz, jstring appName) { @@ -120,8 +131,10 @@ const JNINativeMethod g_methods[] = { {"setInjectLayersPrSetDumpable", "()Z", reinterpret_cast<void*>(setInjectLayersPrSetDumpable_native)}, {"setAngleInfo", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V", + "(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;[Ljava/lang/String;)V", reinterpret_cast<void*>(setAngleInfo_native)}, + {"setLegacyDriverInfo", "(Ljava/lang/String;ZLjava/lang/String;)V", + reinterpret_cast<void*>(setLegacyDriverInfo_native)}, {"getShouldUseAngle", "(Ljava/lang/String;)Z", reinterpret_cast<void*>(shouldUseAngle_native)}, {"setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp index 1f64df49cb56..4d8dac1daaf0 100644 --- a/core/jni/android_os_Parcel.cpp +++ b/core/jni/android_os_Parcel.cpp @@ -116,6 +116,11 @@ static void android_os_Parcel_markForBinder(JNIEnv* env, jclass clazz, jlong nat } } +static jboolean android_os_Parcel_isForRpc(jlong nativePtr) { + Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); + return parcel ? parcel->isForRpc() : false; +} + static jint android_os_Parcel_dataSize(jlong nativePtr) { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); @@ -808,6 +813,8 @@ static const JNINativeMethod gParcelMethods[] = { // @FastNative {"nativeMarkForBinder", "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_markForBinder}, // @CriticalNative + {"nativeIsForRpc", "(J)Z", (void*)android_os_Parcel_isForRpc}, + // @CriticalNative {"nativeDataSize", "(J)I", (void*)android_os_Parcel_dataSize}, // @CriticalNative {"nativeDataAvail", "(J)I", (void*)android_os_Parcel_dataAvail}, diff --git a/core/jni/include_vm/android_runtime/vm.h b/core/jni/include_vm/android_runtime/vm.h deleted file mode 100644 index a6e7c162d6ed..000000000000 --- a/core/jni/include_vm/android_runtime/vm.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#pragma once - -#include <jni.h> - -// Get the Java VM. If the symbol doesn't exist at runtime, it means libandroid_runtime -// is not loaded in the current process. If the symbol exists but it returns nullptr, it -// means JavaVM is not yet started. -extern "C" JavaVM* AndroidRuntimeGetJavaVM(); diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index 3c2a48a51b09..e165b079f450 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -468,6 +468,10 @@ message GlobalSettingsProto { optional SettingProto updatable_driver_prerelease_opt_in_apps = 18; optional SettingProto angle_egl_features = 19; + // ANGLE - List of Apps that ANGLE may have issues with + optional SettingProto angle_deferlist = 20; + // ANGLE - Integer mode of the logic for applying `angle_deferlist` + optional SettingProto angle_deferlist_mode = 21; } optional Gpu gpu = 59; diff --git a/core/tests/coretests/OWNERS b/core/tests/coretests/OWNERS index 0fb0c3021486..e8c9fe70272d 100644 --- a/core/tests/coretests/OWNERS +++ b/core/tests/coretests/OWNERS @@ -1 +1,4 @@ include platform/frameworks/base:/services/core/java/com/android/server/am/OWNERS + +per-file BinderTest.java = file:platform/frameworks/native:/libs/binder/OWNERS +per-file ParcelTest.java = file:platform/frameworks/native:/libs/binder/OWNERS diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java index fdd278b9c621..e2fe87b4cfe3 100644 --- a/core/tests/coretests/src/android/os/ParcelTest.java +++ b/core/tests/coretests/src/android/os/ParcelTest.java @@ -37,6 +37,13 @@ public class ParcelTest { private static final String INTERFACE_TOKEN_2 = "Another IBinder interface token"; @Test + public void testIsForRpc() { + Parcel p = Parcel.obtain(); + assertEquals(false, p.isForRpc()); + p.recycle(); + } + + @Test public void testCallingWorkSourceUidAfterWrite() { Parcel p = Parcel.obtain(); // Method does not throw if replaceCallingWorkSourceUid is called before requests headers diff --git a/core/tests/coretests/src/com/android/internal/security/ContentSignerWrapper.java b/core/tests/coretests/src/com/android/internal/security/ContentSignerWrapper.java new file mode 100644 index 000000000000..0254afee35dd --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/security/ContentSignerWrapper.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 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.internal.security; + +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.operator.ContentSigner; + +import java.io.OutputStream; + +/** A wrapper class of ContentSigner */ +class ContentSignerWrapper implements ContentSigner { + private final ContentSigner mSigner; + + ContentSignerWrapper(ContentSigner wrapped) { + mSigner = wrapped; + } + + @Override + public AlgorithmIdentifier getAlgorithmIdentifier() { + return mSigner.getAlgorithmIdentifier(); + } + + @Override + public OutputStream getOutputStream() { + return mSigner.getOutputStream(); + } + + @Override + public byte[] getSignature() { + return mSigner.getSignature(); + } +} diff --git a/core/tests/coretests/src/com/android/internal/security/OWNERS b/core/tests/coretests/src/com/android/internal/security/OWNERS new file mode 100644 index 000000000000..4f4d8d7a0932 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/security/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 36824 + +per-file VerityUtilsTest.java = file:platform/system/security:/fsverity/OWNERS diff --git a/core/tests/coretests/src/com/android/internal/security/VerityUtilsTest.java b/core/tests/coretests/src/com/android/internal/security/VerityUtilsTest.java new file mode 100644 index 000000000000..d1d8018fc415 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/security/VerityUtilsTest.java @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2022 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.internal.security; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.bouncycastle.asn1.ASN1Encoding; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.CMSProcessableByteArray; +import org.bouncycastle.cms.CMSSignedData; +import org.bouncycastle.cms.CMSSignedDataGenerator; +import org.bouncycastle.cms.SignerInfoGenerator; +import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.DigestCalculator; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.bc.BcDigestCalculatorProvider; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.Date; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +public class VerityUtilsTest { + private static final byte[] SAMPLE_DIGEST = "12345678901234567890123456789012".getBytes(); + private static final byte[] FORMATTED_SAMPLE_DIGEST = toFormattedDigest(SAMPLE_DIGEST); + + KeyPair mKeyPair; + ContentSigner mContentSigner; + X509CertificateHolder mCertificateHolder; + byte[] mCertificateDerEncoded; + + @Before + public void setUp() throws Exception { + mKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); + mContentSigner = newFsverityContentSigner(mKeyPair.getPrivate()); + mCertificateHolder = + newX509CertificateHolder(mContentSigner, mKeyPair.getPublic(), "Someone"); + mCertificateDerEncoded = mCertificateHolder.getEncoded(); + } + + @Test + public void testOnlyAcceptCorrectDigest() throws Exception { + byte[] pkcs7Signature = + generatePkcs7Signature(mContentSigner, mCertificateHolder, FORMATTED_SAMPLE_DIGEST); + + byte[] anotherDigest = Arrays.copyOf(SAMPLE_DIGEST, SAMPLE_DIGEST.length); + anotherDigest[0] ^= (byte) 1; + + assertTrue(verifySignature(pkcs7Signature, SAMPLE_DIGEST, mCertificateDerEncoded)); + assertFalse(verifySignature(pkcs7Signature, anotherDigest, mCertificateDerEncoded)); + } + + @Test + public void testDigestWithWrongSize() throws Exception { + byte[] pkcs7Signature = + generatePkcs7Signature(mContentSigner, mCertificateHolder, FORMATTED_SAMPLE_DIGEST); + assertTrue(verifySignature(pkcs7Signature, SAMPLE_DIGEST, mCertificateDerEncoded)); + + byte[] digestTooShort = Arrays.copyOfRange(SAMPLE_DIGEST, 0, SAMPLE_DIGEST.length - 1); + assertFalse(verifySignature(pkcs7Signature, digestTooShort, mCertificateDerEncoded)); + + byte[] digestTooLong = Arrays.copyOfRange(SAMPLE_DIGEST, 0, SAMPLE_DIGEST.length + 1); + assertFalse(verifySignature(pkcs7Signature, digestTooLong, mCertificateDerEncoded)); + } + + @Test + public void testOnlyAcceptGoodSignature() throws Exception { + byte[] pkcs7Signature = + generatePkcs7Signature(mContentSigner, mCertificateHolder, FORMATTED_SAMPLE_DIGEST); + + byte[] anotherDigest = Arrays.copyOf(SAMPLE_DIGEST, SAMPLE_DIGEST.length); + anotherDigest[0] ^= (byte) 1; + byte[] anotherPkcs7Signature = + generatePkcs7Signature( + mContentSigner, mCertificateHolder, toFormattedDigest(anotherDigest)); + + assertTrue(verifySignature(pkcs7Signature, SAMPLE_DIGEST, mCertificateDerEncoded)); + assertFalse(verifySignature(anotherPkcs7Signature, SAMPLE_DIGEST, mCertificateDerEncoded)); + } + + @Test + public void testOnlyValidCertCanVerify() throws Exception { + byte[] pkcs7Signature = + generatePkcs7Signature(mContentSigner, mCertificateHolder, FORMATTED_SAMPLE_DIGEST); + + var wrongKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); + var wrongContentSigner = newFsverityContentSigner(wrongKeyPair.getPrivate()); + var wrongCertificateHolder = + newX509CertificateHolder(wrongContentSigner, wrongKeyPair.getPublic(), "Not Me"); + byte[] wrongCertificateDerEncoded = wrongCertificateHolder.getEncoded(); + + assertFalse(verifySignature(pkcs7Signature, SAMPLE_DIGEST, wrongCertificateDerEncoded)); + } + + @Test + public void testRejectSignatureWithContent() throws Exception { + CMSSignedDataGenerator generator = + newFsveritySignedDataGenerator(mContentSigner, mCertificateHolder); + byte[] pkcs7SignatureNonDetached = + generatePkcs7SignatureInternal( + generator, FORMATTED_SAMPLE_DIGEST, /* encapsulate */ true); + + assertFalse( + verifySignature(pkcs7SignatureNonDetached, SAMPLE_DIGEST, mCertificateDerEncoded)); + } + + @Test + public void testRejectSignatureWithCertificate() throws Exception { + CMSSignedDataGenerator generator = + newFsveritySignedDataGenerator(mContentSigner, mCertificateHolder); + generator.addCertificate(mCertificateHolder); + byte[] pkcs7Signature = + generatePkcs7SignatureInternal( + generator, FORMATTED_SAMPLE_DIGEST, /* encapsulate */ false); + + assertFalse( + verifySignature(pkcs7Signature, SAMPLE_DIGEST, mCertificateDerEncoded)); + } + + @Ignore("No easy way to construct test data") + @Test + public void testRejectSignatureWithCRL() throws Exception { + CMSSignedDataGenerator generator = + newFsveritySignedDataGenerator(mContentSigner, mCertificateHolder); + + // The current bouncycastle version does not have an easy way to generate a CRL. + // TODO: enable the test once this is doable, e.g. with X509v2CRLBuilder. + // generator.addCRL(new X509CRLHolder(CertificateList.getInstance(new DERSequence(...)))); + byte[] pkcs7Signature = + generatePkcs7SignatureInternal( + generator, FORMATTED_SAMPLE_DIGEST, /* encapsulate */ false); + + assertFalse( + verifySignature(pkcs7Signature, SAMPLE_DIGEST, mCertificateDerEncoded)); + } + + @Test + public void testRejectUnsupportedSignatureAlgorithms() throws Exception { + var contentSigner = newFsverityContentSigner(mKeyPair.getPrivate(), "MD5withRSA", null); + var certificateHolder = + newX509CertificateHolder(contentSigner, mKeyPair.getPublic(), "Someone"); + byte[] pkcs7Signature = + generatePkcs7Signature(contentSigner, certificateHolder, FORMATTED_SAMPLE_DIGEST); + + assertFalse(verifySignature(pkcs7Signature, SAMPLE_DIGEST, certificateHolder.getEncoded())); + } + + @Test + public void testRejectUnsupportedDigestAlgorithm() throws Exception { + CMSSignedDataGenerator generator = new CMSSignedDataGenerator(); + generator.addSignerInfoGenerator( + newSignerInfoGenerator( + mContentSigner, + mCertificateHolder, + OIWObjectIdentifiers.idSHA1, + true)); // directSignature + byte[] pkcs7Signature = + generatePkcs7SignatureInternal( + generator, FORMATTED_SAMPLE_DIGEST, /* encapsulate */ false); + + assertFalse(verifySignature(pkcs7Signature, SAMPLE_DIGEST, mCertificateDerEncoded)); + } + + @Test + public void testRejectAnySignerInfoAttributes() throws Exception { + var generator = new CMSSignedDataGenerator(); + generator.addSignerInfoGenerator( + newSignerInfoGenerator( + mContentSigner, + mCertificateHolder, + NISTObjectIdentifiers.id_sha256, + false)); // directSignature + byte[] pkcs7Signature = + generatePkcs7SignatureInternal( + generator, FORMATTED_SAMPLE_DIGEST, /* encapsulate */ false); + + assertFalse(verifySignature(pkcs7Signature, SAMPLE_DIGEST, mCertificateDerEncoded)); + } + + private static boolean verifySignature( + byte[] pkcs7Signature, byte[] fsverityDigest, byte[] certificateDerEncoded) { + return VerityUtils.verifyPkcs7DetachedSignature( + pkcs7Signature, fsverityDigest, new ByteArrayInputStream(certificateDerEncoded)); + } + + private static byte[] toFormattedDigest(byte[] digest) { + return VerityUtils.toFormattedDigest(digest); + } + + private static byte[] generatePkcs7Signature( + ContentSigner contentSigner, X509CertificateHolder certificateHolder, byte[] signedData) + throws IOException, CMSException, OperatorCreationException { + CMSSignedDataGenerator generator = + newFsveritySignedDataGenerator(contentSigner, certificateHolder); + return generatePkcs7SignatureInternal(generator, signedData, /* encapsulate */ false); + } + + private static byte[] generatePkcs7SignatureInternal( + CMSSignedDataGenerator generator, byte[] signedData, boolean encapsulate) + throws IOException, CMSException, OperatorCreationException { + CMSSignedData cmsSignedData = + generator.generate(new CMSProcessableByteArray(signedData), encapsulate); + return cmsSignedData.toASN1Structure().getEncoded(ASN1Encoding.DL); + } + + private static CMSSignedDataGenerator newFsveritySignedDataGenerator( + ContentSigner contentSigner, X509CertificateHolder certificateHolder) + throws IOException, CMSException, OperatorCreationException { + var generator = new CMSSignedDataGenerator(); + generator.addSignerInfoGenerator( + newSignerInfoGenerator( + contentSigner, + certificateHolder, + NISTObjectIdentifiers.id_sha256, + true)); // directSignature + return generator; + } + + private static SignerInfoGenerator newSignerInfoGenerator( + ContentSigner contentSigner, + X509CertificateHolder certificateHolder, + ASN1ObjectIdentifier digestAlgorithmId, + boolean directSignature) + throws IOException, CMSException, OperatorCreationException { + var provider = + new BcDigestCalculatorProvider() { + /** + * Allow the caller to override the digest algorithm, especially when the + * default does not work (i.e. BcDigestCalculatorProvider could return null). + * + * <p>For example, the current fs-verity signature has to use rsaEncryption for + * the signature algorithm, but BcDigestCalculatorProvider will return null, + * thus we need a way to override. + * + * <p>TODO: After bouncycastle 1.70, we can remove this override and just use + * {@code JcaSignerInfoGeneratorBuilder#setContentDigest}. + */ + @Override + public DigestCalculator get(AlgorithmIdentifier algorithm) + throws OperatorCreationException { + return super.get(new AlgorithmIdentifier(digestAlgorithmId)); + } + }; + var builder = + new JcaSignerInfoGeneratorBuilder(provider).setDirectSignature(directSignature); + return builder.build(contentSigner, certificateHolder); + } + + private static ContentSigner newFsverityContentSigner(PrivateKey privateKey) + throws OperatorCreationException { + // fs-verity expects the signature to have rsaEncryption as the exact algorithm, so + // override the default. + return newFsverityContentSigner( + privateKey, "SHA256withRSA", PKCSObjectIdentifiers.rsaEncryption); + } + + private static ContentSigner newFsverityContentSigner( + PrivateKey privateKey, + String signatureAlgorithm, + ASN1ObjectIdentifier signatureAlgorithmIdOverride) + throws OperatorCreationException { + if (signatureAlgorithmIdOverride != null) { + return new ContentSignerWrapper( + new JcaContentSignerBuilder(signatureAlgorithm).build(privateKey)) { + @Override + public AlgorithmIdentifier getAlgorithmIdentifier() { + return new AlgorithmIdentifier(signatureAlgorithmIdOverride); + } + }; + } else { + return new JcaContentSignerBuilder(signatureAlgorithm).build(privateKey); + } + } + + private static X509CertificateHolder newX509CertificateHolder( + ContentSigner contentSigner, PublicKey publicKey, String name) { + // Time doesn't really matter, as we only care about the key. + Instant now = Instant.now(); + + return new X509v3CertificateBuilder( + new X500Name("CN=Issuer " + name), + /* serial= */ BigInteger.valueOf(now.getEpochSecond()), + new Date(now.minus(Duration.ofDays(1)).toEpochMilli()), + new Date(now.plus(Duration.ofDays(1)).toEpochMilli()), + new X500Name("CN=Subject " + name), + SubjectPublicKeyInfo.getInstance(publicKey.getEncoded())) + .build(contentSigner); + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/qrcode/OWNERS b/packages/SettingsLib/src/com/android/settingslib/qrcode/OWNERS new file mode 100644 index 000000000000..61c73fb733a9 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/qrcode/OWNERS @@ -0,0 +1,8 @@ +# Default reviewers for this and subdirectories. +bonianchen@google.com +changbetty@google.com +goldmanj@google.com +wengsu@google.com +zoeychen@google.com + +# Emergency approvers in case the above are not available diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index ccfeae43e8b6..8683eac73c6c 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -771,6 +771,12 @@ class SettingsProtoDumpUtil { Settings.Global.ANGLE_EGL_FEATURES, GlobalSettingsProto.Gpu.ANGLE_EGL_FEATURES); dumpSetting(s, p, + Settings.Global.ANGLE_DEFERLIST, + GlobalSettingsProto.Gpu.ANGLE_DEFERLIST); + dumpSetting(s, p, + Settings.Global.ANGLE_DEFERLIST_MODE, + GlobalSettingsProto.Gpu.ANGLE_DEFERLIST_MODE); + dumpSetting(s, p, Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX, GlobalSettingsProto.Gpu.SHOW_ANGLE_IN_USE_DIALOG); dumpSetting(s, p, diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index cce515444c1f..1dc088717e9c 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -512,6 +512,8 @@ public class SettingsBackupTest { Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS, Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES, Settings.Global.ANGLE_EGL_FEATURES, + Settings.Global.ANGLE_DEFERLIST, + Settings.Global.ANGLE_DEFERLIST_MODE, Settings.Global.UPDATABLE_DRIVER_ALL_APPS, Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS, Settings.Global.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS, diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index a25ac210f9c8..c72544143fa7 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -458,7 +458,6 @@ public class DisplayDeviceConfig { */ public float getNitsFromBacklight(float backlight) { if (mBacklightToNitsSpline == null) { - Slog.wtf(TAG, "requesting nits when no mapping exists."); return NITS_INVALID; } backlight = Math.max(backlight, mBacklightMinimum); diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java index c2f2b0af997a..ffe0ca003817 100644 --- a/services/core/java/com/android/server/pm/ApkChecksums.java +++ b/services/core/java/com/android/server/pm/ApkChecksums.java @@ -650,7 +650,7 @@ public class ApkChecksums { // Skip /product folder. // TODO(b/231354111): remove this hack once we are allowed to change SELinux rules. if (!containsFile(Environment.getProductDirectory(), filePath)) { - byte[] verityHash = VerityUtils.getFsverityRootHash(filePath); + byte[] verityHash = VerityUtils.getFsverityDigest(filePath); if (verityHash != null) { return new ApkChecksum(split, TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, verityHash); } diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java index 016c1cb7bdf0..fe797d211a8c 100644 --- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java +++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java @@ -147,7 +147,8 @@ public class UserRestrictionsUtils { UserManager.DISALLOW_WIFI_TETHERING, UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI, UserManager.DISALLOW_WIFI_DIRECT, - UserManager.DISALLOW_ADD_WIFI_CONFIG + UserManager.DISALLOW_ADD_WIFI_CONFIG, + UserManager.DISALLOW_CELLULAR_2G }); public static final Set<String> DEPRECATED_USER_RESTRICTIONS = Sets.newArraySet( @@ -195,7 +196,8 @@ public class UserRestrictionsUtils { UserManager.DISALLOW_CHANGE_WIFI_STATE, UserManager.DISALLOW_WIFI_TETHERING, UserManager.DISALLOW_WIFI_DIRECT, - UserManager.DISALLOW_ADD_WIFI_CONFIG + UserManager.DISALLOW_ADD_WIFI_CONFIG, + UserManager.DISALLOW_CELLULAR_2G ); /** @@ -234,7 +236,8 @@ public class UserRestrictionsUtils { UserManager.DISALLOW_CHANGE_WIFI_STATE, UserManager.DISALLOW_WIFI_TETHERING, UserManager.DISALLOW_WIFI_DIRECT, - UserManager.DISALLOW_ADD_WIFI_CONFIG + UserManager.DISALLOW_ADD_WIFI_CONFIG, + UserManager.DISALLOW_CELLULAR_2G ); /** diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 8d831d72c05b..91dcc8e412dc 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -1441,7 +1441,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { a.colorMode = ActivityInfo.COLOR_MODE_DEFAULT; a.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; a.resizeMode = RESIZE_MODE_UNRESIZEABLE; - a.configChanges = ActivityInfo.CONFIG_ORIENTATION; + a.configChanges = 0xffffffff; final ActivityOptions options = ActivityOptions.makeBasic(); options.setLaunchActivityType(ACTIVITY_TYPE_DREAM); diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 70d82701da66..a081bc320921 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -9358,7 +9358,8 @@ public class TelephonyManager { ALLOWED_NETWORK_TYPES_REASON_USER, ALLOWED_NETWORK_TYPES_REASON_POWER, ALLOWED_NETWORK_TYPES_REASON_CARRIER, - ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G + ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G, + ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, }) @Retention(RetentionPolicy.SOURCE) public @interface AllowedNetworkTypesReason { @@ -9397,6 +9398,15 @@ public class TelephonyManager { public static final int ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G = 3; /** + * To indicate allowed network type change is requested by an update to the + * {@link android.os.UserManager.DISALLOW_CELLULAR_2G} user restriction. + * + * @hide + */ + @SystemApi + public static final int ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS = 4; + + /** * Set the allowed network types of the device and provide the reason triggering the allowed * network change. * <p>Requires permission: android.Manifest.MODIFY_PHONE_STATE or @@ -9488,6 +9498,7 @@ public class TelephonyManager { case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER: case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER: case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G: + case ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS: return true; } return false; |