Merge "Set Window#setDecorFitsSystemWindows on Android R+ and View#setFitsSystemWindows on Android Q- instead of using WindowCompat#setDecorFitsSystemWindows" into androidx-main
diff --git a/car/app/app-automotive/src/main/java/androidx/car/app/activity/BaseCarAppActivity.java b/car/app/app-automotive/src/main/java/androidx/car/app/activity/BaseCarAppActivity.java
index 2ccd6f3..fd2dde3 100644
--- a/car/app/app-automotive/src/main/java/androidx/car/app/activity/BaseCarAppActivity.java
+++ b/car/app/app-automotive/src/main/java/androidx/car/app/activity/BaseCarAppActivity.java
@@ -35,6 +35,7 @@
import android.util.Log;
import android.view.PixelCopy;
import android.view.View;
+import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.ImageView;
@@ -43,6 +44,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
import androidx.annotation.VisibleForTesting;
import androidx.car.app.SessionInfo;
import androidx.car.app.activity.renderer.ICarAppActivity;
@@ -62,7 +64,6 @@
import androidx.car.app.serialization.BundlerException;
import androidx.car.app.utils.ThreadUtils;
import androidx.core.view.DisplayCutoutCompat;
-import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Lifecycle;
@@ -86,6 +87,8 @@
View mActivityContainerView;
View mLocalContentContainerView;
+ boolean mDecorFitsSystemWindows = false;
+
/**
* Displays the snapshot of the surface view to avoid a visual glitch when app comes
* to foreground. This view sits behind the surface view and will be visible only when surface
@@ -251,6 +254,14 @@
return new WindowInsets.Builder(insets).setInsets(
WindowInsets.Type.displayCutout(), Insets.NONE).build();
}
+
+ @DoNotInline
+ static void setDecorFitsSystemWindows(BaseCarAppActivity activity, Window window,
+ boolean decorFitsSystemWindows) {
+ // Set mDecorFitsSystemWindows so we can retrieve its value for testing.
+ activity.mDecorFitsSystemWindows = decorFitsSystemWindows;
+ window.setDecorFitsSystemWindows(decorFitsSystemWindows);
+ }
}
@Override
@@ -325,20 +336,30 @@
// Remove display cut-out insets on DecorView
getWindow().getDecorView().setOnApplyWindowInsetsListener((view, insets) -> {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ if (Build.VERSION.SDK_INT >= 30) {
insets = Api30Impl.getDecorViewInsets(insets);
}
return view.onApplyWindowInsets(insets);
});
- // IMPORTANT: The SystemUiVisibility applied here must match the insets provided to the
- // host in OnApplyWindowInsetsListener above. Failing to do so would cause a mismatch
- // between the insets applied to the content on the hosts side vs. the actual visible
- // window available on the client side.
- WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
+ if (Build.VERSION.SDK_INT >= 30) {
+ Api30Impl.setDecorFitsSystemWindows(this, getWindow(), false);
+ } else {
+ getWindow().getDecorView().setFitsSystemWindows(false);
+ }
mActivityContainerView.requestApplyInsets();
}
+ /**
+ * TODO(b/283985939): Workaround for testing {@code setDecorFitsSystemWindows} for older
+ * versions of Roboelectric that don't support {@code getDecorFitsSystemWindows}. Remove this
+ * once Roboelectric version is upgraded to v4.10.3.
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ public boolean getDecorFitsSystemWindows() {
+ return mDecorFitsSystemWindows;
+ }
+
/** Takes a snapshot of the surface view and puts it in the surfaceSnapshotView if succeeded. */
private void takeSurfaceSnapshot() {
// Nothing to do if the surface is not ready yet.
diff --git a/car/app/app-automotive/src/test/java/androidx/car/app/activity/CarAppActivityTest.java b/car/app/app-automotive/src/test/java/androidx/car/app/activity/CarAppActivityTest.java
index 02804af..f371f31 100644
--- a/car/app/app-automotive/src/test/java/androidx/car/app/activity/CarAppActivityTest.java
+++ b/car/app/app-automotive/src/test/java/androidx/car/app/activity/CarAppActivityTest.java
@@ -42,6 +42,7 @@
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
@@ -74,6 +75,7 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
import org.robolectric.annotation.internal.DoNotInstrument;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowPackageManager;
@@ -396,6 +398,39 @@
}
+ @Test
+ @Config(maxSdk = Build.VERSION_CODES.Q)
+ public void testFitsSystemWindows_whenQAndBelow_shouldSetFitsSystemWindowsToFalse() {
+ Intent newIntent = new Intent(getApplicationContext(), CarAppActivity.class);
+ try (ActivityScenario<CarAppActivity> scenario = ActivityScenario.launch(newIntent)) {
+ scenario.onActivity(activity -> {
+ try {
+ assertThat(
+ activity.getWindow().getDecorView().getFitsSystemWindows()).isFalse();
+ } catch (Exception e) {
+ fail(Log.getStackTraceString(e));
+ }
+ });
+
+ }
+ }
+
+ @Test
+ @Config(minSdk = Build.VERSION_CODES.R)
+ public void testDecorFitsSystemWindows_whenRAndAbove_shouldSetDecorFitsSystemWindowsToFalse() {
+ Intent newIntent = new Intent(getApplicationContext(), CarAppActivity.class);
+ try (ActivityScenario<CarAppActivity> scenario = ActivityScenario.launch(newIntent)) {
+ scenario.onActivity(activity -> {
+ try {
+ assertThat(activity.getDecorFitsSystemWindows()).isFalse();
+ } catch (Exception e) {
+ fail(Log.getStackTraceString(e));
+ }
+ });
+
+ }
+ }
+
interface CarActivityAction {
void accept(ActivityScenario<CarAppActivity> scenario, CarAppActivity activity)
throws Exception;