Merge changes I96b17c78,If4b09f5b into tm-dev

* changes:
  Make DialogThemedActivity main window is not focusable
  Make IME visiblity stable without unexpected hidden when setControl
This commit is contained in:
Ming-Shin Lu
2022-04-29 14:19:28 +00:00
committed by Android (Google) Code Review
5 changed files with 71 additions and 10 deletions

View File

@@ -65,6 +65,9 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
public void onWindowFocusGained(boolean hasViewFocus) {
super.onWindowFocusGained(hasViewFocus);
getImm().registerImeConsumer(this);
if (isRequestedVisible() && getControl() == null) {
mIsRequestedVisibleAwaitingControl = true;
}
}
@Override
@@ -149,14 +152,11 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
}
@Override
public void setControl(@Nullable InsetsSourceControl control, int[] showTypes,
public boolean setControl(@Nullable InsetsSourceControl control, int[] showTypes,
int[] hideTypes) {
super.setControl(control, showTypes, hideTypes);
// TODO(b/204524304): clean-up how to deal with the timing issues of hiding IME:
// 1) Already requested show IME, in the meantime of WM callback the control but got null
// control when relayout comes first
// 2) Make sure no regression on some implicit request IME visibility calls (e.g.
// toggleSoftInput)
if (!super.setControl(control, showTypes, hideTypes)) {
return false;
}
if (control == null && !mIsRequestedVisibleAwaitingControl) {
hide();
removeSurface();
@@ -164,6 +164,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
if (control != null) {
mIsRequestedVisibleAwaitingControl = false;
}
return true;
}
@Override

View File

@@ -122,8 +122,9 @@ public class InsetsSourceConsumer {
* animation should be run after setting the control.
* @param hideTypes An integer array with a single entry that determines which types a hide
* animation should be run after setting the control.
* @return Whether the control has changed from the server
*/
public void setControl(@Nullable InsetsSourceControl control,
public boolean setControl(@Nullable InsetsSourceControl control,
@InsetsType int[] showTypes, @InsetsType int[] hideTypes) {
if (mType == ITYPE_IME) {
ImeTracing.getInstance().triggerClientDump("InsetsSourceConsumer#setControl",
@@ -134,7 +135,7 @@ public class InsetsSourceConsumer {
mSourceControl.release(SurfaceControl::release);
mSourceControl = control;
}
return;
return false;
}
SurfaceControl oldLeash = mSourceControl != null ? mSourceControl.getLeash() : null;
@@ -201,6 +202,7 @@ public class InsetsSourceConsumer {
if (lastControl != null) {
lastControl.release(SurfaceControl::release);
}
return true;
}
@VisibleForTesting

View File

@@ -16,6 +16,10 @@
package com.android.server.wm.flicker.helpers
import android.view.WindowInsets.Type.ime
import android.view.WindowInsets.Type.navigationBars
import android.view.WindowInsets.Type.statusBars
import android.app.Instrumentation
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
@@ -25,6 +29,8 @@ import com.android.server.wm.traces.common.FlickerComponentName
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import java.util.regex.Pattern
class ImeAppAutoFocusHelper @JvmOverloads constructor(
instr: Instrumentation,
private val rotation: Int,
@@ -72,6 +78,7 @@ class ImeAppAutoFocusHelper @JvmOverloads constructor(
wmHelper.waitForAppTransitionIdle()
wmHelper.waitForFullScreenApp(
ActivityOptions.DIALOG_THEMED_ACTIVITY_COMPONENT_NAME.toFlickerComponent())
mInstrumentation.waitForIdleSync()
}
fun dismissDialog(wmHelper: WindowManagerStateHelper) {
val dialog = uiDevice.wait(
@@ -83,4 +90,27 @@ class ImeAppAutoFocusHelper @JvmOverloads constructor(
wmHelper.waitForAppTransitionIdle()
}
}
fun getInsetsVisibleFromDialog(type: Int): Boolean {
var insetsVisibilityTextView = uiDevice.wait(
Until.findObject(By.res("android:id/text1")), FIND_TIMEOUT)
if (insetsVisibilityTextView != null) {
var visibility = insetsVisibilityTextView.text.toString()
val matcher = when (type) {
ime() -> {
Pattern.compile("IME\\: (VISIBLE|INVISIBLE)").matcher(visibility)
}
statusBars() -> {
Pattern.compile("StatusBar\\: (VISIBLE|INVISIBLE)").matcher(visibility)
}
navigationBars() -> {
Pattern.compile("NavBar\\: (VISIBLE|INVISIBLE)").matcher(visibility)
}
else -> null
}
if (matcher != null && matcher.find()) {
return matcher.group(1).equals("VISIBLE")
}
}
return false
}
}

View File

@@ -16,6 +16,10 @@
package com.android.server.wm.flicker.ime
import android.view.WindowInsets.Type.ime
import android.view.WindowInsets.Type.navigationBars
import android.view.WindowInsets.Type.statusBars
import android.app.Instrumentation
import android.platform.test.annotations.Presubmit
import android.view.Surface
@@ -35,6 +39,8 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
/**
* Test IME snapshot mechanism won't apply when transitioning from non-IME focused dialog activity.
@@ -56,6 +62,10 @@ class LaunchAppShowImeAndDialogThemeAppTest(private val testSpec: FlickerTestPar
testApp.launchViaIntent(wmHelper)
wmHelper.waitImeShown()
testApp.startDialogThemedActivity(wmHelper)
// Verify IME insets isn't visible on dialog since it's non-IME focusable window
assertFalse(testApp.getInsetsVisibleFromDialog(ime()))
assertTrue(testApp.getInsetsVisibleFromDialog(statusBars()))
assertTrue(testApp.getInsetsVisibleFromDialog(navigationBars()))
}
}
teardown {

View File

@@ -17,11 +17,16 @@
package com.android.server.wm.flicker.testapp;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.graphics.Color;
import android.os.Bundle;
import android.view.WindowManager;
@@ -33,9 +38,12 @@ public class DialogThemedActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
getWindow().addFlags(FLAG_NOT_FOCUSABLE);
getWindow().getDecorView().setBackgroundColor(Color.TRANSPARENT);
TextView textView = new TextView(this);
textView.setText("This is a test dialog");
// Print SystemBars' insets visibility on this window for demonstrating during the test.
textView.setId(android.R.id.text1);
textView.setText("Insets visibility\n\n");
textView.setTextColor(Color.BLACK);
LinearLayout layout = new LinearLayout(this);
layout.setBackgroundColor(Color.GREEN);
@@ -51,7 +59,17 @@ public class DialogThemedActivity extends Activity {
attrs.flags = FLAG_DIM_BEHIND | FLAG_ALT_FOCUSABLE_IM;
dialog.getWindow().getDecorView().setLayoutParams(attrs);
dialog.setCanceledOnTouchOutside(true);
dialog.setOnShowListener(d -> textView.setText(textView.getText()
+ "IME: " + isInsetsVisible(dialog, ime()) + "\n"
+ "StatusBar: " + isInsetsVisible(dialog, statusBars()) + "\n"
+ "NavBar: " + isInsetsVisible(dialog, navigationBars()) + "\n")
);
dialog.show();
dialog.setOnDismissListener((d) -> finish());
}
private String isInsetsVisible(Dialog d, int type) {
return d.getWindow().getDecorView().getRootWindowInsets().isVisible(type) ? "VISIBLE"
: "INVISIBLE";
}
}