Snap for 9573585 from fb15ea3e529c370e0bb160cc7de508015e3c180d to mainline-art-release

Change-Id: I614dd69ef6ce3c3c915f09a6d143db87c21dfd62
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java
index c3b6900..e8ed8c7 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java
@@ -1479,6 +1479,14 @@
         if (screenSize < (FIRST_SDK_IS_AT_LEAST_R ? 3.3 : 2.5)) return false;
         if (screenSize > 8.0) return false;
         if (!hasDeviceGotBattery()) return false;
+        // handheld nature is not exposed to package manager, so for now,
+        // in addition to physical screen size, the following checks are
+        // also required:
+        if (!pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) return false;
+        if (isWatch()) return false;
+        if (isTv()) return false;
+        if (isAutomotive()) return false;
+        if (isPc()) return false;
         return true;
     }
 
@@ -1487,6 +1495,14 @@
         if (screenSize < 7.0) return false;
         if (screenSize > 18.0) return false;
         if (!hasDeviceGotBattery()) return false;
+        // tablet nature is not exposed to package manager, so for now,
+        // in addition to physical screen size, the following checks are
+        // also required:
+        if (!pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) return false;
+        if (isWatch()) return false;
+        if (isTv()) return false;
+        if (isAutomotive()) return false;
+        if (isPc()) return false;
         return true;
     }
 
diff --git a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
index c0dfae1..5d792d9 100644
--- a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
+++ b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
@@ -29,6 +29,7 @@
 import org.w3c.dom.NodeList;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -37,6 +38,9 @@
 
 public final class CompatChangesValidConfigTest extends CompatChangeGatingTestCase {
 
+    private static final long RESTRICT_STORAGE_ACCESS_FRAMEWORK = 141600225L;
+    private static final String FEATURE_WATCH = "android.hardware.type.watch";
+
     private static final Set<String> OVERRIDES_ALLOWLIST = ImmutableSet.of(
         // This change id will sometimes remain enabled if an instrumentation test fails.
         "ALLOW_TEST_API_ACCESS"
@@ -114,6 +118,15 @@
                 changes.add(change);
             }
         }
+
+        // RESTRICT_STORAGE_ACCESS_FRAMEWORK not supported on wear
+        if (getDevice().hasFeature(FEATURE_WATCH)) {
+            for (Iterator<Change> it = changes.iterator(); it.hasNext();) {
+                if (it.next().changeId == RESTRICT_STORAGE_ACCESS_FRAMEWORK) {
+                    it.remove();
+                }
+            }
+        }
         return changes;
     }
 
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 7627600..5487fb4 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -27,6 +27,7 @@
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
     <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
@@ -217,6 +218,11 @@
         <activity android:name="android.security.cts.ActivityManagerTest$ActivityOptionsActivity" />
         <activity android:name="android.security.cts.ActivityManagerTest$BaseActivity" />
 
+        <activity android:name="android.security.cts.PackageInstallerTest$BackgroundLaunchActivity"
+            android:exported="true" />
+        <service android:name="android.security.cts.TestForegroundService"
+            android:exported="true" />
+
         <provider android:name="android.security.cts.CVE_2022_20358.PocContentProvider"
             android:authorities="android.security.cts.CVE_2022_20358.provider"
             android:enabled="true"
diff --git a/tests/tests/security/src/android/security/cts/PackageInstallerTest.java b/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
index ddea213..43124ec 100644
--- a/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
@@ -16,25 +16,46 @@
 
 package android.security.cts;
 
+import static android.content.Intent.EXTRA_REMOTE_CALLBACK;
+
 import android.Manifest;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.Instrumentation.ActivityMonitor;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.RemoteCallback;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.AsbSecurityTest;
+import android.provider.Settings;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.SystemUtil;
 import com.android.cts.install.lib.Install;
 import com.android.cts.install.lib.TestApp;
 import com.android.cts.install.lib.Uninstall;
 import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
 
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
 
 @RunWith(AndroidJUnit4.class)
 @AppModeFull
@@ -42,10 +63,41 @@
 
     private static final String TEST_APP_NAME = "android.security.cts.packageinstallertestapp";
 
