summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/CtsVerifier/AndroidManifest.xml2
-rw-r--r--tests/tests/security/AndroidManifest.xml3
-rw-r--r--tests/tests/security/src/android/security/cts/ActivityManagerTest.java178
3 files changed, 178 insertions, 5 deletions
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 307e19907d4..efa1de71ecd 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -4208,6 +4208,7 @@
android:value="android.hardware.type.automotive:android.hardware.ram.low" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="CddTest" android:value="3.8.2/C-1-2,C-1-3" />
</activity>
<activity android:name=".deskclock.DeskClockTestsActivity"
@@ -5233,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 186c5e2ab7b..4ddeca0e23c 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 f16b8fb2111..a27a0b940cd 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 org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
+import java.util.concurrent.Callable;
-import org.junit.runner.RunWith;
-import org.junit.Test;
@RunWith(AndroidJUnit4.class)
public class ActivityManagerTest extends StsExtraBusinessLogicTestCase {
@@ -111,6 +130,51 @@ public class ActivityManagerTest extends StsExtraBusinessLogicTestCase {
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 @@ public class ActivityManagerTest extends StsExtraBusinessLogicTestCase {
}
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) {
+ }
+ }
+ }
}