Added some test for visible behind activities.

Bug: 19225708
Change-Id: I26b2889063278e4deb0e48f1ce9354b39a1e1034
diff --git a/hostsidetests/services/activitymanager/app/AndroidManifest.xml b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
index 7e1662d..522fd71 100755
--- a/hostsidetests/services/activitymanager/app/AndroidManifest.xml
+++ b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
@@ -59,6 +59,19 @@
                   androidprv:alwaysFocusable="true"
                   android:exported="true"
         />
+        <activity android:name=".TranslucentActivity"
+                  android:theme="@style/Theme.Transparent"
+                  android:resizeable="true"
+                  android:supportsPictureInPicture="true"
+                  android:exported="true"
+                  android:taskAffinity="nobody.but.TranslucentActivity"
+        />
+        <activity android:name=".VisibleBehindActivity"
+                  android:resizeable="true"
+                  android:supportsPictureInPicture="true"
+                  android:exported="true"
+                  android:taskAffinity="nobody.but.VisibleBehindActivity"
+        />
     </application>
 </manifest>
 
diff --git a/hostsidetests/services/activitymanager/app/res/values/styles.xml b/hostsidetests/services/activitymanager/app/res/values/styles.xml
new file mode 100644
index 0000000..59ebad2
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/res/values/styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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
+  -->
+
+<resources>
+    <style name="Theme.Transparent" parent="android:Theme">
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowNoTitle">true</item>
+    </style>
+</resources>
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/TranslucentActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/TranslucentActivity.java
new file mode 100644
index 0000000..35c0e91
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/TranslucentActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 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.app;
+
+import android.app.Activity;
+
+public class TranslucentActivity extends Activity {
+}
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/VisibleBehindActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/VisibleBehindActivity.java
new file mode 100644
index 0000000..cc8f273
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/VisibleBehindActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 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.app;
+
+import android.app.Activity;
+import android.util.Log;
+
+public class VisibleBehindActivity extends Activity {
+    private static final String TAG = "VisibleBehindActivity";
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (requestVisibleBehind(true)) {
+            Log.e(TAG, "Failed to request visibility behind...");
+        }
+    }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java
index fc60b78..8bd3145 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java
@@ -125,4 +125,23 @@
     void assertFrontWindow(String msg, String windowName) {
         assertEquals(msg, windowName, mWmState.getFrontWindow());
     }
+
+    void assertVisibility(String activityName, boolean visible) {
+        final String activityComponentName =
+                ActivityManagerTestBase.getActivityComponentName(activityName);
+        final String windowName =
+                ActivityManagerTestBase.getWindowName(activityName);
+
+        final boolean activityVisible = mAmState.isActivityVisible(activityComponentName);
+        final boolean windowVisible = mWmState.isWindowVisible(windowName);
+
+        if (visible) {
+            assertTrue("Activity=" + activityComponentName + " must be visible.", activityVisible);
+            assertTrue("Window=" + windowName + " must be visible.", windowVisible);
+        } else {
+            assertFalse("Activity=" + activityComponentName + " must NOT be visible.",
+                    activityVisible);
+            assertFalse("Window=" + windowName + " must NOT be visible.", windowVisible);
+        }
+    }
 }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
index f6019d2..b194e7d 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
@@ -31,14 +31,13 @@
     private static final String AM_START_LAUNCH_TO_SIDE_ACTIVITY =
             "am start -n android.server.app/." + LAUNCH_TO_SIDE_ACTIVITY_NAME;
 
-    private static final String AM_FORCE_STOP_TEST = "am force-stop android.server.app";
     private static final String AM_FORCE_STOP_SETTINGS = "am force-stop com.android.settings";
     private static final String AM_MOVE_TASK = "am stack movetask ";
 
     @Override