+    private static final String KEY_ERROR = "key_error";
+    private static final String ACTION_COMMIT_WITH_ACTIVITY_INTENT_SENDER = TEST_APP_NAME
+            + ".action.COMMIT_WITH_ACTIVITY_INTENT_SENDER";
+    private static final String ACTION_COMMIT_WITH_FG_SERVICE_INTENT_SENDER = TEST_APP_NAME
+            + ".action.COMMIT_WITH_FG_SERVICE_INTENT_SENDER";
+
+    static final long DEFAULT_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(15);
+
     private static final TestApp TEST_APP = new TestApp(
             "PackageInstallerTestApp", TEST_APP_NAME, 1, /*isApex*/ false,
             "PackageInstallerTestApp.apk");
 
+    private static Context sContext = InstrumentationRegistry.getInstrumentation().getContext();
+    private static HandlerThread sResponseThread;
+    private static Handler sHandler;
+
+    private static final ComponentName BACKGROUND_RECEIVER_COMPONENT_NAME =
+            ComponentName.createRelative(TEST_APP_NAME, ".BackgroundReceiver");
+    private static final ComponentName BACKGROUND_LAUNCH_ACTIVITY_COMPONENT_NAME =
+            new ComponentName(sContext, BackgroundLaunchActivity.class);
+    private static final ComponentName FOREGROUND_SERVICE_COMPONENT_NAME =
+            new ComponentName(sContext, TestForegroundService.class);
+
+    @BeforeClass
+    public static void onBeforeClass() {
+        sResponseThread = new HandlerThread("response");
+        sResponseThread.start();
+        sHandler = new Handler(sResponseThread.getLooper());
+    }
+
+    @AfterClass
+    public static void onAfterClass() {
+        sResponseThread.quit();
+    }
+
     @Before
     public void setUp() {
         InstrumentationRegistry
@@ -74,4 +126,87 @@
         Assert.assertNotNull("Did not receive broadcast", packageName);
         Assert.assertEquals(TEST_APP_NAME, packageName);
     }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 230492955)
+    public void commitSessionInBackground_withActivityIntentSender_doesNotLaunchActivity()
+            throws Exception {
+        Install.single(TEST_APP).commit();
+        // An activity with the system uid in the foreground is necessary to this test.
+        goToSettings();
+        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        final ActivityMonitor monitor = instrumentation.addMonitor(
+                BackgroundLaunchActivity.class.getName(), null /* result */, false /* block */);
+        try {
+            sendActionToBackgroundReceiver(
+                    ACTION_COMMIT_WITH_ACTIVITY_INTENT_SENDER,
+                    BACKGROUND_LAUNCH_ACTIVITY_COMPONENT_NAME);
+
+            final Activity activity = monitor.waitForActivityWithTimeout(DEFAULT_TIMEOUT_MS);
+            if (activity != null) {
+                instrumentation.runOnMainSync(() -> activity.finish());
+            }
+            Assert.assertNull(activity);
+        } finally {
+            instrumentation.removeMonitor(monitor);
+        }
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 243377226)
+    public void commitSessionInBackground_withForegroundServiceIntentSender_doesNotStartService()
+            throws Exception {
+        Install.single(TEST_APP).commit();
+        // An activity with the system uid in the foreground is necessary to this test.
+        goToSettings();
+
+        sendActionToBackgroundReceiver(
+                ACTION_COMMIT_WITH_FG_SERVICE_INTENT_SENDER, FOREGROUND_SERVICE_COMPONENT_NAME);
+
+        final Service service =
+                TestForegroundService.waitFor(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        if (service != null) {
+            InstrumentationRegistry.getInstrumentation().runOnMainSync(
+                    () -> service.stopSelf());
+        }
+        Assert.assertNull(service);
+    }
+
+    private void goToSettings() {
+        SystemUtil.runShellCommand(
+                "am start -W --user current -a " + Settings.ACTION_SETTINGS);
+    }
+
+    private Bundle sendActionToBackgroundReceiver(String action, ComponentName statusReceiver)
+            throws Exception {
+        final Intent intent = new Intent(action)
+                .setComponent(BACKGROUND_RECEIVER_COMPONENT_NAME);
+        if (statusReceiver != null) {
+            intent.putExtra(Intent.EXTRA_COMPONENT_NAME, statusReceiver);
+        }
+        final ConditionVariable latch = new ConditionVariable();
+        final AtomicReference<Bundle> resultReference = new AtomicReference<>();
+        final RemoteCallback remoteCallback = new RemoteCallback(
+                bundle -> {
+                    resultReference.set(bundle);
+                    latch.open();
+                },
+                sHandler);
+        intent.putExtra(EXTRA_REMOTE_CALLBACK, remoteCallback);
+        sContext.sendBroadcast(intent);
+
+        if (!latch.block(DEFAULT_TIMEOUT_MS)) {
+            throw new TimeoutException(
+                    "Latch timed out while awaiting a response from background receiver");
+        }
+        final Bundle bundle = resultReference.get();
+        if (bundle != null && bundle.containsKey(KEY_ERROR)) {
+            throw Objects.requireNonNull(bundle.getSerializable(KEY_ERROR, Exception.class));
+        }
+        return bundle;
+    }
+
+    // An activity to receive status of a committed session
+    public static class BackgroundLaunchActivity extends Activity {
+    }
 }
