From d5e4b0c36086c8816409af8ff7efd496abe57fd2 Mon Sep 17 00:00:00 2001 From: Chaiwat Ekkaewnumchai Date: Tue, 26 Oct 2021 03:38:45 -0700 Subject: [PATCH] Clear Activity after Being Destroyed Summary: [Reported in the support request](https://fb.workplace.com/groups/flippersupport/posts/1237466586733997/), Activity object is held by ObjectTracker even though the Activity is destroyed. This, in this case, caused strict mode in Portal app to forcibly terminate. This diff tried to remove activities from the reference holder. Reviewed By: passy Differential Revision: D31828290 fbshipit-source-id: aad7e8d7ba14069f8dd7c654a3604d482d85e110 --- .../plugins/inspector/ApplicationWrapper.java | 13 +++++++++ .../inspector/InspectorFlipperPlugin.java | 28 ++++++++++++++++++- .../plugins/inspector/ObjectTracker.java | 4 +++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/facebook/flipper/plugins/inspector/ApplicationWrapper.java b/android/src/main/java/com/facebook/flipper/plugins/inspector/ApplicationWrapper.java index 35f2f382f..c3beaa269 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/inspector/ApplicationWrapper.java +++ b/android/src/main/java/com/facebook/flipper/plugins/inspector/ApplicationWrapper.java @@ -27,11 +27,16 @@ public class ApplicationWrapper implements Application.ActivityLifecycleCallback void onActivityStackChanged(List stack); } + public interface ActivityDestroyedListener { + void onActivityDestroyed(Activity activity); + } + private final Application mApplication; private final AndroidRootResolver mAndroidRootsResolver; private final List> mActivities; private final Handler mHandler; private ActivityStackChangedListener mListener; + private ActivityDestroyedListener mActivityDestroyedListener; public ApplicationWrapper(Application application) { mApplication = application; @@ -66,6 +71,10 @@ public class ApplicationWrapper implements Application.ActivityLifecycleCallback public void onActivityDestroyed(Activity activity) { final Iterator> activityIterator = mActivities.iterator(); + if (mActivityDestroyedListener != null) { + mActivityDestroyedListener.onActivityDestroyed(activity); + } + while (activityIterator.hasNext()) { if (activityIterator.next().get() == activity) { activityIterator.remove(); @@ -84,6 +93,10 @@ public class ApplicationWrapper implements Application.ActivityLifecycleCallback mListener = listener; } + public void setActivityDestroyedListener(ActivityDestroyedListener listener) { + mActivityDestroyedListener = listener; + } + public Application getApplication() { return mApplication; } diff --git a/android/src/main/java/com/facebook/flipper/plugins/inspector/InspectorFlipperPlugin.java b/android/src/main/java/com/facebook/flipper/plugins/inspector/InspectorFlipperPlugin.java index fbf6be554..b5101df4c 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/inspector/InspectorFlipperPlugin.java +++ b/android/src/main/java/com/facebook/flipper/plugins/inspector/InspectorFlipperPlugin.java @@ -7,8 +7,10 @@ package com.facebook.flipper.plugins.inspector; +import android.app.Activity; import android.app.Application; import android.content.Context; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; @@ -29,6 +31,7 @@ import java.util.Map; import javax.annotation.Nullable; public class InspectorFlipperPlugin implements FlipperPlugin { + private static final String TAG = "ContextDescriptor"; private ApplicationWrapper mApplication; private DescriptorMapping mDescriptorMapping; @@ -91,7 +94,7 @@ public class InspectorFlipperPlugin implements FlipperPlugin { // Package visible for testing InspectorFlipperPlugin( ApplicationWrapper wrapper, - DescriptorMapping descriptorMapping, + final DescriptorMapping descriptorMapping, @Nullable List extensions) { mDescriptorMapping = descriptorMapping; @@ -99,6 +102,29 @@ public class InspectorFlipperPlugin implements FlipperPlugin { mApplication = wrapper; mExtensionCommands = extensions; mShowLithoAccessibilitySettings = false; + + mApplication.setActivityDestroyedListener( + new ApplicationWrapper.ActivityDestroyedListener() { + private final DescriptorMapping mCallbackDescriptorMapping = mDescriptorMapping; + private final ObjectTracker mCallbackObjectTracker = mObjectTracker; + + @Override + public void onActivityDestroyed(Activity activity) { + try { + final NodeDescriptor activityDescriptor = + (NodeDescriptor) + mCallbackDescriptorMapping.descriptorForClass(Activity.class); + if (activityDescriptor == null || mCallbackObjectTracker == null) { + return; + } + String activityId = activityDescriptor.getId(activity); + mCallbackObjectTracker.remove(activityId); + } catch (Exception e) { + // Ignore if there is an error + Log.d(TAG, "Cannot remove activity from ObjectTracker: " + e.getMessage()); + } + } + }); } @Override diff --git a/android/src/main/java/com/facebook/flipper/plugins/inspector/ObjectTracker.java b/android/src/main/java/com/facebook/flipper/plugins/inspector/ObjectTracker.java index 95801b543..242c796e6 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/inspector/ObjectTracker.java +++ b/android/src/main/java/com/facebook/flipper/plugins/inspector/ObjectTracker.java @@ -40,6 +40,10 @@ public class ObjectTracker { mObjects.clear(); } + public void remove(String id) { + mObjects.remove(id); + } + public boolean contains(String id) { return mObjects.containsKey(id); }