Snap for 8909719 from f3e79eee4eb9b5bbf9ed0e196d7a4b68d84744c8 to mainline-networking-release

Change-Id: I9636ccefd5a0d05064e7790cd3c5ab244e5e7e10
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 3531e39..efa1de7 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -5234,6 +5234,7 @@
                        android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.watch:android.hardware.type.automotive" />
             <meta-data android:name="display_mode"
                        android:value="multi_display_mode" />
+            <meta-data android:name="CddTest" android:value="3.8.8/C-1-2"/>
         </activity>
 
         <activity android:name=".tv.MockTvInputSetupActivity"
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 186c5e2..4ddeca0 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -201,6 +201,9 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.security.cts.ActivityManagerTest$ActivityOptionsActivity" />
+        <activity android:name="android.security.cts.ActivityManagerTest$BaseActivity" />
+
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
index f16b8fb..a27a0b9 100644
--- a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
@@ -15,24 +15,43 @@
  */
 package android.security.cts;
 
+import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
+import static android.view.Window.FEATURE_ACTIVITY_TRANSITIONS;
+
 import static org.junit.Assert.*;
 
+import android.app.Activity;
 import android.app.ActivityManager;
-import android.app.ApplicationExitInfo;
+import android.app.ActivityOptions;
+import android.app.Application;
 import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.platform.test.annotations.AsbSecurityTest;
 import android.util.Log;
-import androidx.test.runner.AndroidJUnit4;
+import android.view.SurfaceControl;
+import android.window.IRemoteTransition;
+import android.window.IRemoteTransitionFinishedCallback;
+import android.window.RemoteTransition;
+import android.window.TransitionInfo;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.SystemUtil;
 import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
-import junit.framework.TestCase;
 
-import java.lang.reflect.InvocationTargetException;
-
-import org.junit.runner.RunWith;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.util.concurrent.Callable;
+
 
 @RunWith(AndroidJUnit4.class)
 public class ActivityManagerTest extends StsExtraBusinessLogicTestCase {
@@ -111,6 +130,51 @@
         assertTrue(Math.abs((double) mockPackagescores / totalLoops - 0.5d) < tolerance);
     }
 
+    @AsbSecurityTest(cveBugId = 237290578)
+    @Test
+    public void testActivityManager_stripTransitionFromActivityOptions() throws Exception {
+        Context targetContext = getInstrumentation().getTargetContext();
+
+        // Need to start a base activity since this requires shared element transition.
+        final Intent baseIntent = new Intent(targetContext, BaseActivity.class);
+        baseIntent.setFlags(FLAG_ACTIVITY_NO_USER_ACTION | FLAG_ACTIVITY_NEW_TASK);
+        final BaseActivity baseActivity = (BaseActivity) SystemUtil.callWithShellPermissionIdentity(
+                () -> getInstrumentation().startActivitySync(baseIntent));
+
+        RemoteTransition someRemote = new RemoteTransition(new IRemoteTransition.Stub() {
+            @Override
+            public void startAnimation(IBinder token, TransitionInfo info,
+                    SurfaceControl.Transaction t,
+                    IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
+                t.apply();
+                finishCallback.onTransitionFinished(null /* wct */, null /* sct */);
+            }
+
+            @Override
+            public void mergeAnimation(IBinder token, TransitionInfo info,
+                    SurfaceControl.Transaction t, IBinder mergeTarget,
+                    IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
+            }
+        });
+        ActivityOptions opts = ActivityOptions.makeRemoteTransition(someRemote);
+        assertTrue(waitUntil(() -> baseActivity.mResumed));
+        ActivityOptions sceneOpts = baseActivity.mSceneOpts;
+        assertEquals(ANIM_SCENE_TRANSITION, sceneOpts.getAnimationType());
+
+        // Prepare the intent
+        final Intent intent = new Intent(targetContext, ActivityOptionsActivity.class);
+        intent.setFlags(FLAG_ACTIVITY_NO_USER_ACTION | FLAG_ACTIVITY_NEW_TASK);
+        final Bundle optionsBundle = opts.toBundle();
+        optionsBundle.putAll(sceneOpts.toBundle());
+        final ActivityOptionsActivity activity =
+                (ActivityOptionsActivity) SystemUtil.callWithShellPermissionIdentity(
+                        () -> getInstrumentation().startActivitySync(intent, optionsBundle));
+        assertTrue(waitUntil(() -> activity.mResumed));
+
+        assertTrue(activity.mPreCreate || activity.mPreStart);
+        assertNull(activity.mReceivedTransition);
+    }
+
     /**
      * Run ActivityManager.getHistoricalProcessExitReasons once, return the time spent on it.
      */
@@ -122,4 +186,108 @@
         }
         return System.nanoTime() - start;
     }
+
+    private boolean waitUntil(Callable<Boolean> test) throws Exception {
+        long timeoutMs = 2000;
+        final long timeout = System.currentTimeMillis() + timeoutMs;
+        while (!test.call()) {
+            final long waitMs = timeout - System.currentTimeMillis();
+            if (waitMs <= 0) break;
+            try {
+                wait(timeoutMs);
+            } catch (InterruptedException e) {
+                // retry
+            }
+        }
+        return test.call();
+    }
+
+    public static class BaseActivity extends Activity {
+        public boolean mResumed = false;
+        public ActivityOptions mSceneOpts = null;
+
+        @Override
+        public void onCreate(Bundle i) {
+            super.onCreate(i);
+            getWindow().requestFeature(FEATURE_ACTIVITY_TRANSITIONS);
+            mSceneOpts = ActivityOptions.makeSceneTransitionAnimation(this);
+        }
+
+        @Override
+        public void onResume() {
+            super.onResume();
+            mResumed = true;
+        }
+    }
+
+    public static class ActivityOptionsActivity extends Activity {
+        public RemoteTransition mReceivedTransition = null;
+        public boolean mPreCreate = false;
+        public boolean mPreStart = false;
+        public boolean mResumed = false;
+
+        public ActivityOptionsActivity() {
+            registerActivityLifecycleCallbacks(new Callbacks());
+        }
+
+        private class Callbacks implements Application.ActivityLifecycleCallbacks {
+            private void accessOptions(Activity activity) {
+                try {
+                    Field mPendingOptions = Activity.class.getDeclaredField("mPendingOptions");
+                    mPendingOptions.setAccessible(true);
+                    ActivityOptions options = (ActivityOptions) mPendingOptions.get(activity);
+                    if (options != null) {
+                        mReceivedTransition = options.getRemoteTransition();
+                    }
+                } catch (ReflectiveOperationException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            @Override
+            public void onActivityPreCreated(Activity activity, Bundle i) {
+                mPreCreate = true;
+                if (mReceivedTransition == null) {
+                    accessOptions(activity);
+                }
+            }
+
+            @Override
+            public void onActivityPreStarted(Activity activity) {
+                mPreStart = true;
+                if (mReceivedTransition == null) {
+                    accessOptions(activity);
+                }
+            }
+
+            @Override
+            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+            }
+
+            @Override
+            public void onActivityStarted(Activity activity) {
+            }
+
+            @Override
+            public void onActivityResumed(Activity activity) {
+                mResumed = true;
+            }
+
+            @Override
+            public void onActivityPaused(Activity activity) {
+            }
+
+            @Override
+            public void onActivityStopped(Activity activity) {
+            }
+
+            @Override
+            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+            }
+
+            @Override
+            public void onActivityDestroyed(Activity activity) {
+            }
+        }
+    }
 }