diff --git a/tests/tests/security/src/android/security/cts/TestForegroundService.java b/tests/tests/security/src/android/security/cts/TestForegroundService.java
new file mode 100644
index 0000000..b09a925
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/TestForegroundService.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 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.security.cts;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+
+import org.junit.Assert;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+public class TestForegroundService extends Service {
+    private static BlockingQueue<Service> sQueue = new LinkedBlockingQueue<>();
+
+    private static final int FGS_NOTIFICATION_ID = 1;
+    private static final String NOTIFICATION_CHANNEL_ID =
+            TestForegroundService.class.getSimpleName();
+
+    @Override
+    public void onCreate() {
+        createNotificationChannelId(this, NOTIFICATION_CHANNEL_ID);
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        // When this service is started, make it a foreground service
+        final Notification.Builder builder =
+                new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
+                        .setSmallIcon(android.R.drawable.btn_star)
+                        .setContentTitle(NOTIFICATION_CHANNEL_ID)
+                        .setContentText(TestForegroundService.class.getName());
+        startForeground(FGS_NOTIFICATION_ID, builder.build());
+
+        try {
+            sQueue.put(this);
+        } catch (InterruptedException e) {
+            Assert.fail(e.toString());
+        }
+        return Service.START_NOT_STICKY;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    /** Create a notification channel. */
+    private static void createNotificationChannelId(Context context, String id) {
+        final NotificationManager nm =
+                context.getSystemService(NotificationManager.class);
+        final CharSequence name = id;
+        final String description = TestForegroundService.class.getName();
+        final int importance = NotificationManager.IMPORTANCE_DEFAULT;
+        final NotificationChannel channel = new NotificationChannel(
+                NOTIFICATION_CHANNEL_ID, name, importance);
+        channel.setDescription(description);
+        nm.createNotificationChannel(channel);
+    }
+
+    /** Wait until the service is started */
+    public static Service waitFor(long timeout, TimeUnit unit)
+            throws InterruptedException {
+        return sQueue.poll(timeout, unit);
+    }
+}
diff --git a/tests/tests/security/testdata/packageinstallertestapp.xml b/tests/tests/security/testdata/packageinstallertestapp.xml
index 5e6e066..ad39db5 100644
--- a/tests/tests/security/testdata/packageinstallertestapp.xml
+++ b/tests/tests/security/testdata/packageinstallertestapp.xml
@@ -34,5 +34,6 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
+        <receiver android:name=".BackgroundReceiver" android:exported="true" />
     </application>
 </manifest>
diff --git a/tests/tests/security/testdata/src/android/security/cts/packageinstallertestapp/BackgroundReceiver.java b/tests/tests/security/testdata/src/android/security/cts/packageinstallertestapp/BackgroundReceiver.java
new file mode 100644
index 0000000..8997082
--- /dev/null
+++ b/tests/tests/security/testdata/src/android/security/cts/packageinstallertestapp/BackgroundReceiver.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2023 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.security.cts.packageinstallertestapp;
+
+import static android.content.Intent.EXTRA_COMPONENT_NAME;
+import static android.content.Intent.EXTRA_REMOTE_CALLBACK;
+import static android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageInstaller.Session;
+import android.content.pm.PackageInstaller.SessionParams;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * A receiver to invoke APIs in the background.
+ */
+public class BackgroundReceiver extends BroadcastReceiver {
+    private static final String PKG_NAME = "android.security.cts.packageinstallertestapp";
+    private static final String KEY_ERROR = "key_error";
+    private static final String ACTION_COMMIT_WITH_ACTIVITY_INTENT_SENDER = PKG_NAME
+            + ".action.COMMIT_WITH_ACTIVITY_INTENT_SENDER";
+    private static final String ACTION_COMMIT_WITH_FG_SERVICE_INTENT_SENDER = PKG_NAME
+            + ".action.COMMIT_WITH_FG_SERVICE_INTENT_SENDER";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final RemoteCallback remoteCallback = intent.getParcelableExtra(EXTRA_REMOTE_CALLBACK,
+                RemoteCallback.class);
+        final ComponentName statusReceiver = intent.getParcelableExtra(
+                EXTRA_COMPONENT_NAME, ComponentName.class);
+        final String action = intent.getAction();
+
+        if (!isAppInBackground(context)) {
+            sendError(remoteCallback,
+                    new IllegalStateException("App is not in background"));
+            return;
+        }
+        try {
+            if (action.equals(ACTION_COMMIT_WITH_ACTIVITY_INTENT_SENDER)) {
+                final IntentSender intentSender = PendingIntent.getActivity(context,
+                                0 /* requestCode */,
+                                new Intent().setComponent(statusReceiver),
+                                PendingIntent.FLAG_IMMUTABLE)
+                        .getIntentSender();
+                sendInstallCommit(context, remoteCallback, intentSender);
+            } else if (action.equals(ACTION_COMMIT_WITH_FG_SERVICE_INTENT_SENDER)) {
+                final IntentSender intentSender = PendingIntent.getForegroundService(context,
+                                0 /* requestCode */,
+                                new Intent().setComponent(statusReceiver),
+                                PendingIntent.FLAG_IMMUTABLE)
+                        .getIntentSender();
+                sendInstallCommit(context, remoteCallback, intentSender);
+            } else {
+                sendError(remoteCallback,
+                        new IllegalArgumentException("Unknown action: " + action));
+            }
+        } catch (Throwable e) {
+            sendError(remoteCallback, e);
+        }
+    }
+
+    private static boolean isAppInBackground(Context context) {
+        final ActivityManager activityManager = context.getSystemService(ActivityManager.class);
+        final List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
+        final String packageName = context.getPackageName();
+        final RunningAppProcessInfo appInfo = appProcesses.stream()
+                .filter(app -> app.processName.equals(packageName))
+                .findAny().orElse(null);
+        if (appInfo != null
+                && appInfo.importance >= RunningAppProcessInfo.IMPORTANCE_SERVICE) {
+            return true;
+        }
+        return false;
+    }
+
+    private static void sendInstallCommit(Context context, RemoteCallback remoteCallback,
+            IntentSender intentSender) throws IOException {
+        final PackageInstaller packageInstaller =
+                context.getPackageManager().getPackageInstaller();
+        final int sessionId = packageInstaller.createSession(
+                new SessionParams(MODE_FULL_INSTALL));
+        final Session session = packageInstaller.openSession(sessionId);
+        session.commit(intentSender);
+        sendSuccess(remoteCallback);
+    }
+
+    private static void sendError(RemoteCallback remoteCallback, Throwable failure) {
+        Bundle result = new Bundle();
+        result.putSerializable(KEY_ERROR, failure);
+        remoteCallback.sendResult(result);
+    }
+
+    private static void sendSuccess(RemoteCallback remoteCallback) {
+        Bundle result = new Bundle();
+        remoteCallback.sendResult(result);
+    }
+}
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
index 767143c..5c1e926 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
@@ -434,6 +434,8 @@
             // TODO ntmyren: test TV indicator
         } else if (sPkgMgr.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
             // TODO ntmyren: test Auto indicator
+        } else if (sPkgMgr.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            // The privacy chips/indicators are not implemented on Wear
         } else {
             verifyMicrophoneChipHandheld(shouldBePresent);
         }