Merge "cts for service start/launch count"
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index cb5ce8e..768ddee 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1276,7 +1276,7 @@
</activity>
<activity android:name=".security.BiometricPromptBoundKeysTest"
- android:label="@string/sec_fingerprint_dialog_bound_key_test"
+ android:label="@string/sec_biometric_prompt_bound_key_test"
android:configChanges="keyboardHidden|orientation|screenSize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index a2f12d4..90d1200 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -166,6 +166,7 @@
complete this test. If available, this test should be run by using fingerprint authentication
as well as PIN/pattern/password authentication.
</string>
+
<string name="sec_fingerprint_bound_key_test">Fingerprint Bound Keys Test</string>
<string name="sec_fingerprint_bound_key_test_info">
This test ensures that Keystore cryptographic keys that are bound to fingerprint authentication
@@ -175,7 +176,12 @@
<string name="sec_fp_dialog_message">Authenticate now with fingerprint</string>
<string name="sec_fp_auth_failed">Authentication failed</string>
<string name="sec_start_test">Start Test</string>
- <string name="sec_fingerprint_dialog_bound_key_test">Fingerprint Bound Keys Test (System Dialog)</string>
+
+ <string name="sec_biometric_prompt_bound_key_test">Biometric Prompt Bound Keys Test</string>
+ <string name="sec_biometric_prompt_bound_key_test_info">
+ This test ensures that Keystore cryptographic keys that are bound to biometric authentication
+ are unusable without an authentication.
+ </string>
<!-- Strings for BluetoothActivity -->
<string name="bluetooth_test">Bluetooth Test</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/security/BiometricPromptBoundKeysTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/security/BiometricPromptBoundKeysTest.java
index a11eb82..7fece23 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/security/BiometricPromptBoundKeysTest.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/security/BiometricPromptBoundKeysTest.java
@@ -22,6 +22,8 @@
import android.os.Handler;
import android.os.Looper;
+import com.android.cts.verifier.R;
+
import java.util.concurrent.Executor;
public class BiometricPromptBoundKeysTest extends FingerprintBoundKeysTest {
@@ -63,7 +65,7 @@
mCancellationSignal = new CancellationSignal();
mDialogCallback = new DialogCallback();
mBiometricPrompt = new BiometricPrompt.Builder(getApplicationContext())
- .setTitle("Authenticate with fingerprint")
+ .setTitle("Authenticate with biometric")
.setNegativeButton("Cancel", mExecutor,
(DialogInterface dialogInterface, int which) -> {
if (which == DialogInterface.BUTTON_NEGATIVE) {
@@ -76,4 +78,14 @@
.CryptoObject(getCipher()),
mCancellationSignal, mExecutor, mDialogCallback);
}
+
+ @Override
+ protected int getTitleRes() {
+ return R.string.sec_biometric_prompt_bound_key_test;
+ }
+
+ @Override
+ protected int getDescriptionRes() {
+ return R.string.sec_biometric_prompt_bound_key_test_info;
+ }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java
index 83b84e7..1ae7a12 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java
@@ -16,9 +16,6 @@
package com.android.cts.verifier.security;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
import android.Manifest;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -26,21 +23,23 @@
import android.app.KeyguardManager;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.CancellationSignal;
-import android.util.Log;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.security.keystore.UserNotAuthenticatedException;
+import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -76,12 +75,20 @@
private FingerprintAuthDialogFragment mFingerprintDialog;
private Cipher mCipher;
+ protected int getTitleRes() {
+ return R.string.sec_fingerprint_bound_key_test;
+ }
+
+ protected int getDescriptionRes() {
+ return R.string.sec_fingerprint_bound_key_test_info;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sec_screen_lock_keys_main);
setPassFailButtonClickListeners();
- setInfoResources(R.string.sec_fingerprint_bound_key_test, R.string.sec_fingerprint_bound_key_test_info, -1);
+ setInfoResources(getTitleRes(), getDescriptionRes(), -1);
getPassButton().setEnabled(false);
requestPermissions(new String[]{Manifest.permission.USE_FINGERPRINT},
FINGERPRINT_PERMISSION_REQUEST_CODE);
diff --git a/common/device-side/nativetesthelper/jni/gtest_wrapper.cpp b/common/device-side/nativetesthelper/jni/gtest_wrapper.cpp
index cfc4475..a8b6b3e 100644
--- a/common/device-side/nativetesthelper/jni/gtest_wrapper.cpp
+++ b/common/device-side/nativetesthelper/jni/gtest_wrapper.cpp
@@ -120,21 +120,27 @@
virtual void OnTestPartResult(const testing::TestPartResult &testPartResult) override {
if (!testPartResult.passed()) {
- std::ostringstream messageStream;
- messageStream << testPartResult.file_name() << ":" << testPartResult.line_number()
- << "\n" << testPartResult.message();
- ScopedLocalRef<jstring> jmessage(mEnv, mEnv->NewStringUTF(messageStream.str().c_str()));
+ mCurrentTestError << "\n" << testPartResult.file_name() << ":" << testPartResult.line_number()
+ << "\n" << testPartResult.message() << "\n";
+ }
+ }
+
+ virtual void OnTestEnd(const testing::TestInfo&) override {
+ const std::string error = mCurrentTestError.str();
+
+ if (!error.empty()) {
+ ScopedLocalRef<jstring> jmessage(mEnv, mEnv->NewStringUTF(error.c_str()));
ScopedLocalRef<jobject> jthrowable(mEnv, mEnv->NewObject(gAssertionFailure.clazz,
gAssertionFailure.ctor, jmessage.get()));
ScopedLocalRef<jobject> jfailure(mEnv, mEnv->NewObject(gFailure.clazz,
gFailure.ctor, mCurrentTestDescription.get(), jthrowable.get()));
mEnv->CallVoidMethod(mRunNotifier, gRunNotifier.fireTestFailure, jfailure.get());
}
- }
- virtual void OnTestEnd(const testing::TestInfo&) override {
notify(gRunNotifier.fireTestFinished);
mCurrentTestDescription.reset();
+ mCurrentTestError.str("");
+ mCurrentTestError.clear();
}
void reportDisabledTests(const std::vector<std::string>& mangledNames) {
@@ -154,6 +160,7 @@
jobject mRunNotifier;
jstring mClassName;
ScopedLocalRef<jobject> mCurrentTestDescription;
+ std::ostringstream mCurrentTestError;
};
} // namespace
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml b/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml
index cfe80be..d3f8870 100644
--- a/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml
+++ b/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml
@@ -20,7 +20,9 @@
<application>
<uses-library android:name="android.test.runner" />
- <activity android:name=".DrawFramesActivity" android:label="GraphicsStats Test Activity" />
+ <activity android:name=".DrawFramesActivity"
+ android:label="GraphicsStats Test Activity"
+ android:theme="@style/DefaultTheme"/>
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/res/values/themes.xml b/hostsidetests/incident/apps/graphicsstatsapp/res/values/themes.xml
new file mode 100644
index 0000000..b3b1514
--- /dev/null
+++ b/hostsidetests/incident/apps/graphicsstatsapp/res/values/themes.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<resources>
+ <style name="DefaultTheme" parent="@android:style/Theme.Material.NoActionBar.Fullscreen">
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowFullscreen">true</item>
+ <item name="android:windowOverscan">true</item>
+ <item name="android:fadingEdge">none</item>
+ <item name="android:windowBackground">@android:color/white</item>
+ <item name="android:windowContentTransitions">false</item>
+ <item name="android:windowAnimationStyle">@null</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/hostsidetests/os/src/android/os/cts/OsHostTests.java b/hostsidetests/os/src/android/os/cts/OsHostTests.java
index 086f787..c557c9e 100644
--- a/hostsidetests/os/src/android/os/cts/OsHostTests.java
+++ b/hostsidetests/os/src/android/os/cts/OsHostTests.java
@@ -86,12 +86,22 @@
*/
@AppModeFull(reason = "Error message is different for instant app (Activity does not exist)")
public void testNonExportedActivities() throws Exception {
- // Attempt to launch the non-exported activity in the test app
- CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
- mDevice.executeShellCommand(START_NON_EXPORTED_ACTIVITY_COMMAND, outputReceiver);
- final String output = outputReceiver.getOutput();
+ // Run as unroot
+ boolean wasRoot = mDevice.isAdbRoot();
+ try {
+ mDevice.disableAdbRoot();
+ // Attempt to launch the non-exported activity in the test app
+ CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
+ mDevice.executeShellCommand(START_NON_EXPORTED_ACTIVITY_COMMAND, outputReceiver);
+ final String output = outputReceiver.getOutput();
- assertTrue(output.contains("Permission Denial") && output.contains(" not exported"));
+ assertTrue(output.contains("Permission Denial") && output.contains(" not exported"));
+ } finally {
+ // Restore back to original root state
+ if (wasRoot) {
+ mDevice.enableAdbRoot();
+ }
+ }
}
public void testIntentFilterHostValidation() throws Exception {
diff --git a/tests/framework/base/activitymanager/app/AndroidManifest.xml b/tests/framework/base/activitymanager/app/AndroidManifest.xml
index b0a780a..6e8f623 100755
--- a/tests/framework/base/activitymanager/app/AndroidManifest.xml
+++ b/tests/framework/base/activitymanager/app/AndroidManifest.xml
@@ -414,10 +414,13 @@
<activity android:name=".LaunchTestOnDestroyActivity"
android:exported="true"/>
-
<activity android:name=".ReportFullyDrawnActivity"
android:exported="true"/>
+ <activity android:name=".NoDisplayActivity"
+ android:exported="true"
+ android:theme="@android:style/Theme.NoDisplay"/>
+
<!-- Disable home activities by default or it may disturb other tests by
showing ResolverActivity when start home activity -->
<activity-alias android:name=".HomeActivity"
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/Components.java b/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
index 76b5b79..63c9bd3 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
@@ -65,6 +65,7 @@
public static final ComponentName MOVE_TASK_TO_BACK_ACTIVITY =
component("MoveTaskToBackActivity");
public static final ComponentName NIGHT_MODE_ACTIVITY = component("NightModeActivity");
+ public static final ComponentName NO_DISPLAY_ACTIVITY = component("NoDisplayActivity");
public static final ComponentName NO_HISTORY_ACTIVITY = component("NoHistoryActivity");
public static final ComponentName NO_RELAUNCH_ACTIVITY = component("NoRelaunchActivity");
public static final ComponentName NON_RESIZEABLE_ACTIVITY = component("NonResizeableActivity");
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/NoDisplayActivity.java b/tests/framework/base/activitymanager/app/src/android/server/am/NoDisplayActivity.java
new file mode 100644
index 0000000..1256f28
--- /dev/null
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/NoDisplayActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.server.am;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class NoDisplayActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ finish();
+ }
+}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
index 6f2ec8d..eb6e62c 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
@@ -122,10 +122,11 @@
launchActivity(DEBUGGABLE_APP_ACTIVITY);
executeShellCommand(getStopProfileCmd(DEBUGGABLE_APP_ACTIVITY));
- // Sleep for 0.1 second (100 milliseconds) so the generation of the profiling
+
+ // Sleep for 0.3 second (300 milliseconds) so the generation of the profiling
// file is complete.
try {
- Thread.sleep(100);
+ Thread.sleep(300);
} catch (InterruptedException e) {
//ignored
}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityMetricsLoggerTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityMetricsLoggerTests.java
index 6ef28c4..0e58956 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityMetricsLoggerTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityMetricsLoggerTests.java
@@ -17,7 +17,10 @@
package android.server.am;
import static android.os.SystemClock.sleep;
+import static android.server.am.Components.ENTRY_POINT_ALIAS_ACTIVITY;
+import static android.server.am.Components.NO_DISPLAY_ACTIVITY;
import static android.server.am.Components.REPORT_FULLY_DRAWN_ACTIVITY;
+import static android.server.am.Components.SINGLE_TASK_ACTIVITY;
import static android.server.am.Components.TEST_ACTIVITY;
import static android.server.am.Components.TRANSLUCENT_TEST_ACTIVITY;
@@ -104,6 +107,7 @@
final long postUptimeMs = SystemClock.uptimeMillis();
assertMetricsLogs(TEST_ACTIVITY, APP_TRANSITION, metricsLog, mPreUptimeMs, postUptimeMs);
+ assertTransitionIsStartingWindow(metricsLog);
final int windowsDrawnDelayMs =
(int) metricsLog.getTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS);
final String expectedLog =
@@ -129,10 +133,6 @@
assertThat("reported uptime should be before assertion time", startUptimeSec,
lessThanOrEqualTo(postUptimeSec));
assertNotNull("log should have delay", log.getTaggedData(APP_TRANSITION_DELAY_MS));
- assertEquals("transition should be started because of starting window",
- 1 /* APP_TRANSITION_STARTING_WINDOW */, log.getSubtype());
- assertNotNull("log should have starting window delay",
- log.getTaggedData(APP_TRANSITION_STARTING_WINDOW_DELAY_MS));
assertNotNull("log should have windows drawn delay",
log.getTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS));
long windowsDrawnDelayMs = (int) log.getTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS);
@@ -140,6 +140,13 @@
windowsDrawnDelayMs, lessThanOrEqualTo(testElapsedTimeMs));
}
+ private void assertTransitionIsStartingWindow(LogMaker log) {
+ assertEquals("transition should be started because of starting window",
+ 1 /* APP_TRANSITION_STARTING_WINDOW */, log.getSubtype());
+ assertNotNull("log should have starting window delay",
+ log.getTaggedData(APP_TRANSITION_STARTING_WINDOW_DELAY_MS));
+ }
+
private void assertEventLogsContainsLaunchTime(List<Event> events, ComponentName componentName,
int windowsDrawnDelayMs) {
for (Event event : events) {
@@ -265,6 +272,51 @@
metricsLog = getMetricsLog(THIRD_ACTIVITY, APP_TRANSITION);
assertMetricsLogs(THIRD_ACTIVITY, APP_TRANSITION, metricsLog, mPreUptimeMs,
postUptimeMs);
+ assertTransitionIsStartingWindow(metricsLog);
+ }
+
+ /**
+ * Launch a NoDisplay activity and verify it does not affect subsequent activity launch
+ * metrics. NoDisplay activities do not draw any windows and may be incorrectly identified as a
+ * trampoline activity. See b/80380150 (Long warm launch times reported in dev play console)
+ */
+ @Test
+ public void testNoDisplayActivityLaunch() {
+ getLaunchActivityBuilder()
+ .setUseInstrumentation()
+ .setTargetActivity(NO_DISPLAY_ACTIVITY)
+ .setWaitForLaunched(true)
+ .execute();
+
+ mPreUptimeMs = SystemClock.uptimeMillis();
+ getLaunchActivityBuilder()
+ .setUseInstrumentation()
+ .setTargetActivity(SECOND_ACTIVITY)
+ .setWaitForLaunched(true)
+ .execute();
+ final LogMaker metricsLog = getMetricsLog(SECOND_ACTIVITY, APP_TRANSITION);
+ final long postUptimeMs = SystemClock.uptimeMillis();
+ assertMetricsLogs(SECOND_ACTIVITY, APP_TRANSITION, metricsLog, mPreUptimeMs, postUptimeMs);
+ assertTransitionIsStartingWindow(metricsLog);
+ }
+
+ /**
+ * Launch an activity with a trampoline activity and verify launch metrics measures the complete
+ * launch sequence from when the trampoline activity is launching to when the target activity
+ * draws on screen.
+ */
+ @Test
+ public void testTrampolineActivityLaunch() {
+ // Launch a trampoline activity that will launch single task activity.
+ getLaunchActivityBuilder()
+ .setUseInstrumentation()
+ .setTargetActivity(ENTRY_POINT_ALIAS_ACTIVITY)
+ .setWaitForLaunched(true)
+ .execute();
+ final LogMaker metricsLog = getMetricsLog(SINGLE_TASK_ACTIVITY, APP_TRANSITION);
+ final long postUptimeMs = SystemClock.uptimeMillis();
+ assertMetricsLogs(SINGLE_TASK_ACTIVITY, APP_TRANSITION, metricsLog, mPreUptimeMs,
+ postUptimeMs);
}
private LogMaker getMetricsLog(ComponentName componentName, int category) {