Skip to content

Commit

Permalink
Use curtains to get phone window from decor view
Browse files Browse the repository at this point in the history
Summary:
The official api only let you access this window by going through a views activity, but if a doesn't belong to an activity there is no possible way without  reflection tricks.  Curtains is a nice library that does this reflection adn a lot of the other reflection hacks that the UIdebugger needs.

## The reason this is important

When snapshotting a dialog fragment  we were using pixel copy using tryCopyViaInternalSurface approach. The issue is this is the lowest level api and doesnt consider 'surface insets' Surface insets seems to be related to the fact that a surface may be bigger than the content it draws.  This ended up manifesting like this

{F1372530065}

the issue is we create a bitmap sized to the decor view, but we were snapshotting the whole surface which is actually a bit bigger due to the black bars / surface insets.

When you pass a android.view.Window to pixel copy it has code to account for the surface insets. https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/graphics/java/android/view/PixelCopy.java;l=291;drc=228276a74bc36e8c0f0fadbb4a15ef013ff6ce24

Before we couldn't pass a window for dialogs since there was no activity to provide it, now curtains gives us this window and we can use the high level api in pxiel copy that does the right thing w.r.t surface insets

Reviewed By: passy

Differential Revision: D53090570

fbshipit-source-id: 969695198cfa5b848238e734d6ddec29681930e5
  • Loading branch information
Luke De Feo authored and facebook-github-bot committed Feb 2, 2024
1 parent 35bcc75 commit d38bb12
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 8 deletions.
1 change: 1 addition & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ android {
implementation deps.openssl
implementation deps.fbjni
implementation deps.soloader
implementation deps.curtains
implementation deps.jsr305
implementation deps.supportAppCompat
implementation deps.supportSqlite
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

package com.facebook.flipper.plugins.uidebugger.core

import android.app.Activity
import android.graphics.Canvas
import android.os.Build
import android.os.Handler
Expand All @@ -17,6 +16,7 @@ import android.view.PixelCopy
import android.view.View
import androidx.annotation.RequiresApi
import com.facebook.flipper.plugins.uidebugger.LogTag
import curtains.phoneWindow
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
Expand Down Expand Up @@ -92,25 +92,26 @@ class PixelCopySnapshotter(

return if (view.isHardwareAccelerated) {
SnapshotCommon.doSnapshotWithErrorHandling(bitmapPool, view, fallback) {
tryCopyViaActivityWindow(view, it) || tryCopyViaInternalSurface(view, it)
tryCopyViaPhoneWindow(view, it) || tryCopyViaInternalSurface(view, it)
}
} else {
fallback.takeSnapshot(view)
}
}

private suspend fun tryCopyViaActivityWindow(
/**
* This is the preferred method, passing a window into pixel copy correctly accounts for the
* surface insets, this means dialog fragments are snapshotted correctly
*/
private suspend fun tryCopyViaPhoneWindow(
view: View,
bitmap: BitmapPool.ReusableBitmap
): Boolean {

val decorViewToActivity: Map<View, Activity> = ActivityTracker.decorViewToActivityMap

val activityForDecorView = decorViewToActivity[view] ?: return false
val window = view.phoneWindow ?: return false

return suspendCoroutine { continuation ->
PixelCopy.request(
activityForDecorView.window, bitmap.bitmap, pixelCopyCallback(continuation), handler)
PixelCopy.request(window, bitmap.bitmap, pixelCopyCallback(continuation), handler)
}
}

Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ ext.deps = [
fbjni : "com.facebook.fbjni:fbjni:$FBJNI_VERSION",
screenshot : 'com.facebook.testing.screenshot:core:0.15.0',
boltsTasks : 'com.parse.bolts:bolts-tasks:1.4.0',
curtains : 'com.squareup.curtains:curtains:1.2.5',
// Third-party
websocket : 'org.java-websocket:Java-WebSocket:1.5.4',
openssl : 'com.android.ndk.thirdparty:openssl:1.1.1l-beta-1',
Expand Down

0 comments on commit d38bb12

Please sign in to comment.