diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java deleted file mode 100644 index 9db6ef475fb..00000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.devsupport; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.graphics.PixelFormat; -import android.net.Uri; -import android.provider.Settings; -import android.view.WindowManager; -import android.widget.FrameLayout; -import androidx.annotation.Nullable; -import com.facebook.common.logging.FLog; -import com.facebook.infer.annotation.Nullsafe; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.UiThreadUtil; -import com.facebook.react.common.ReactConstants; - -/** - * Helper class for controlling overlay view with FPS and JS FPS info that gets added directly - * to @{link WindowManager} instance. - */ -/* package */ @Nullsafe(Nullsafe.Mode.LOCAL) -class DebugOverlayController { - - public static void requestPermission(Context context) { - // Get permission to show debug overlay in dev builds. - if (!Settings.canDrawOverlays(context)) { - Intent intent = - new Intent( - Settings.ACTION_MANAGE_OVERLAY_PERMISSION, - Uri.parse("package:" + context.getPackageName())); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - FLog.w( - ReactConstants.TAG, - "Overlay permissions needs to be granted in order for react native apps to run in dev" - + " mode"); - if (canHandleIntent(context, intent)) { - context.startActivity(intent); - } - } - } - - private static boolean permissionCheck(Context context) { - // Get permission to show debug overlay in dev builds. - // overlay permission not yet granted - return Settings.canDrawOverlays(context); - } - - private static boolean hasPermission(Context context, String permission) { - try { - PackageInfo info = - context - .getPackageManager() - // NULLSAFE_FIXME[Nullable Dereference] - .getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS); - if (info.requestedPermissions != null) { - for (String p : info.requestedPermissions) { - if (p.equals(permission)) { - return true; - } - } - } - } catch (PackageManager.NameNotFoundException e) { - FLog.e(ReactConstants.TAG, "Error while retrieving package info", e); - } - return false; - } - - private static boolean canHandleIntent(Context context, Intent intent) { - PackageManager packageManager = context.getPackageManager(); - return packageManager != null && intent.resolveActivity(packageManager) != null; - } - - private final WindowManager mWindowManager; - private final ReactContext mReactContext; - - private @Nullable FrameLayout mFPSDebugViewContainer; - - public DebugOverlayController(ReactContext reactContext) { - mReactContext = reactContext; - mWindowManager = (WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE); - } - - public void setFpsDebugViewVisible(final boolean fpsDebugViewVisible) { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - if (fpsDebugViewVisible && mFPSDebugViewContainer == null) { - if (!permissionCheck(mReactContext)) { - FLog.d(ReactConstants.TAG, "Wait for overlay permission to be set"); - return; - } - mFPSDebugViewContainer = new FpsView(mReactContext); - WindowManager.LayoutParams params = - new WindowManager.LayoutParams( - WindowManager.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.MATCH_PARENT, - WindowOverlayCompat.TYPE_SYSTEM_OVERLAY, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, - PixelFormat.TRANSLUCENT); - mWindowManager.addView(mFPSDebugViewContainer, params); - } else if (!fpsDebugViewVisible && mFPSDebugViewContainer != null) { - mFPSDebugViewContainer.removeAllViews(); - mWindowManager.removeView(mFPSDebugViewContainer); - mFPSDebugViewContainer = null; - } - } - }); - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.kt new file mode 100644 index 00000000000..3467d9af749 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.kt @@ -0,0 +1,87 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.devsupport + +import android.content.Context +import android.content.Intent +import android.graphics.PixelFormat +import android.net.Uri +import android.provider.Settings +import android.view.WindowManager +import android.widget.FrameLayout +import com.facebook.common.logging.FLog +import com.facebook.react.bridge.ReactContext +import com.facebook.react.bridge.UiThreadUtil +import com.facebook.react.common.ReactConstants + +/** + * Helper class for controlling overlay view with FPS and JS FPS info that gets added directly to + * [WindowManager] instance. + */ +internal class DebugOverlayController(private val reactContext: ReactContext) { + private val windowManager = reactContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager + + private var fpsDebugViewContainer: FrameLayout? = null + + fun setFpsDebugViewVisible(fpsDebugViewVisible: Boolean) { + UiThreadUtil.runOnUiThread( + Runnable { + if (fpsDebugViewVisible && fpsDebugViewContainer == null) { + if (!permissionCheck(reactContext)) { + FLog.d(ReactConstants.TAG, "Wait for overlay permission to be set") + return@Runnable + } + fpsDebugViewContainer = FpsView(reactContext) + val params = + WindowManager.LayoutParams( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT, + WindowOverlayCompat.TYPE_SYSTEM_OVERLAY, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, + PixelFormat.TRANSLUCENT) + windowManager.addView(fpsDebugViewContainer, params) + } else if (!fpsDebugViewVisible && fpsDebugViewContainer != null) { + fpsDebugViewContainer?.removeAllViews() + windowManager.removeView(fpsDebugViewContainer) + fpsDebugViewContainer = null + } + }) + } + + companion object { + @JvmStatic + fun requestPermission(context: Context) { + // Get permission to show debug overlay in dev builds. + if (!Settings.canDrawOverlays(context)) { + val intent = + Intent( + Settings.ACTION_MANAGE_OVERLAY_PERMISSION, + Uri.parse("package:" + context.packageName)) + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + FLog.w( + ReactConstants.TAG, + "Overlay permissions needs to be granted in order for react native apps to run in dev mode") + if (canHandleIntent(context, intent)) { + context.startActivity(intent) + } + } + } + + private fun permissionCheck(context: Context): Boolean { + // Get permission to show debug overlay in dev builds. + // overlay permission not yet granted + return Settings.canDrawOverlays(context) + } + + private fun canHandleIntent(context: Context, intent: Intent): Boolean { + val packageManager = context.packageManager + return packageManager != null && intent.resolveActivity(packageManager) != null + } + } +}