blob: c39aaa2ced6edfe414b4ae28c4558bad3a706a7d [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.server.wm.RoundedCornerTests.TestActivity.EXTRA_ORIENTATION;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowMetrics;
import androidx.test.rule.ActivityTestRule;
import com.android.compatibility.common.util.PollingCheck;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@Presubmit
@RunWith(Parameterized.class)
public class PrivacyIndicatorBoundsTests extends ActivityManagerTestBase {
private static final String TAG = PrivacyIndicatorBoundsTests.class.getSimpleName();
private static final long TIMEOUT_MS = 1000;
@Parameterized.Parameters(name= "{1}({0})")
public static Object[][] data() {
return new Object[][]{
{SCREEN_ORIENTATION_PORTRAIT, "SCREEN_ORIENTATION_PORTRAIT"},
{SCREEN_ORIENTATION_LANDSCAPE, "SCREEN_ORIENTATION_LANDSCAPE"},
{SCREEN_ORIENTATION_REVERSE_LANDSCAPE, "SCREEN_ORIENTATION_REVERSE_LANDSCAPE"},
{SCREEN_ORIENTATION_REVERSE_PORTRAIT, "SCREEN_ORIENTATION_REVERSE_PORTRAIT"},
};
}
@Parameterized.Parameter(0)
public int orientation;
@Parameterized.Parameter(1)
public String orientationName;
@Rule
public final ActivityTestRule<TestActivity> mTestActivity =
new ActivityTestRule<>(TestActivity.class, false /* initialTouchMode */,
false /* launchActivity */);
@Test
public void testStaticBoundsAreNotNull() {
// TODO(b/187757919): Allow Automotive to skip this test until privacy chip is implemented
// in immersive mode
assumeFalse(isCar());
final PrivacyIndicatorBoundsTests.TestActivity activity = mTestActivity.launchActivity(
new Intent().putExtra(EXTRA_ORIENTATION, orientation));
getInstrumentation().runOnMainSync(() -> {
activity.addChildWindow();
});
final View childWindowRoot = activity.getChildWindowRoot();
PollingCheck.waitFor(TIMEOUT_MS, () -> childWindowRoot.getWidth() > 0);
PollingCheck.waitFor(TIMEOUT_MS, () -> activity.getDispatchedInsets() != null);
mWmState.waitForValidState(mTestActivity.getActivity().getComponentName());
WindowInsets insets = activity.getDispatchedInsets();
assertNotNull(insets);
Rect screenBounds = activity.getScreenBounds();
assertNotNull(screenBounds);
Rect bounds = insets.getPrivacyIndicatorBounds();
assertNotNull(bounds);
final int windowingMode = mWmState
.getTaskDisplayArea(mTestActivity.getActivity().getComponentName())
.getWindowingMode();
final boolean inMultiWindowMode = windowingMode != WINDOWING_MODE_FULLSCREEN
&& windowingMode != WINDOWING_MODE_UNDEFINED;
if (!inMultiWindowMode) {
// Multi-window environments may place the indicator bounds somewhere other than the
// top (e.g. desktops may decide that the bottom-right corner has the highest visual
// priority). Other windowing modes
assertEquals(bounds.top, 0);
}
// TODO 188788786: Figure out why the screen bounds are different in cuttlefish,
// causing failures
// assertTrue(bounds + " not contained in " + screenBounds, screenBounds.contains(bounds));
assertTrue(bounds.left >= 0);
assertTrue(bounds.right >= 0);
}
public static class TestActivity extends Activity {
static final String EXTRA_ORIENTATION = "extra.orientation";
private View mChildWindowRoot;
private WindowInsets mDispatchedInsets;
private Rect mScreenBounds = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getWindow().getDecorView().getWindowInsetsController().hide(
android.view.WindowInsets.Type.statusBars());
getWindow().getAttributes().layoutInDisplayCutoutMode =
LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
if (getIntent() != null) {
setRequestedOrientation(getIntent().getIntExtra(
EXTRA_ORIENTATION, SCREEN_ORIENTATION_UNSPECIFIED));
}
}
void addChildWindow() {
final WindowMetrics windowMetrics = getWindowManager().getMaximumWindowMetrics();
mScreenBounds = windowMetrics.getBounds();
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
attrs.x = mScreenBounds.left;
attrs.y = mScreenBounds.top;
attrs.width = mScreenBounds.width();
attrs.height = mScreenBounds.height();
attrs.gravity = Gravity.LEFT | Gravity.TOP;
attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
attrs.flags = FLAG_NOT_FOCUSABLE;
attrs.setFitInsetsTypes(0);
mChildWindowRoot = new View(this);
mChildWindowRoot.setOnApplyWindowInsetsListener(
(v, insets) -> {
mDispatchedInsets = insets;
return insets;
});
getWindowManager().addView(mChildWindowRoot, attrs);
}
View getChildWindowRoot() {
return mChildWindowRoot;
}
WindowInsets getDispatchedInsets() {
return mDispatchedInsets;
}
Rect getScreenBounds() {
return mScreenBounds;
}
}
}