-    protected void tearDown() {
+    protected void tearDown() throws Exception {
+        super.tearDown();
         try {
-            mDevice.executeShellCommand(AM_FORCE_STOP_TEST);
             mDevice.executeShellCommand(AM_FORCE_STOP_SETTINGS);
         } catch (DeviceNotAvailableException e) {
         }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
index 4f16295..0542ba4 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -22,8 +22,6 @@
 import java.lang.String;
 
 public class ActivityManagerPinnedStackTests extends ActivityManagerTestBase {
-    private static final boolean PRETEND_DEVICE_SUPPORTS_PIP = false;
-
     private static final String PIP_ACTIVITY_COMPONENT_NAME = "android.server.app/.PipActivity";
     private static final String PIP_WINDOW_NAME =
             "android.server.app/android.server.app.PipActivity";
@@ -45,8 +43,6 @@
 
     private static final String AM_START_PIP_ACTIVITY =
             "am start -n " + PIP_ACTIVITY_COMPONENT_NAME;
-    private static final String AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK =
-            "am stack move-top-activity-to-pinned-stack 1 0 0 500 500";
     private static final String AM_START_AUTO_ENTER_PIP_ACTIVITY =
             "am start -n " + AUTO_ENTER_PIP_ACTIVITY_COMPONENT_NAME;
     private static final String AM_START_ALWAYS_FOCUSABLE_PIP_ACTIVITY =
@@ -54,16 +50,6 @@
     private static final String AM_START_LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY =
             "am start -n " + LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY_COMPONENT_NAME;
 
-    private static final String AM_FORCE_STOP_TEST_PACKAGE = "am force-stop android.server.app";
-
-    @Override
-    protected void tearDown() {
-        try {
-            mDevice.executeShellCommand(AM_FORCE_STOP_TEST_PACKAGE);
-        } catch (DeviceNotAvailableException e) {
-        }
-    }
-
     public void testEnterPictureInPictureMode() throws Exception {
         final String[] commands = { AM_START_AUTO_ENTER_PIP_ACTIVITY };
         pinnedStackTester(AUTO_ENTER_PIP_ACTIVITY_COMPONENT_NAME,
@@ -71,13 +57,14 @@
     }
 
     public void testMoveTopActivityToPinnedStack() throws Exception {
-        final String[] commands = { AM_START_PIP_ACTIVITY, AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK };
+        final String[] commands = { AM_START_PIP_ACTIVITY,
+                AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK_COMMAND };
         pinnedStackTester(PIP_ACTIVITY_COMPONENT_NAME, PIP_WINDOW_NAME, commands, false);
     }
 
     public void testAlwaysFocusablePipActivity() throws Exception {
-        final String[] commands =
-                { AM_START_ALWAYS_FOCUSABLE_PIP_ACTIVITY, AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK };
+        final String[] commands = { AM_START_ALWAYS_FOCUSABLE_PIP_ACTIVITY,
+                AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK_COMMAND };
         pinnedStackTester(ALWAYS_FOCUSABLE_PIP_ACTIVITY_COMPONENT_NAME,
                 ALWAYS_FOCUSABLE_PIP_WINDOW_NAME, commands, true);
     }
@@ -97,8 +84,6 @@
 
     private void pinnedStackTester(String activiyName, String windowName, String[] commands,
             boolean isFocusable) throws Exception {
-        final boolean supportsPip = hasDeviceFeature("android.software.picture_in_picture")
-                || PRETEND_DEVICE_SUPPORTS_PIP;
 
         for (String command : commands) {
             mDevice.executeShellCommand(command);
@@ -107,7 +92,7 @@
         mAmWmState.computeState(mDevice);
         mAmWmState.assertSanity();
 
-        if (supportsPip) {
+        if (supportsPip()) {
             mAmWmState.assertContainsStack("Must contain pinned stack.", PINNED_STACK_ID);
             mAmWmState.assertFrontStack("Pinned stack must be the front stack.", PINNED_STACK_ID);
             mAmWmState.assertFrontWindow("Pinned window must be the front window.", windowName);
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
index a4ec55b..785e487 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
@@ -34,19 +34,10 @@
     private static final String SLOW_CREATE_ACTIVITY_NAME = "SlowCreateActivity";
     private static final String NO_RELAUNCH_ACTIVITY_NAME = "NoRelaunchActivity";
 
-    private static final String AM_FORCE_STOP_TEST = "am force-stop android.server.app";
     private static final String AM_MOVE_TASK = "am stack movetask ";
 
     private List<String> mTempWindowTokens = new ArrayList();
 
-    @Override
-    protected void tearDown() {
-        try {
-            mDevice.executeShellCommand(AM_FORCE_STOP_TEST);
-        } catch (DeviceNotAvailableException e) {
-        }
-    }
-
     public void testReplaceWindow_Dock_Relaunch() throws Exception {
         testReplaceWindow_Dock(true);
     }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java
index 7181fdd..7939c06 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java
@@ -182,6 +182,19 @@
         return mStacks.size();
     }
 
+    boolean isActivityVisible(String activityName) {
+        for (ActivityStack stack : mStacks) {
+            for (ActivityTask task : stack.mTasks) {
+               for (Activity activity : task.mActivities) {
+                   if (activity.name.equals(activityName)) {
+                       return activity.visible;
+                   }
+               }
+            }
+        }
+        return false;
+    }
+
     static class ActivityStack extends ActivityContainer {
 
         private static final Pattern TASK_ID_PATTERN = Pattern.compile("Task id #(\\d+)");
@@ -269,11 +282,21 @@
         private static final Pattern ORIG_ACTIVITY_PATTERN = Pattern.compile("origActivity=(\\S+)");
         private static final Pattern REAL_ACTIVITY_PATTERN = Pattern.compile("realActivity=(\\S+)");
 
+        private static final Pattern ACTIVITY_NAME_PATTERN = Pattern.compile(
+                "\\* Hist #(\\d+)\\: ActivityRecord\\{(\\S+) u(\\d+) (\\S+) t(\\d+)\\}");
+
+        private static final Pattern TASK_TYPE_PATTERN = Pattern.compile("autoRemoveRecents=(\\S+) "
+                + "isPersistable=(\\S+) numFullscreen=(\\d+) taskType=(\\d+) "
+                + "mTaskToReturnTo=(\\d+)");
+
         int mTaskId;
         int mStackId;
         Rectangle mLastNonFullscreenBounds;
         String mRealActivity;
         String mOrigActivity;
+        ArrayList<Activity> mActivities = new ArrayList();
+        int mTaskType = -1;
+        int mReturnToType = -1;
 
         private ActivityTask() {
         }
@@ -300,8 +323,21 @@
         }
 
         private void extract(LinkedList<String> dump, Pattern[] exitPatterns) {
+            final List<Pattern> activityExitPatterns = new ArrayList();
+            Collections.addAll(activityExitPatterns, exitPatterns);
+            activityExitPatterns.add(ACTIVITY_NAME_PATTERN);
+            final Pattern[] activityExitPatternsArray =
+                    activityExitPatterns.toArray(new Pattern[activityExitPatterns.size()]);
 
             while (!doneExtracting(dump, exitPatterns)) {
+                final Activity activity =
+                        Activity.create(dump, ACTIVITY_NAME_PATTERN, activityExitPatternsArray);
+
+                if (activity != null) {
+                    mActivities.add(activity);
+                    continue;
+                }
+
                 final String line = dump.pop().trim();
 
                 if (extractFullscreen(line)) {
@@ -346,6 +382,73 @@
                     }
                     continue;
                 }
+
+                matcher = TASK_TYPE_PATTERN.matcher(line);
+                if (matcher.matches()) {
+                    CLog.logAndDisplay(INFO, line);
+                    mTaskType = Integer.valueOf(matcher.group(4));
+                    mReturnToType = Integer.valueOf(matcher.group(5));
+                    continue;
+                }
+            }
+        }
+    }
+
+    static class Activity {
+        private static final Pattern VISIBILITY_PATTERN = Pattern.compile(
+                "keysPaused=(\\S+) inHistory=(\\S+) visible=(\\S+) sleeping=(\\S+) idle=(\\S+)");
+        private static final Pattern FRONT_OF_TASK_PATTERN = Pattern.compile("frontOfTask=(\\S+) "
+                + "task=TaskRecord\\{(\\S+) #(\\d+) A=(\\S+) U=(\\d+) StackId=(\\d+) sz=(\\d+)\\}");
+
+        String name;
+        boolean visible;
+        boolean frontOfTask;
+
+        private Activity() {
+        }
+
+        static Activity create(
+                LinkedList<String> dump, Pattern activityNamePattern, Pattern[] exitPatterns) {
+            final String line = dump.peek().trim();
+
+            final Matcher matcher = activityNamePattern.matcher(line);
+            if (!matcher.matches()) {
+                // Not an activity.
+                return null;
+            }
+            // For the activity name line we just read.
+            dump.pop();
+
+            final Activity activity = new Activity();
+            CLog.logAndDisplay(INFO, line);
+            activity.name = matcher.group(4);
+            CLog.logAndDisplay(INFO, activity.name);
+            activity.extract(dump, exitPatterns);
+            return activity;
+        }
+
+        private void extract(LinkedList<String> dump, Pattern[] exitPatterns) {
+
+            while (!doneExtracting(dump, exitPatterns)) {
+                final String line = dump.pop().trim();
+
+                Matcher matcher = VISIBILITY_PATTERN.matcher(line);
+                if (matcher.matches()) {
+                    CLog.logAndDisplay(INFO, line);
+                    final String visibleString = matcher.group(3);
+                    visible = Boolean.valueOf(visibleString);
+                    CLog.logAndDisplay(INFO, visibleString);
+                    continue;
+                }
+
+                matcher = FRONT_OF_TASK_PATTERN.matcher(line);
+                if (matcher.matches()) {
+                    CLog.logAndDisplay(INFO, line);
+                    final String frontOfTaskString = matcher.group(1);
+                    frontOfTask = Boolean.valueOf(frontOfTaskString);
+                    CLog.logAndDisplay(INFO, frontOfTaskString);
+                    continue;
+                }
             }
         }
     }
@@ -358,20 +461,6 @@
         protected boolean mFullscreen;
         protected Rectangle mBounds;
 
-        static boolean doneExtracting(LinkedList<String> dump, Pattern[] exitPatterns) {
-            if (dump.isEmpty()) {
-                return true;
-            }
-            final String line = dump.peek().trim();
-
-            for (Pattern pattern : exitPatterns) {
-                if (pattern.matcher(line).matches()) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
         boolean extractFullscreen(String line) {
             final Matcher matcher = FULLSCREEN_PATTERN.matcher(line);
             if (!matcher.matches()) {
@@ -405,4 +494,18 @@
             return rect;
         }
     }
+
+    static boolean doneExtracting(LinkedList<String> dump, Pattern[] exitPatterns) {
+        if (dump.isEmpty()) {
+            return true;
+        }
+        final String line = dump.peek().trim();
+
+        for (Pattern pattern : exitPatterns) {
+            if (pattern.matcher(line).matches()) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
index 953d185..1f67520 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
@@ -29,6 +29,7 @@
 import java.util.HashSet;
 
 public abstract class ActivityManagerTestBase extends DeviceTestCase {
+    private static final boolean PRETEND_DEVICE_SUPPORTS_PIP = false;
 
     // Constants copied from ActivityManager.StackId. If they are changed there, these must be
     // updated.
@@ -54,16 +55,32 @@
 
     private static final String AM_STACK_LIST = "am stack list";
 
+    private static final String AM_FORCE_STOP_TEST_PACKAGE = "am force-stop android.server.app";
+
+    protected static final String AM_START_HOME_ACTIVITY_COMMAND =
+            "am start -a android.intent.action.MAIN -c android.intent.category.HOME";
+
+    protected static final String AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK_COMMAND =
+            "am stack move-top-activity-to-pinned-stack 1 0 0 500 500";
+
     /** A reference to the device under test. */
     protected ITestDevice mDevice;
 
     private HashSet<String> mAvailableFeatures;
 
     protected static String getAmStartCmd(final String activityName) {
-        return "am start -n android.server.app/." + activityName;
+        return "am start -n " + getActivityComponentName(activityName);
     }
 
-    protected static String getWindowName(final String activityName) {
+    protected static String getAmStartCmdOverHome(final String activityName) {
+        return "am start --activity-task-on-home -n " + getActivityComponentName(activityName);
+    }
+
+    static String getActivityComponentName(final String activityName) {
+        return "android.server.app/." + activityName;
+    }
+
+    static String getWindowName(final String activityName) {
         return "android.server.app/android.server.app." + activityName;
     }
 
@@ -77,6 +94,15 @@
         mDevice = getDevice();
     }
 
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        try {
+            mDevice.executeShellCommand(AM_FORCE_STOP_TEST_PACKAGE);
+        } catch (DeviceNotAvailableException e) {
+        }
+    }
+
     // Utility method for debugging, not used directly here, but useful, so kept around.
     protected void printStacksAndTasks() throws DeviceNotAvailableException {
         CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
@@ -104,6 +130,11 @@
         return -1;
     }
 
+    protected boolean supportsPip() throws DeviceNotAvailableException {
+        return hasDeviceFeature("android.software.picture_in_picture")
+                || PRETEND_DEVICE_SUPPORTS_PIP;
+    }
+
     protected boolean hasDeviceFeature(String requiredFeature) throws DeviceNotAvailableException {
         if (mAvailableFeatures == null) {
             // TODO: Move this logic to ITestDevice.
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerVisibleBehindActivityTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerVisibleBehindActivityTests.java
new file mode 100644
index 0000000..1ceba88
--- /dev/null
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerVisibleBehindActivityTests.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 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.cts;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import java.lang.Exception;
+import java.lang.String;
+
+public class ActivityManagerVisibleBehindActivityTests extends ActivityManagerTestBase {
+    private static final String TRANSLUCENT_ACTIVITY = "TranslucentActivity";
+    private static final String VISIBLE_BEHIND_ACTIVITY = "VisibleBehindActivity";
+    private static final String PIP_ACTIVITY = "PipActivity";
+
+    public void testVisibleBehindHomeActivity() throws Exception {
+        mDevice.executeShellCommand(getAmStartCmd(VISIBLE_BEHIND_ACTIVITY));
+        mDevice.executeShellCommand(AM_START_HOME_ACTIVITY_COMMAND);
+
+        mAmWmState.computeState(mDevice);
+        mAmWmState.assertSanity();
+        mAmWmState.assertContainsStack(
+                "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
+        mAmWmState.assertFrontStack("Home stack must be the front stack.", HOME_STACK_ID);
+        mAmWmState.assertVisibility(
+                VISIBLE_BEHIND_ACTIVITY, hasDeviceFeature("android.software.leanback"));
+    }
+
+    public void testVisibleBehindOtherActivity_NotOverHome() throws Exception {
+        mDevice.executeShellCommand(getAmStartCmd(VISIBLE_BEHIND_ACTIVITY));
+        mDevice.executeShellCommand(getAmStartCmd(TRANSLUCENT_ACTIVITY));
+
+        mAmWmState.computeState(mDevice);
+        mAmWmState.assertSanity();
+        mAmWmState.assertVisibility(VISIBLE_BEHIND_ACTIVITY, true);
+        mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
+    }
+
+    public void testVisibleBehindOtherActivity_OverHome() throws Exception {
+        mDevice.executeShellCommand(getAmStartCmdOverHome(VISIBLE_BEHIND_ACTIVITY));
+        mDevice.executeShellCommand(getAmStartCmdOverHome(TRANSLUCENT_ACTIVITY));
+
+        mAmWmState.computeState(mDevice);
+        mAmWmState.assertSanity();
+        mAmWmState.assertVisibility(VISIBLE_BEHIND_ACTIVITY, true);
+        mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
+    }
+
+    public void testTranslucentActivityOnTopOfPinnedStack() throws Exception {
+        if (!supportsPip()) {
+            return;
+        }
+
+        mDevice.executeShellCommand(getAmStartCmdOverHome(PIP_ACTIVITY));
+        mDevice.executeShellCommand(AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK_COMMAND);
+        mDevice.executeShellCommand(getAmStartCmdOverHome(TRANSLUCENT_ACTIVITY));
+        mDevice.executeShellCommand(AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK_COMMAND);
+
+        mAmWmState.computeState(mDevice);
+        mAmWmState.assertSanity();
+        mAmWmState.assertFrontStack("Pinned stack must be the front stack.", PINNED_STACK_ID);
+        mAmWmState.assertVisibility(PIP_ACTIVITY, true);
+        mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
+    }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java b/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java
index 169e245..949dc9b 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java
@@ -213,6 +213,15 @@
         return false;
     }
 
+    boolean isWindowVisible(String windowName) {
+        for (String window : mWindows) {
+            if (window.equals(windowName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void reset() {
         mSysDump.clear();
         mStacks.clear();