From 04cb994830dd5ce917b611f49aa374e3526189a9 Mon Sep 17 00:00:00 2001 From: omarmt Date: Tue, 25 Apr 2023 13:41:31 +0000 Subject: [PATCH] Verify enableOnBackInvokedCallback at the app-level if ActivityInfo is null The `ActivityInfo` should not be `null`, otherwise we will not be able to check if the activity has the `enableOnBackInvokedCallback="true|false"` flag. Unfortunately, there is no good default value in this case. Our options are: - Use the application flag, but this may cause random behavior that is difficult to troubleshoot. - Assume that the activity has `enableOnBackInvokedCallback="false"` in the manifest, which might have strange behavior but at least it would be a "known issue" (for example, if you activate predictive back and it doesn't work in that activity, you can check that XYZ is correct). Regardless of the reason, I would add a warning or error message explaining the problem. Test: mp droid Bug: 271860402 Change-Id: Ie91376ce18eb0a8d5528339a68e4db88a57cff86 --- .../window/WindowOnBackInvokedDispatcher.java | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java index 51382a4b265f4..4d0132e46ba7b 100644 --- a/core/java/android/window/WindowOnBackInvokedDispatcher.java +++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java @@ -21,6 +21,8 @@ import android.annotation.Nullable; import android.app.Activity; import android.content.Context; import android.content.ContextWrapper; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.os.Handler; import android.os.RemoteException; import android.os.SystemProperties; @@ -421,36 +423,45 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { return false; } - boolean requestsPredictiveBack; + boolean requestsPredictiveBack = false; // Check if the context is from an activity. while ((context instanceof ContextWrapper) && !(context instanceof Activity)) { context = ((ContextWrapper) context).getBaseContext(); } + boolean shouldCheckActivity = false; + if (context instanceof Activity) { final Activity activity = (Activity) context; - if (activity.getActivityInfo().hasOnBackInvokedCallbackEnabled()) { - requestsPredictiveBack = - activity.getActivityInfo().isOnBackInvokedCallbackEnabled(); - } else { - requestsPredictiveBack = - context.getApplicationInfo().isOnBackInvokedCallbackEnabled(); - } + final ActivityInfo activityInfo = activity.getActivityInfo(); + if (activityInfo != null) { + if (activityInfo.hasOnBackInvokedCallbackEnabled()) { + shouldCheckActivity = true; + requestsPredictiveBack = activityInfo.isOnBackInvokedCallbackEnabled(); - if (DEBUG) { - Log.d(TAG, TextUtils.formatSimple("Activity: %s isPredictiveBackEnabled=%s", - activity.getComponentName(), - requestsPredictiveBack)); + if (DEBUG) { + Log.d(TAG, TextUtils.formatSimple( + "Activity: %s isPredictiveBackEnabled=%s", + activity.getComponentName(), + requestsPredictiveBack)); + } + } + } else { + Log.w(TAG, "The ActivityInfo is null, so we cannot verify if this Activity" + + " has the 'android:enableOnBackInvokedCallback' attribute." + + " The application attribute will be used as a fallback."); } - } else { - requestsPredictiveBack = - context.getApplicationInfo().isOnBackInvokedCallbackEnabled(); + } + + if (!shouldCheckActivity) { + final ApplicationInfo applicationInfo = context.getApplicationInfo(); + requestsPredictiveBack = applicationInfo.isOnBackInvokedCallbackEnabled(); if (DEBUG) { Log.d(TAG, TextUtils.formatSimple("App: %s requestsPredictiveBack=%s", - context.getApplicationInfo().packageName, + applicationInfo.packageName, requestsPredictiveBack)); } }