Merge "Add simple tests for Path#approximate" into oc-dev
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index 54fdb08..a8b9863 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -391,8 +391,6 @@
s,e,_,_,_ = cam.do_3a(get_results=True, do_af=False)
req = its.objects.manual_capture_request(s, e)
fps = 30
- if "60fps" in sys.argv:
- fps = 60
req["android.control.aeTargetFpsRange"] = [fps, fps]
print "Capturing %dx%d with sens. %d, exp. time %.1fms" % (
W, H, s, e*NSEC_TO_MSEC)
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index e0ac96f..77513c5 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -42,6 +42,10 @@
private static final String EPHEMERAL_2_APK = "CtsEphemeralTestsEphemeralApp2.apk";
private static final String EPHEMERAL_2_PKG = "com.android.cts.ephemeralapp2";
+ // a normally installed application with implicitly exposed components
+ private static final String IMPLICIT_APK = "CtsEphemeralTestsImplicitApp.apk";
+ private static final String IMPLICIT_PKG = "com.android.cts.implicitapp";
+
// a normally installed application with no exposed components
private static final String UNEXPOSED_APK = "CtsEphemeralTestsUnexposedApp.apk";
private static final String UNEXPOSED_PKG = "com.android.cts.unexposedapp";
@@ -143,6 +147,7 @@
private void installTestPackages() throws Exception {
installApp(NORMAL_APK);
installApp(UNEXPOSED_APK);
+ installApp(IMPLICIT_APK);
installEphemeralApp(EPHEMERAL_1_APK);
installEphemeralApp(EPHEMERAL_2_APK);
}
@@ -150,6 +155,7 @@
private void uninstallTestPackages() throws Exception {
getDevice().uninstallPackage(NORMAL_PKG);
getDevice().uninstallPackage(UNEXPOSED_PKG);
+ getDevice().uninstallPackage(IMPLICIT_PKG);
getDevice().uninstallPackage(EPHEMERAL_1_PKG);
getDevice().uninstallPackage(EPHEMERAL_2_PKG);
}
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
index 260f37a..8f44f89 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
@@ -392,9 +392,17 @@
// startViewIntent.addCategory(Intent.CATEGORY_BROWSABLE);
// startViewIntent.setData(Uri.parse("https://cts.google.com/normal"));
// InstrumentationRegistry.getContext().startActivity(startViewIntent, null /*options*/);
-// final BroadcastResult testResult = getResult();
-// assertThat("com.android.cts.normalapp", is(testResult.packageName));
-// assertThat("NormalWebActivity", is(testResult.activityName));
+// final TestResult testResult = getResult();
+// assertThat(testResult.getPackageName(),
+// is("com.android.cts.normalapp"));
+// assertThat(testResult.getComponentName(),
+// is("NormalWebActivity"));
+// assertThat(testResult.getStatus(),
+// is("PASS"));
+// assertThat(testResult.getEphemeralPackageInfoExposed(),
+// is(false));
+// assertThat(testResult.getException(),
+// is(nullValue()));
// }
// We don't attempt to start the service since it will merely return and not
@@ -447,7 +455,7 @@
@Test
public void testStartExposed() throws Exception {
- // start the exposed activity
+ // start the explicitly exposed activity
{
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
InstrumentationRegistry
@@ -465,7 +473,7 @@
is(nullValue()));
}
- // start the exposed activity; directed package
+ // start the explicitly exposed activity; directed package
{
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
startExposedIntent.setPackage("com.android.cts.normalapp");
@@ -484,7 +492,7 @@
is(nullValue()));
}
- // start the exposed activity; directed component
+ // start the explicitly exposed activity; directed component
{
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
startExposedIntent.setComponent(new ComponentName(
@@ -504,6 +512,34 @@
is(nullValue()));
}
+ // start the implicitly exposed activity; directed package
+ {
+ try {
+ final Intent startExposedIntent = new Intent(Intent.ACTION_VIEW);
+ startExposedIntent.setPackage("com.android.cts.implicitapp");
+ startExposedIntent.addCategory(Intent.CATEGORY_BROWSABLE);
+ startExposedIntent.setData(Uri.parse("https://cts.google.com/implicit"));
+ InstrumentationRegistry
+ .getContext().startActivity(startExposedIntent, null /*options*/);
+ fail("activity started");
+ } catch (ActivityNotFoundException expected) { }
+ }
+
+ // start the implicitly exposed activity; directed component
+ {
+ try {
+ final Intent startExposedIntent = new Intent(Intent.ACTION_VIEW);
+ startExposedIntent.setComponent(new ComponentName(
+ "com.android.cts.implicitapp",
+ "com.android.cts.implicitapp.ImplicitActivity"));
+ startExposedIntent.addCategory(Intent.CATEGORY_BROWSABLE);
+ startExposedIntent.setData(Uri.parse("https://cts.google.com/implicit"));
+ InstrumentationRegistry
+ .getContext().startActivity(startExposedIntent, null /*options*/);
+ fail("activity started");
+ } catch (ActivityNotFoundException expected) { }
+ }
+
// start the exposed service; directed package
{
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
@@ -879,19 +915,28 @@
@Test
public void testPackageInfo() throws Exception {
PackageInfo info;
- // Test own package info.
+ // own package info
info = InstrumentationRegistry.getContext().getPackageManager()
.getPackageInfo("com.android.cts.ephemeralapp1", 0);
assertThat(info.packageName,
is("com.android.cts.ephemeralapp1"));
- // Test exposed app package info.
+ // exposed application package info
info = InstrumentationRegistry.getContext().getPackageManager()
.getPackageInfo("com.android.cts.normalapp", 0);
assertThat(info.packageName,
is("com.android.cts.normalapp"));
- // Test unexposed app package info not accessible.
+ // implicitly exposed application package info not accessible
+ try {
+ info = InstrumentationRegistry.getContext().getPackageManager()
+ .getPackageInfo("com.android.cts.implicitapp", 0);
+ fail("Instant apps should not be able to access PackageInfo for an app that does not" +
+ " expose itself to Instant Apps.");
+ } catch (PackageManager.NameNotFoundException expected) {
+ }
+
+ // unexposed application package info not accessible
try {
info = InstrumentationRegistry.getContext().getPackageManager()
.getPackageInfo("com.android.cts.unexposedapp", 0);
@@ -899,7 +944,8 @@
" expose itself to Instant Apps.");
} catch (PackageManager.NameNotFoundException expected) {
}
- // Test Instant App (with visibleToInstantApp components) still isn't accessible.
+
+ // instant application (with visibleToInstantApp component) package info not accessible
try {
info = InstrumentationRegistry.getContext().getPackageManager()
.getPackageInfo("com.android.cts.ephemeralapp2", 0);
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/Android.mk
new file mode 100644
index 0000000..453dbcb
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/Android.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ cts-aia-util \
+ android-support-test \
+ legacy-android-test
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := CtsEphemeralTestsImplicitApp
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/AndroidManifest.xml
new file mode 100644
index 0000000..f202a0a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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="com.android.cts.implicitapp">
+ <uses-sdk
+ android:minSdkVersion="24" />
+
+ <application
+ android:label="@string/app_name">
+ <uses-library android:name="android.test.runner" />
+ <activity
+ android:name=".ImplicitActivity"
+ android:theme="@android:style/Theme.NoDisplay">
+ <!-- TEST: implicitly exposes this activity to instant apps -->
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="https" />
+ <data android:host="cts.google.com" />
+ <data android:path="/implicit" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.implicitapp" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/res/values/strings.xml
new file mode 100644
index 0000000..90393aa
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/res/values/strings.xml
@@ -0,0 +1,18 @@
+<!-- Copyright (C) 2017 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="app_name">ImplicitlyExposedApp</string>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/src/com/android/cts/implicitapp/ImplicitActivity.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/src/com/android/cts/implicitapp/ImplicitActivity.java
new file mode 100644
index 0000000..feffd84
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/src/com/android/cts/implicitapp/ImplicitActivity.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 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.implicitapp;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.cts.util.TestResult;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.List;
+
+public class ImplicitActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ boolean canAccessInstantApp = false;
+ String exception = null;
+ try {
+ canAccessInstantApp = tryAccessingInstantApp();
+ } catch (Throwable t) {
+ exception = t.getClass().getName();
+ }
+
+ TestResult.getBuilder()
+ .setPackageName("com.android.cts.implicitapp")
+ .setComponentName("ImplicitActivity")
+ .setStatus("PASS")
+ .setException(exception)
+ .setEphemeralPackageInfoExposed(canAccessInstantApp)
+ .build()
+ .broadcast(this);
+ finish();
+ }
+
+ private boolean tryAccessingInstantApp() throws NameNotFoundException {
+ final PackageInfo info = getPackageManager()
+ .getPackageInfo("com.android.cts.ephemeralapp1", 0 /*flags*/);
+ return (info != null);
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAdminService/package1/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAdminService/package1/AndroidManifest.xml
index 5d63794..47f3c6a6 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdminService/package1/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAdminService/package1/AndroidManifest.xml
@@ -32,7 +32,8 @@
<service
android:name=".MyService"
- android:exported="false">
+ android:exported="true"
+ android:permission="android.permission.BIND_DEVICE_ADMIN" >
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_SERVICE" />
</intent-filter>
diff --git a/hostsidetests/devicepolicy/app/DeviceAdminService/package2/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAdminService/package2/AndroidManifest.xml
index 5d63794..0ff8e68 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdminService/package2/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAdminService/package2/AndroidManifest.xml
@@ -32,7 +32,8 @@
<service
android:name=".MyService"
- android:exported="false">
+ android:exported="false"
+ android:permission="android.permission.BIND_DEVICE_ADMIN" >
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_SERVICE" />
</intent-filter>
diff --git a/hostsidetests/devicepolicy/app/DeviceAdminService/package3/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAdminService/package3/AndroidManifest.xml
index 84dacbd..5d63794 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdminService/package3/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAdminService/package3/AndroidManifest.xml
@@ -32,7 +32,7 @@
<service
android:name=".MyService"
- android:exported="true">
+ android:exported="false">
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_SERVICE" />
</intent-filter>
diff --git a/hostsidetests/devicepolicy/app/DeviceAdminService/package4/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAdminService/package4/AndroidManifest.xml
index 1b8497d..b43d086 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdminService/package4/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAdminService/package4/AndroidManifest.xml
@@ -31,14 +31,14 @@
</receiver>
<service
android:name=".MyService"
- android:exported="false">
+ android:permission="android.permission.BIND_DEVICE_ADMIN" >
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_SERVICE" />
</intent-filter>
</service>
<service
android:name=".MyService2"
- android:exported="false">
+ android:permission="android.permission.BIND_DEVICE_ADMIN" >
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_SERVICE" />
</intent-filter>
diff --git a/hostsidetests/devicepolicy/app/DeviceAdminService/packageb/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAdminService/packageb/AndroidManifest.xml
index 894d13c..95d203a 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdminService/packageb/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAdminService/packageb/AndroidManifest.xml
@@ -31,7 +31,8 @@
</receiver>
<service
android:name="com.android.cts.deviceadminservice.MyService"
- android:exported="false">
+ android:exported="true"
+ android:permission="android.permission.BIND_DEVICE_ADMIN" >
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_SERVICE" />
</intent-filter>
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
index f60abfa..79d3c3f 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
@@ -21,8 +21,8 @@
import android.app.Activity;
import android.app.ActivityOptions;
+import android.app.PictureInPictureParams;
import android.content.BroadcastReceiver;
-import android.app.PictureInPictureArgs;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -32,6 +32,7 @@
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
+import android.util.Rational;
import android.view.WindowManager;
public class PipActivity extends AbstractLifecycleLogActivity {
@@ -58,12 +59,23 @@
// Calls enterPictureInPicture() on creation
private static final String EXTRA_ENTER_PIP = "enter_pip";
// Used with EXTRA_AUTO_ENTER_PIP, value specifies the aspect ratio to enter PIP with
- private static final String EXTRA_ENTER_PIP_ASPECT_RATIO = "enter_pip_aspect_ratio";
+ private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR =
+ "enter_pip_aspect_ratio_numerator";
+ // Used with EXTRA_AUTO_ENTER_PIP, value specifies the aspect ratio to enter PIP with
+ private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR =
+ "enter_pip_aspect_ratio_denominator";
// Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value
- private static final String EXTRA_SET_ASPECT_RATIO = "set_aspect_ratio";
+ private static final String EXTRA_SET_ASPECT_RATIO_NUMERATOR = "set_aspect_ratio_numerator";
+ // Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value
+ private static final String EXTRA_SET_ASPECT_RATIO_DENOMINATOR = "set_aspect_ratio_denominator";
// Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value with a
// fixed delay
- private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY = "set_aspect_ratio_with_delay";
+ private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR =
+ "set_aspect_ratio_with_delay_numerator";
+ // Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value with a
+ // fixed delay
+ private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR =
+ "set_aspect_ratio_with_delay_denominator";
// Adds a click listener to finish this activity when it is clicked
private static final String EXTRA_TAP_TO_FINISH = "tap_to_finish";
// Calls requestAutoEnterPictureInPicture() with the value provided
@@ -102,14 +114,17 @@
startIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(startIntent);
- if (intent.hasExtra(EXTRA_SET_ASPECT_RATIO_WITH_DELAY)) {
+ if (intent.hasExtra(EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR)
+ && intent.hasExtra(EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR)) {
// Ugly, but required to wait for the startActivity to actually start
// the activity...
mHandler.postDelayed(() -> {
- PictureInPictureArgs args = new PictureInPictureArgs();
- args.setAspectRatio(Float.valueOf(intent.getStringExtra(
- EXTRA_SET_ASPECT_RATIO_WITH_DELAY)));
- setPictureInPictureArgs(args);
+ final PictureInPictureParams.Builder builder =
+ new PictureInPictureParams.Builder();
+ builder.setAspectRatio(getAspectRatio(intent,
+ EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR,
+ EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR));
+ setPictureInPictureParams(builder.build());
}, 100);
}
break;
@@ -142,26 +157,33 @@
// Enter picture in picture with the given aspect ratio if provided
if (getIntent().hasExtra(EXTRA_ENTER_PIP)) {
- if (getIntent().hasExtra(EXTRA_ENTER_PIP_ASPECT_RATIO)) {
+ if (getIntent().hasExtra(EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR)
+ && getIntent().hasExtra(EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR)) {
try {
- final float aspectRatio = Float.valueOf(getIntent().getStringExtra(
- EXTRA_ENTER_PIP_ASPECT_RATIO));
- enterPictureInPictureMode(new PictureInPictureArgs(aspectRatio, null));
+ final PictureInPictureParams.Builder builder =
+ new PictureInPictureParams.Builder();
+ builder.setAspectRatio(getAspectRatio(getIntent(),
+ EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR,
+ EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR));
+ enterPictureInPictureMode(builder.build());
} catch (Exception e) {
// This call can fail intentionally if the aspect ratio is too extreme
}
} else {
- enterPictureInPictureMode();
+ enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
}
}
// We need to wait for either enterPictureInPicture() or requestAutoEnterPictureInPicture()
// to be called before setting the aspect ratio
- if (getIntent().hasExtra(EXTRA_SET_ASPECT_RATIO)) {
- final float aspectRatio = Float.valueOf(getIntent().getStringExtra(
- EXTRA_SET_ASPECT_RATIO));
+ if (getIntent().hasExtra(EXTRA_SET_ASPECT_RATIO_NUMERATOR)
+ && getIntent().hasExtra(EXTRA_SET_ASPECT_RATIO_DENOMINATOR)) {
+ final PictureInPictureParams.Builder builder =
+ new PictureInPictureParams.Builder();
+ builder.setAspectRatio(getAspectRatio(getIntent(),
+ EXTRA_SET_ASPECT_RATIO_NUMERATOR, EXTRA_SET_ASPECT_RATIO_DENOMINATOR));
try {
- setPictureInPictureArgs(new PictureInPictureArgs(aspectRatio, null));
+ setPictureInPictureParams(builder.build());
} catch (Exception e) {
// This call can fail intentionally if the aspect ratio is too extreme
}
@@ -214,7 +236,7 @@
// Enter PIP on move to background
if (getIntent().hasExtra(EXTRA_ENTER_PIP_ON_PAUSE)) {
- enterPictureInPictureMode();
+ enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
}
}
@@ -223,7 +245,7 @@
super.onStop();
if (getIntent().hasExtra(EXTRA_ASSERT_NO_ON_STOP_BEFORE_PIP) && !mEnteredPictureInPicture) {
- Log.w("PipActivity", "Unexpected onStop() called before entering picture-in-picture");
+ Log.w(TAG, "Unexpected onStop() called before entering picture-in-picture");
finish();
}
}
@@ -239,6 +261,13 @@
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode);
+ // Fail early if the activity state does not match the dispatched state
+ if (isInPictureInPictureMode() != isInPictureInPictureMode) {
+ Log.w(TAG, "Received onPictureInPictureModeChanged mode=" + isInPictureInPictureMode
+ + " activityState=" + isInPictureInPictureMode());
+ finish();
+ }
+
// Mark that we've entered picture-in-picture so that we can stop checking for
// EXTRA_ASSERT_NO_ON_STOP_BEFORE_PIP
if (isInPictureInPictureMode) {
@@ -250,7 +279,7 @@
// checking that the stacks ever changed). Therefor, we need to delay here slightly to
// allow the tests to verify that the stacks have changed before re-entering.
mHandler.postDelayed(() -> {
- enterPictureInPictureMode();
+ enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
}, 1000);
}
}
@@ -284,4 +313,13 @@
protected String getTag() {
return TAG;
}
+
+ /**
+ * @return a {@link Rational} aspect ratio from the given intent and extras.
+ */
+ private Rational getAspectRatio(Intent intent, String extraNum, String extraDenom) {
+ return new Rational(
+ Integer.valueOf(intent.getStringExtra(extraNum)),
+ Integer.valueOf(intent.getStringExtra(extraDenom)));
+ }
}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
index 038eb8d..65f507e 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -49,9 +49,16 @@
private static final String EXTRA_FIXED_ORIENTATION = "fixed_orientation";
private static final String EXTRA_ENTER_PIP = "enter_pip";
- private static final String EXTRA_ENTER_PIP_ASPECT_RATIO = "enter_pip_aspect_ratio";
- private static final String EXTRA_SET_ASPECT_RATIO = "set_aspect_ratio";
- private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY = "set_aspect_ratio_with_delay";
+ private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR =
+ "enter_pip_aspect_ratio_numerator";
+ private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR =
+ "enter_pip_aspect_ratio_denominator";
+ private static final String EXTRA_SET_ASPECT_RATIO_NUMERATOR = "set_aspect_ratio_numerator";
+ private static final String EXTRA_SET_ASPECT_RATIO_DENOMINATOR = "set_aspect_ratio_denominator";
+ private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR =
+ "set_aspect_ratio_with_delay_numerator";
+ private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR =
+ "set_aspect_ratio_with_delay_denominator";
private static final String EXTRA_ENTER_PIP_ON_PAUSE = "enter_pip_on_pause";
private static final String EXTRA_TAP_TO_FINISH = "tap_to_finish";
private static final String EXTRA_START_ACTIVITY = "start_activity";
@@ -91,11 +98,13 @@
private static final float FLOAT_COMPARE_EPSILON = 0.005f;
// Corresponds to com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio
- private static final float MIN_ASPECT_RATIO = 1f / 2.39f;
- private static final float BELOW_MIN_ASPECT_RATIO = MIN_ASPECT_RATIO - FLOAT_COMPARE_EPSILON;
+ private static final int MIN_ASPECT_RATIO_NUMERATOR = 100;
+ private static final int MIN_ASPECT_RATIO_DENOMINATOR = 239;
+ private static final int BELOW_MIN_ASPECT_RATIO_DENOMINATOR = MIN_ASPECT_RATIO_DENOMINATOR + 1;
// Corresponds to com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio
- private static final float MAX_ASPECT_RATIO = 2.39f;
- private static final float ABOVE_MAX_ASPECT_RATIO = MAX_ASPECT_RATIO + FLOAT_COMPARE_EPSILON;
+ private static final int MAX_ASPECT_RATIO_NUMERATOR = 239;
+ private static final int MAX_ASPECT_RATIO_DENOMINATOR = 100;
+ private static final int ABOVE_MAX_ASPECT_RATIO_NUMERATOR = MAX_ASPECT_RATIO_NUMERATOR + 1;
public void testEnterPictureInPictureMode() throws Exception {
pinnedStackTester(getAmStartCmd(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true"), PIP_ACTIVITY,
@@ -270,42 +279,44 @@
}
public void testEnterPipAspectRatioMin() throws Exception {
- testEnterPipAspectRatio(MAX_ASPECT_RATIO);
+ testEnterPipAspectRatio(MIN_ASPECT_RATIO_NUMERATOR, MIN_ASPECT_RATIO_DENOMINATOR);
}
public void testEnterPipAspectRatioMax() throws Exception {
- testEnterPipAspectRatio(MIN_ASPECT_RATIO);
+ testEnterPipAspectRatio(MAX_ASPECT_RATIO_NUMERATOR, MAX_ASPECT_RATIO_DENOMINATOR);
}
- private void testEnterPipAspectRatio(float aspectRatio) throws Exception {
+ private void testEnterPipAspectRatio(int num, int denom) throws Exception {
if (!supportsPip()) return;
launchActivity(PIP_ACTIVITY,
EXTRA_ENTER_PIP, "true",
- EXTRA_ENTER_PIP_ASPECT_RATIO, Float.toString(aspectRatio));
+ EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+ EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
assertPinnedStackExists();
// Assert that we have entered PIP and that the aspect ratio is correct
Rectangle pinnedStackBounds =
mAmWmState.getAmState().getStackById(PINNED_STACK_ID).getBounds();
assertTrue(floatEquals((float) pinnedStackBounds.width / pinnedStackBounds.height,
- aspectRatio));
+ (float) num / denom));
}
public void testResizePipAspectRatioMin() throws Exception {
- testResizePipAspectRatio(MIN_ASPECT_RATIO);
+ testResizePipAspectRatio(MIN_ASPECT_RATIO_NUMERATOR, MIN_ASPECT_RATIO_DENOMINATOR);
}
public void testResizePipAspectRatioMax() throws Exception {
- testResizePipAspectRatio(MAX_ASPECT_RATIO);
+ testResizePipAspectRatio(MAX_ASPECT_RATIO_NUMERATOR, MAX_ASPECT_RATIO_DENOMINATOR);
}
- private void testResizePipAspectRatio(float aspectRatio) throws Exception {
+ private void testResizePipAspectRatio(int num, int denom) throws Exception {
if (!supportsPip()) return;
launchActivity(PIP_ACTIVITY,
EXTRA_ENTER_PIP, "true",
- EXTRA_SET_ASPECT_RATIO, Float.toString(aspectRatio));
+ EXTRA_SET_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+ EXTRA_SET_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
assertPinnedStackExists();
// Hacky, but we need to wait for the enterPictureInPicture animation to complete and
@@ -314,7 +325,8 @@
mAmWmState.waitForWithAmState(mDevice, (state) -> {
Rectangle pinnedStackBounds = state.getStackById(PINNED_STACK_ID).getBounds();
boolean isValidAspectRatio = floatEquals(
- (float) pinnedStackBounds.width / pinnedStackBounds.height, aspectRatio);
+ (float) pinnedStackBounds.width / pinnedStackBounds.height,
+ (float) num / denom);
result[0] = isValidAspectRatio;
return isValidAspectRatio;
}, "Waiting for pinned stack to be resized");
@@ -322,45 +334,54 @@
}
public void testEnterPipExtremeAspectRatioMin() throws Exception {
- testEnterPipExtremeAspectRatio(BELOW_MIN_ASPECT_RATIO);
+ testEnterPipExtremeAspectRatio(MIN_ASPECT_RATIO_NUMERATOR,
+ BELOW_MIN_ASPECT_RATIO_DENOMINATOR);
}
public void testEnterPipExtremeAspectRatioMax() throws Exception {
- testEnterPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO);
+ testEnterPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO_NUMERATOR,
+ MAX_ASPECT_RATIO_DENOMINATOR);
}
- private void testEnterPipExtremeAspectRatio(float aspectRatio) throws Exception {
+ private void testEnterPipExtremeAspectRatio(int num, int denom) throws Exception {
if (!supportsPip()) return;
// Assert that we could not create a pinned stack with an extreme aspect ratio
launchActivity(PIP_ACTIVITY,
EXTRA_ENTER_PIP, "true",
- EXTRA_ENTER_PIP_ASPECT_RATIO, Float.toString(aspectRatio));
+ EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+ EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
assertPinnedStackDoesNotExist();
}
public void testSetPipExtremeAspectRatioMin() throws Exception {
- testSetPipExtremeAspectRatio(BELOW_MIN_ASPECT_RATIO);
+ testSetPipExtremeAspectRatio(MIN_ASPECT_RATIO_NUMERATOR,
+ BELOW_MIN_ASPECT_RATIO_DENOMINATOR);
}
public void testSetPipExtremeAspectRatioMax() throws Exception {
- testSetPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO);
+ testSetPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO_NUMERATOR,
+ MAX_ASPECT_RATIO_DENOMINATOR);
}
- private void testSetPipExtremeAspectRatio(float aspectRatio) throws Exception {
+ private void testSetPipExtremeAspectRatio(int num, int denom) throws Exception {
if (!supportsPip()) return;
// Try to resize the a normal pinned stack to an extreme aspect ratio and ensure that
// fails (the aspect ratio remains the same)
launchActivity(PIP_ACTIVITY,
EXTRA_ENTER_PIP, "true",
- EXTRA_ENTER_PIP_ASPECT_RATIO, Float.toString(MAX_ASPECT_RATIO),
- EXTRA_SET_ASPECT_RATIO, Float.toString(aspectRatio));
+ EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR,
+ Integer.toString(MAX_ASPECT_RATIO_NUMERATOR),
+ EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR,
+ Integer.toString(MAX_ASPECT_RATIO_DENOMINATOR),
+ EXTRA_SET_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+ EXTRA_SET_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
assertPinnedStackExists();
Rectangle pinnedStackBounds =
mAmWmState.getAmState().getStackById(PINNED_STACK_ID).getBounds();
assertTrue(floatEquals((float) pinnedStackBounds.width / pinnedStackBounds.height,
- MAX_ASPECT_RATIO));
+ (float) MAX_ASPECT_RATIO_NUMERATOR / MAX_ASPECT_RATIO_DENOMINATOR));
}
public void testDisallowPipLaunchFromStoppedActivity() throws Exception {
@@ -434,7 +455,8 @@
// Launch the PIP activity on pause, and set the aspect ratio
launchActivity(PIP_ACTIVITY,
EXTRA_ENTER_PIP_ON_PAUSE, "true",
- EXTRA_SET_ASPECT_RATIO, Float.toString(MAX_ASPECT_RATIO));
+ EXTRA_SET_ASPECT_RATIO_NUMERATOR, Integer.toString(MAX_ASPECT_RATIO_NUMERATOR),
+ EXTRA_SET_ASPECT_RATIO_DENOMINATOR, Integer.toString(MAX_ASPECT_RATIO_DENOMINATOR));
// Go home while the pip activity is open to trigger auto-PIP
launchHomeActivity();
@@ -446,7 +468,8 @@
mAmWmState.waitForWithAmState(mDevice, (state) -> {
Rectangle pinnedStackBounds = state.getStackById(PINNED_STACK_ID).getBounds();
boolean isValidAspectRatio = floatEquals(
- (float) pinnedStackBounds.width / pinnedStackBounds.height, MAX_ASPECT_RATIO);
+ (float) pinnedStackBounds.width / pinnedStackBounds.height,
+ (float) MAX_ASPECT_RATIO_NUMERATOR / MAX_ASPECT_RATIO_DENOMINATOR);
result[0] = isValidAspectRatio;
return isValidAspectRatio;
}, "Waiting for pinned stack to be resized");
@@ -806,8 +829,9 @@
// Trigger it to go back to fullscreen and try to set the aspect ratio, and ensure that the
// call to set the aspect ratio did not prevent the PiP from returning to fullscreen
- executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_EXPAND_PIP + " -e "
- + EXTRA_SET_ASPECT_RATIO_WITH_DELAY + " 1.23456789");
+ executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_EXPAND_PIP
+ + " -e " + EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR + " 123456789"
+ + " -e " + EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR + " 100000000");
mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY, FULLSCREEN_WORKSPACE_STACK_ID);
assertPinnedStackDoesNotExist();
}
@@ -851,6 +875,9 @@
assertPinnedStackExists();
int taskId = mAmWmState.getAmState().getStackById(PINNED_STACK_ID).getTopTask().mTaskId;
+ // Ensure that we don't any any other overlays as a result of launching into PIP
+ launchHomeActivity();
+
// Launch task overlay activity into PiP activity task
launchActivityAsTaskOverlay(TRANSLUCENT_TEST_ACTIVITY, taskId, PINNED_STACK_ID);
@@ -858,10 +885,7 @@
executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_FINISH);
mAmWmState.waitForWithAmState(mDevice, (amState) -> {
ActivityStack stack = amState.getStackById(PINNED_STACK_ID);
- if (stack != null) {
- return false;
- }
- return true;
+ return stack == null;
}, "Waiting for pinned stack to be removed...");
assertPinnedStackDoesNotExist();
}
@@ -908,15 +932,13 @@
if (expectTopTaskHasActivity) {
ActivityTask topTask = mAmWmState.getAmState().getStackById(
FULLSCREEN_WORKSPACE_STACK_ID).getTopTask();
- Activity topActivity = topTask.mActivities.get(0);
- assertTrue(topActivity.name.equals(ActivityManagerTestBase.getActivityComponentName(
+ assertTrue(topTask.containsActivity(ActivityManagerTestBase.getActivityComponentName(
activityName)));
}
if (expectBottomTaskHasActivity) {
ActivityTask bottomTask = mAmWmState.getAmState().getStackById(
FULLSCREEN_WORKSPACE_STACK_ID).getBottomTask();
- Activity bottomActivity = bottomTask.mActivities.get(0);
- assertTrue(bottomActivity.name.equals(ActivityManagerTestBase.getActivityComponentName(
+ assertTrue(bottomTask.containsActivity(ActivityManagerTestBase.getActivityComponentName(
activityName)));
}
}
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
index 6565215..56fed31 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
@@ -607,6 +607,18 @@
public String getResizeMode() {
return mResizeMode;
}
+
+ /**
+ * @return whether this task contains the given activity.
+ */
+ public boolean containsActivity(String activityName) {
+ for (Activity activity : mActivities) {
+ if (activity.name.equals(activityName)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
static class Activity {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
index 786ff40..430c612 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
@@ -62,9 +62,9 @@
final Parcelable result;
if (sResponse != null) {
- result = sResponse.asFillResponse(structure);
+ result = sResponse.asFillResponse((id) -> Helper.findNodeByResourceId(structure, id));
} else if (sDataset != null) {
- result = sDataset.asDataset(structure);
+ result = sDataset.asDataset((id) -> Helper.findNodeByResourceId(structure, id));
} else {
throw new IllegalStateException("no dataset or response");
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index b456dd7..9f5368f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -22,11 +22,11 @@
import static android.autofillservice.cts.Helper.getAutofillIds;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
-import android.autofillservice.cts.CannedFillResponse.Builder;
import android.content.IntentSender;
import android.os.Bundle;
import android.service.autofill.Dataset;
import android.service.autofill.FillCallback;
+import android.service.autofill.FillContext;
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
import android.view.autofill.AutofillId;
@@ -38,6 +38,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
/**
* Helper class used to produce a {@link FillResponse} based on expected fields that should be
@@ -66,7 +67,7 @@
private final IntentSender mAuthentication;
private final String[] mAuthenticationIds;
private final String[] mIgnoredIds;
- private final CharSequence mNegativeActionLabel;
+ private final int mNegativeActionStyle;
private final IntentSender mNegativeActionListener;
private final int mFlags;
@@ -81,7 +82,7 @@
mAuthentication = builder.mAuthentication;
mAuthenticationIds = builder.mAuthenticationIds;
mIgnoredIds = builder.mIgnoredIds;
- mNegativeActionLabel = builder.mNegativeActionLabel;
+ mNegativeActionStyle = builder.mNegativeActionStyle;
mNegativeActionListener = builder.mNegativeActionListener;
mFlags = builder.mFlags;
}
@@ -96,45 +97,37 @@
* Creates a new response, replacing the dataset field ids by the real ids from the assist
* structure.
*/
- FillResponse asFillResponse(AssistStructure structure) {
+ FillResponse asFillResponse(Function<String, ViewNode> nodeResolver) {
final FillResponse.Builder builder = new FillResponse.Builder();
if (mDatasets != null) {
for (CannedDataset cannedDataset : mDatasets) {
- final Dataset dataset = cannedDataset.asDataset(structure);
+ final Dataset dataset = cannedDataset.asDataset(nodeResolver);
assertWithMessage("Cannot create datase").that(dataset).isNotNull();
builder.addDataset(dataset);
}
}
if (mRequiredSavableIds != null) {
- final SaveInfo.Builder saveInfo;
-
- if (mRequiredSavableIds == null) {
- saveInfo = new SaveInfo.Builder(mSaveType, null);
- } else {
- saveInfo = new SaveInfo.Builder(mSaveType,
- getAutofillIds(structure, mRequiredSavableIds));
- }
+ final SaveInfo.Builder saveInfo = new SaveInfo.Builder(mSaveType,
+ getAutofillIds(nodeResolver, mRequiredSavableIds));
saveInfo.setFlags(mFlags);
if (mOptionalSavableIds != null) {
- saveInfo.setOptionalIds(getAutofillIds(structure, mOptionalSavableIds));
+ saveInfo.setOptionalIds(getAutofillIds(nodeResolver, mOptionalSavableIds));
}
if (mSaveDescription != null) {
saveInfo.setDescription(mSaveDescription);
}
- if (mNegativeActionLabel != null) {
- saveInfo.setNegativeAction(mNegativeActionLabel, mNegativeActionListener);
- }
+ saveInfo.setNegativeAction(mNegativeActionStyle, mNegativeActionListener);
builder.setSaveInfo(saveInfo.build());
}
if (mIgnoredIds != null) {
- builder.setIgnoredIds(getAutofillIds(structure, mIgnoredIds));
+ builder.setIgnoredIds(getAutofillIds(nodeResolver, mIgnoredIds));
}
return builder
.setClientState(mExtras)
- .setAuthentication(getAutofillIds(structure, mAuthenticationIds), mAuthentication,
- mPresentation)
+ .setAuthentication(getAutofillIds(nodeResolver, mAuthenticationIds),
+ mAuthentication, mPresentation)
.build();
}
@@ -163,7 +156,7 @@
private IntentSender mAuthentication;
private String[] mAuthenticationIds;
private String[] mIgnoredIds;
- private CharSequence mNegativeActionLabel;
+ private int mNegativeActionStyle;
private IntentSender mNegativeActionListener;
private int mFlags;
@@ -246,9 +239,9 @@
/**
* Sets the negative action spec.
*/
- public Builder setNegativeAction(CharSequence label,
+ public Builder setNegativeAction(int style,
IntentSender listener) {
- mNegativeActionLabel = label;
+ mNegativeActionStyle = style;
mNegativeActionListener = listener;
return this;
}
@@ -291,7 +284,7 @@
/**
* Creates a new dataset, replacing the field ids by the real ids from the assist structure.
*/
- Dataset asDataset(AssistStructure structure) {
+ Dataset asDataset(Function<String, ViewNode> nodeResolver) {
final Dataset.Builder builder = (mPresentation == null)
? new Dataset.Builder()
: new Dataset.Builder(mPresentation);
@@ -299,9 +292,8 @@
if (mFieldValues != null) {
for (Map.Entry<String, AutofillValue> entry : mFieldValues.entrySet()) {
final String resourceId = entry.getKey();
- final ViewNode node = findNodeByResourceId(structure, resourceId);
+ final ViewNode node = nodeResolver.apply(resourceId);
if (node == null) {
- dumpStructure("asDataset()", structure);
throw new AssertionError("No node with resource id " + resourceId);
}
final AutofillId id = node.getAutofillId();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index e19fa0c..f1491b4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -27,6 +27,7 @@
import android.os.Bundle;
import android.os.UserManager;
import android.service.autofill.Dataset;
+import android.service.autofill.FillContext;
import android.service.autofill.FillResponse;
import android.support.annotation.NonNull;
import android.support.test.InstrumentationRegistry;
@@ -40,8 +41,10 @@
import com.android.compatibility.common.util.SystemUtil;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
/**
* Helper for common funcionalities.
@@ -163,6 +166,15 @@
}
/**
+ * Dump the contexts on logcat.
+ */
+ static void dumpStructure(String message, List<FillContext> contexts) {
+ for (FillContext context : contexts) {
+ dumpStructure(message, context.getStructure());
+ }
+ }
+
+ /**
* Dumps the state of the autofill service on logcat.
*/
static void dumpAutofillService() {
@@ -227,6 +239,19 @@
/**
* Gets a node given its Android resource id, or {@code null} if not found.
*/
+ static ViewNode findNodeByResourceId(ArrayList<FillContext> contexts, String resourceId) {
+ for (FillContext context : contexts) {
+ ViewNode node = findNodeByResourceId(context.getStructure(), resourceId);
+ if (node != null) {
+ return node;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets a node given its Android resource id, or {@code null} if not found.
+ */
static ViewNode findNodeByResourceId(ViewNode node, String resourceId) {
if (resourceId.equals(node.getIdEntry())) {
return node;
@@ -530,15 +555,15 @@
* Creates an array of {@link AutofillId} mapped from the {@code structure} nodes with the given
* {@code resourceIds}.
*/
- static AutofillId[] getAutofillIds(AssistStructure structure, String[] resourceIds) {
+ static AutofillId[] getAutofillIds(Function<String, ViewNode> nodeResolver,
+ String[] resourceIds) {
if (resourceIds == null) return null;
final AutofillId[] requiredIds = new AutofillId[resourceIds.length];
for (int i = 0; i < resourceIds.length; i++) {
final String resourceId = resourceIds[i];
- final ViewNode node = findNodeByResourceId(structure, resourceId);
+ final ViewNode node = nodeResolver.apply(resourceId);
if (node == null) {
- dumpStructure("getAutofillIds()", structure);
throw new AssertionError("No node with savable resourceId " + resourceId);
}
requiredIds[i] = node.getAutofillId();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
index 44ca039..61b47af 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -38,6 +38,7 @@
import android.service.autofill.SaveCallback;
import android.util.Log;
+import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -85,21 +86,17 @@
@Override
public void onFillRequest(android.service.autofill.FillRequest request,
CancellationSignal cancellationSignal, FillCallback callback) {
- final AssistStructure structure = request.getStructure();
- if (DUMP_FILL_REQUESTS) dumpStructure("onFillRequest()", structure);
+ if (DUMP_FILL_REQUESTS) dumpStructure("onFillRequest()", request.getFillContexts());
- sReplier.onFillRequest(structure, request.getClientState(), cancellationSignal, callback,
- request.getFlags());
+ sReplier.onFillRequest(request.getFillContexts(), request.getClientState(),
+ cancellationSignal, callback, request.getFlags());
}
@Override
public void onSaveRequest(android.service.autofill.SaveRequest request,
SaveCallback callback) {
- final List<FillContext> contexts = request.getFillContexts();
- final AssistStructure structure = contexts.get(contexts.size() - 1).getStructure();
-
- if (DUMP_SAVE_REQUESTS) dumpStructure("onSaveRequest()", structure);
- sReplier.onSaveRequest(structure, request.getClientState(), callback);
+ if (DUMP_SAVE_REQUESTS) dumpStructure("onSaveRequest()", request.getFillContexts());
+ sReplier.onSaveRequest(request.getFillContexts(), request.getClientState(), callback);
}
/**
@@ -152,18 +149,20 @@
*/
static final class FillRequest {
final AssistStructure structure;
+ final ArrayList<FillContext> contexts;
final Bundle data;
final CancellationSignal cancellationSignal;
final FillCallback callback;
final int flags;
- private FillRequest(AssistStructure structure, Bundle data,
+ private FillRequest(ArrayList<FillContext> contexts, Bundle data,
CancellationSignal cancellationSignal, FillCallback callback, int flags) {
- this.structure = structure;
+ this.contexts = contexts;
this.data = data;
this.cancellationSignal = cancellationSignal;
this.callback = callback;
this.flags = flags;
+ structure = contexts.get(contexts.size() - 1).getStructure();
}
}
@@ -173,12 +172,18 @@
* that can be asserted at the end of a test case.
*/
static final class SaveRequest {
+ final List<FillContext> contexts;
final AssistStructure structure;
final Bundle data;
final SaveCallback callback;
- private SaveRequest(AssistStructure structure, Bundle data, SaveCallback callback) {
- this.structure = structure;
+ private SaveRequest(List<FillContext> contexts, Bundle data, SaveCallback callback) {
+ if (contexts != null && contexts.size() > 0) {
+ structure = contexts.get(contexts.size() - 1).getStructure();
+ } else {
+ structure = null;
+ }
+ this.contexts = contexts;
this.data = data;
this.callback = callback;
}
@@ -277,7 +282,7 @@
mSaveRequests.clear();
}
- private void onFillRequest(AssistStructure structure, Bundle data,
+ private void onFillRequest(ArrayList<FillContext> contexts, Bundle data,
CancellationSignal cancellationSignal, FillCallback callback, int flags) {
try {
CannedFillResponse response = null;
@@ -288,7 +293,7 @@
Thread.currentThread().interrupt();
}
if (response == null) {
- dumpStructure("onFillRequest() without response", structure);
+ dumpStructure("onFillRequest() without response", contexts);
throw new IllegalStateException("No CannedResponse");
}
if (response == NO_RESPONSE) {
@@ -296,19 +301,20 @@
return;
}
- final FillResponse fillResponse = response.asFillResponse(structure);
+ final FillResponse fillResponse = response.asFillResponse(
+ (id) -> Helper.findNodeByResourceId(contexts, id));
Log.v(TAG, "onFillRequest(): fillResponse = " + fillResponse);
callback.onSuccess(fillResponse);
} finally {
- mFillRequests.offer(new FillRequest(structure, data, cancellationSignal, callback,
+ mFillRequests.offer(new FillRequest(contexts, data, cancellationSignal, callback,
flags));
}
}
- private void onSaveRequest(AssistStructure structure, Bundle data, SaveCallback callback) {
+ private void onSaveRequest(List<FillContext> contexts, Bundle data, SaveCallback callback) {
Log.d(TAG, "onSaveRequest()");
- mSaveRequests.offer(new SaveRequest(structure, data, callback));
+ mSaveRequests.offer(new SaveRequest(contexts, data, callback));
callback.onSuccess();
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 30cfde7..74356fa 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -62,6 +62,7 @@
import android.content.IntentSender;
import android.os.Bundle;
import android.service.autofill.FillEventHistory;
+import android.service.autofill.SaveInfo;
import android.support.test.rule.ActivityTestRule;
import android.support.test.uiautomator.UiObject2;
import android.view.View;
@@ -1146,7 +1147,7 @@
}
@Test
- public void testCustomNegativeSaveButton() throws Exception {
+ public void testRejectStyleNegativeSaveButton() throws Exception {
enableService();
// Set service behavior.
@@ -1159,7 +1160,7 @@
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
- .setNegativeAction("Foo", listener)
+ .setNegativeAction(SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT, listener)
.build());
// Trigger auto-fill.
@@ -1185,7 +1186,8 @@
}, intentFilter);
// Trigger the negative button.
- sUiBot.saveForAutofill(false, SAVE_DATA_TYPE_PASSWORD);
+ sUiBot.saveForAutofill(SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT,
+ false, SAVE_DATA_TYPE_PASSWORD);
// Wait for the custom action.
assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue();
@@ -1194,6 +1196,55 @@
}
@Test
+ public void testCancelStyleNegativeSaveButton() throws Exception {
+ enableService();
+
+ // Set service behavior.
+
+ final String intentAction = "android.autofillservice.cts.CUSTOM_ACTION";
+
+ // Configure the save UI.
+ final IntentSender listener = PendingIntent.getBroadcast(
+ getContext(), 0, new Intent(intentAction), 0).getIntentSender();
+
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
+ .setNegativeAction(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL, listener)
+ .build());
+
+ // Trigger auto-fill.
+ mActivity.onUsername(View::requestFocus);
+
+ // Wait for onFill() before proceeding.
+ sReplier.getNextFillRequest();
+
+ // Trigger save.
+ mActivity.onUsername((v) -> v.setText("foo"));
+ mActivity.onPassword((v) -> v.setText("foo"));
+ mActivity.tapLogin();
+
+ // Start watching for the negative intent
+ final CountDownLatch latch = new CountDownLatch(1);
+ final IntentFilter intentFilter = new IntentFilter(intentAction);
+ getContext().registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ getContext().unregisterReceiver(this);
+ latch.countDown();
+ }
+ }, intentFilter);
+
+ // Trigger the negative button.
+ sUiBot.saveForAutofill(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL,
+ false, SAVE_DATA_TYPE_PASSWORD);
+
+ // Wait for the custom action.
+ assertThat(latch.await(500, TimeUnit.SECONDS)).isTrue();
+
+ assertNoDanglingSessions();
+ }
+
+ @Test
public void testGetTextInputType() throws Exception {
// Set service.
enableService();
@@ -1253,13 +1304,17 @@
assertThat(usernameContainer.getChildCount()).isEqualTo(2);
}
+ private static final boolean BUG_36171235_FIXED = false;
+
+ @Test
public void testAutofillManuallyOneDataset() throws Exception {
// Set service.
enableService();
+ if (BUG_36171235_FIXED)
// And activity.
mActivity.onUsername((v) -> {
- // v.setAutofillMode(AUTOFILL_MODE_MANUAL);
+ v.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
// TODO: setting an empty text, otherwise longPress() does not
// display the AUTOFILL context menu. Need to fix it, but it's a test case issue...
v.setText("");
@@ -1274,7 +1329,11 @@
mActivity.expectAutoFill("dude", "sweet");
// Long-press field to trigger AUTOFILL menu.
- sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+ if (BUG_36171235_FIXED) {
+ sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+ } else {
+ mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
+ }
final FillRequest fillRequest = sReplier.getNextFillRequest();
assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
@@ -1286,10 +1345,12 @@
mActivity.assertAutoFilled();
}
+ @Test
public void testAutofillManuallyTwoDatasetsPickFirst() throws Exception {
autofillManuallyTwoDatasets(true);
}
+ @Test
public void testAutofillManuallyTwoDatasetsPickSecond() throws Exception {
autofillManuallyTwoDatasets(false);
}
@@ -1298,9 +1359,10 @@
// Set service.
enableService();
+ if (BUG_36171235_FIXED)
// And activity.
mActivity.onUsername((v) -> {
- // v.setAutofillMode(AUTOFILL_MODE_MANUAL);
+ v.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
// TODO: setting an empty text, otherwise longPress() does not display the AUTOFILL
// context menu. Need to fix it, but it's a test case issue...
v.setText("");
@@ -1327,7 +1389,11 @@
}
// Long-press field to trigger AUTOFILL menu.
- sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+ if (BUG_36171235_FIXED) {
+ sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+ } else {
+ mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
+ }
final FillRequest fillRequest = sReplier.getNextFillRequest();
assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
index 32844d4..026cf08 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
@@ -54,9 +54,11 @@
if (structure != null) {
Parcelable result;
if (sResponse != null) {
- result = sResponse.asFillResponse(structure);
+ result = sResponse.asFillResponse(
+ (id) -> Helper.findNodeByResourceId(structure, id));
} else if (sDataset != null) {
- result = sDataset.asDataset(structure);
+ result = sDataset.asDataset(
+ (id) -> Helper.findNodeByResourceId(structure, id));
} else {
throw new IllegalStateException("no dataset or response");
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
index 76c8c70..d474dc8 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
@@ -24,8 +24,12 @@
import static com.google.common.truth.Truth.assertThat;
+import android.app.assist.AssistStructure;
+import android.app.assist.AssistStructure.ViewNode;
+import android.os.Bundle;
import android.support.test.rule.ActivityTestRule;
import android.util.Log;
+import android.view.autofill.AutofillValue;
import android.widget.EditText;
import org.junit.Before;
@@ -52,11 +56,17 @@
public void loginOnTwoFragments() throws Exception {
enableService();
try {
- // Set expectations.
+ Bundle clientState = new Bundle();
+ clientState.putString("key", "value1");
sReplier.addResponse(new CannedFillResponse.Builder()
- .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText1").build());
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField("editText1", "editText1-autofilled")
+ .setPresentation(createPresentation("dataset1"))
+ .build())
+ .setExtras(clientState)
+ .build());
- final InstrumentedAutoFillService.FillRequest[] request =
+ final InstrumentedAutoFillService.FillRequest[] fillRequest =
new InstrumentedAutoFillService.FillRequest[1];
// Trigger autofill
@@ -67,37 +77,123 @@
});
try {
- request[0] = sReplier.getNextFillRequest();
+ fillRequest[0] = sReplier.getNextFillRequest();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, (int) (FILL_TIMEOUT_MS * 2));
- assertThat(findNodeByResourceId(request[0].structure, "editText1")).isNotNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText2")).isNotNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText3")).isNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText4")).isNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText5")).isNull();
+ assertThat(fillRequest[0].data).isNull();
- Log.i(LOG_TAG, "Switching Fragments");
+ AssistStructure structure = fillRequest[0].contexts.get(0).getStructure();
+ assertThat(fillRequest[0].contexts.size()).isEqualTo(1);
+ assertThat(findNodeByResourceId(structure, "editText1")).isNotNull();
+ assertThat(findNodeByResourceId(structure, "editText2")).isNotNull();
+ assertThat(findNodeByResourceId(structure, "editText3")).isNull();
+ assertThat(findNodeByResourceId(structure, "editText4")).isNull();
+ assertThat(findNodeByResourceId(structure, "editText5")).isNull();
+
+ // Wait until autofill has been applied
+ sUiBot.selectDataset("dataset1");
+ sUiBot.assertShownByText("editText1-autofilled");
+
+ // Manually fill view
+ mActivity.syncRunOnUiThread(() -> mEditText2.setText("editText2-manually-filled"));
// Replacing the fragment focused a previously unknown view which triggers a new
// partition
+ clientState.putString("key", "value2");
sReplier.addResponse(new CannedFillResponse.Builder()
- .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText3").build());
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField("editText3", "editText3-autofilled")
+ .setField("editText4", "editText4-autofilled")
+ .setPresentation(createPresentation("dataset2"))
+ .build())
+ .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText2", "editText5")
+ .setExtras(clientState)
+ .build());
+ Log.i(LOG_TAG, "Switching Fragments");
mActivity.syncRunOnUiThread(
() -> mActivity.getFragmentManager().beginTransaction().replace(
R.id.rootContainer, new FragmentWithMoreEditTexts(),
FRAGMENT_TAG).commitNow());
+ EditText mEditText5 = mActivity.findViewById(R.id.editText5);
- request[0] = sReplier.getNextFillRequest();
+ fillRequest[0] = sReplier.getNextFillRequest();
- assertThat(findNodeByResourceId(request[0].structure, "editText1")).isNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText2")).isNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText3")).isNotNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText4")).isNotNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText5")).isNotNull();
+ // The fillRequest should have a fillContext for each partition. The first partition
+ // should be filled in
+ assertThat(fillRequest[0].contexts.size()).isEqualTo(2);
+
+ assertThat(fillRequest[0].data.getString("key")).isEqualTo("value1");
+
+ AssistStructure structure1 = fillRequest[0].contexts.get(0).getStructure();
+ ViewNode editText1Node = findNodeByResourceId(structure1, "editText1");
+ // The actual value in the structure is not updated in FillRequest-contexts, but the
+ // autofill value is. For text views in SaveRequest both are updated, but this is the
+ // only exception.
+ assertThat(editText1Node.getAutofillValue()).isEqualTo(
+ AutofillValue.forText("editText1-autofilled"));
+
+ ViewNode editText2Node = findNodeByResourceId(structure1, "editText2");
+ // Manually filled fields are not send to onFill. They appear in onSave if they are set
+ // as saveable fields.
+ assertThat(editText2Node.getText().toString()).isEqualTo("");
+
+ assertThat(findNodeByResourceId(structure1, "editText3")).isNull();
+ assertThat(findNodeByResourceId(structure1, "editText4")).isNull();
+ assertThat(findNodeByResourceId(structure1, "editText5")).isNull();
+
+ AssistStructure structure2 = fillRequest[0].contexts.get(1).getStructure();
+
+ assertThat(findNodeByResourceId(structure2, "editText1")).isNull();
+ assertThat(findNodeByResourceId(structure2, "editText2")).isNull();
+ assertThat(findNodeByResourceId(structure2, "editText3")).isNotNull();
+ assertThat(findNodeByResourceId(structure2, "editText4")).isNotNull();
+ assertThat(findNodeByResourceId(structure2, "editText5")).isNotNull();
+
+ // Wait until autofill has been applied
+ sUiBot.selectDataset("dataset2");
+ sUiBot.assertShownByText("editText3-autofilled");
+ sUiBot.assertShownByText("editText4-autofilled");
+
+ // Manually fill view
+ mActivity.syncRunOnUiThread(() -> mEditText5.setText("editText5-manually-filled"));
+
+ // Finish activity and save data
+ mActivity.finish();
+ sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_GENERIC);
+
+ // The saveRequest should have a fillContext for each partition with all the data
+ InstrumentedAutoFillService.SaveRequest saveRequest = sReplier.getNextSaveRequest();
+ assertThat(saveRequest.contexts.size()).isEqualTo(2);
+
+ assertThat(saveRequest.data.getString("key")).isEqualTo("value2");
+
+ structure1 = saveRequest.contexts.get(0).getStructure();
+ editText1Node = findNodeByResourceId(structure1, "editText1");
+ assertThat(editText1Node.getText().toString()).isEqualTo("editText1-autofilled");
+
+ editText2Node = findNodeByResourceId(structure1, "editText2");
+ assertThat(editText2Node.getText().toString()).isEqualTo("editText2-manually-filled");
+
+ assertThat(findNodeByResourceId(structure1, "editText3")).isNull();
+ assertThat(findNodeByResourceId(structure1, "editText4")).isNull();
+ assertThat(findNodeByResourceId(structure1, "editText5")).isNull();
+
+ structure2 = saveRequest.contexts.get(1).getStructure();
+ assertThat(findNodeByResourceId(structure2, "editText1")).isNull();
+ assertThat(findNodeByResourceId(structure2, "editText2")).isNull();
+
+ ViewNode editText3Node = findNodeByResourceId(structure2, "editText3");
+ assertThat(editText3Node.getText().toString()).isEqualTo("editText3-autofilled");
+
+ ViewNode editText4Node = findNodeByResourceId(structure2, "editText4");
+ assertThat(editText4Node.getText().toString()).isEqualTo("editText4-autofilled");
+
+ ViewNode editText5Node = findNodeByResourceId(structure2, "editText5");
+ assertThat(editText5Node.getText().toString()).isEqualTo("editText5-manually-filled");
} finally {
disableService();
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index 3b8c12a..fa7780a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -31,6 +31,7 @@
import android.app.UiAutomation;
import android.content.res.Resources;
import android.os.SystemClock;
+import android.service.autofill.SaveInfo;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
@@ -249,6 +250,10 @@
}
UiObject2 assertSaveShowing(String description, int... types) {
+ return assertSaveShowing(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL, description, types);
+ }
+
+ UiObject2 assertSaveShowing(int negativeButtonStyle, String description, int... types) {
final UiObject2 snackbar = waitForObject(By.res("android", RESOURCE_ID_SAVE_SNACKBAR),
SAVE_TIMEOUT_MS);
@@ -288,6 +293,12 @@
assertWithMessage("save subtitle(%s)", description).that(saveSubTitle).isNotNull();
}
+ final String negativeButtonText = (negativeButtonStyle
+ == SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT) ? "NOT NOW" : "NO THANKS";
+ UiObject2 negativeButton = snackbar.findObject(By.text(negativeButtonText));
+ assertWithMessage("negative button (%s)", negativeButtonText)
+ .that(negativeButton).isNotNull();
+
final String expectedAccessibilityTitle =
getString(RESOURCE_STRING_SAVE_SNACKBAR_ACCESSIBILITY_TITLE);
assertAccessibilityTitle(snackbar, expectedAccessibilityTitle);
@@ -302,7 +313,19 @@
* @param types expected types of save info.
*/
void saveForAutofill(boolean yesDoIt, int... types) {
- final UiObject2 saveSnackBar = assertSaveShowing(null, types);
+ final UiObject2 saveSnackBar = assertSaveShowing(
+ SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL,null, types);
+ saveForAutofill(saveSnackBar, yesDoIt);
+ }
+
+ /**
+ * Taps an option in the save snackbar.
+ *
+ * @param yesDoIt {@code true} for 'YES', {@code false} for 'NO THANKS'.
+ * @param types expected types of save info.
+ */
+ void saveForAutofill(int negativeButtonStyle, boolean yesDoIt, int... types) {
+ final UiObject2 saveSnackBar = assertSaveShowing(negativeButtonStyle,null, types);
saveForAutofill(saveSnackBar, yesDoIt);
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
index 670832c..2102773 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
@@ -41,7 +41,6 @@
import android.view.autofill.AutofillValue;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -161,7 +160,8 @@
@Override
public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
if (mOverrideDispatchProvideAutofillStructure) {
- Log.d(TAG, "Overriding dispatchProvideAutofillStructure");
+ Log.d(TAG, "Overriding dispatchProvideAutofillStructure()");
+ structure.setAutofillId(getAutofillId());
onProvideAutofillVirtualStructure(structure, flags);
} else {
super.dispatchProvideAutofillStructure(structure, flags);
@@ -184,7 +184,7 @@
final ViewStructure child = mSync
? structure.newChild(index)
: structure.asyncNewChild(index);
- child.setAutofillId(structure, item.id);
+ child.setAutofillId(structure.getAutofillId(), item.id);
child.setDataIsSensitive(item.sensitive);
index++;
final String className = item.editable ? TEXT_CLASS : LABEL_CLASS;
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index e4ca5af..ba902bf 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -296,5 +296,12 @@
"android.telecom.cts.WiredHeadsetTest"
],
bug: 26149528
+},
+{
+ desciption: "Seems to be failing on X86, flaky on arm. Root cause to be investigated",
+ names: [
+ "android.webkit.cts.WebViewClientTest#testOnRenderProcessGone"
+ ],
+ bug: 37704262
}
]
diff --git a/tests/tests/app/AndroidManifest.xml b/tests/tests/app/AndroidManifest.xml
index be903e3..707b22b 100644
--- a/tests/tests/app/AndroidManifest.xml
+++ b/tests/tests/app/AndroidManifest.xml
@@ -23,6 +23,11 @@
<activity android:name=".ApplyOverrideConfigurationActivity"
android:configChanges="orientation|screenSize" />
+
+ <activity android:name=".PictureInPictureActivity"
+ android:resizeableActivity="false"
+ android:supportsPictureInPicture="true"
+ android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout" />
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java b/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java
index d08b29f..da02a81 100644
--- a/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java
+++ b/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java
@@ -15,12 +15,16 @@
*/
package android.app.cts;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
-import android.app.ActivityManager;
+import android.app.Activity;
+import android.app.Instrumentation;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -32,9 +36,20 @@
@RunWith(AndroidJUnit4.class)
public class PictureInPictureActionsTest {
+ private Activity mActivity;
+
+ @Rule
+ public ActivityTestRule<PictureInPictureActivity> mActivityRule =
+ new ActivityTestRule<>(PictureInPictureActivity.class);
+
+ @Before
+ public void setup() {
+ mActivity = mActivityRule.getActivity();
+ }
+
@Test
public void testNumPictureInPictureActions() throws Exception {
- // Currently enforce that there are a max of three actions
- assertEquals(ActivityManager.getMaxNumPictureInPictureActions(), 3);
+ // Currently enforce that there are at least 3 actions
+ assertTrue(mActivity.getMaxNumPictureInPictureActions() >= 3);
}
}
diff --git a/tests/tests/app/src/android/app/cts/PictureInPictureActivity.java b/tests/tests/app/src/android/app/cts/PictureInPictureActivity.java
new file mode 100644
index 0000000..75245b7
--- /dev/null
+++ b/tests/tests/app/src/android/app/cts/PictureInPictureActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 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.app.cts;
+
+import android.app.Activity;
+
+public class PictureInPictureActivity extends Activity {
+ // Empty
+}
diff --git a/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java b/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
new file mode 100644
index 0000000..639c4d1
--- /dev/null
+++ b/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 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.app.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.PictureInPictureParams;
+import android.app.PictureInPictureParams.Builder;
+import android.graphics.Rect;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Rational;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+/**
+ * Tests the {@link PictureInPictureParams} builder.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PictureInPictureParamsBuilderTest {
+
+ @Test
+ public void testBuildParams() throws Exception {
+ // Set the params
+ Builder builder = new Builder()
+ .setAspectRatio(new Rational(1, 2))
+ .setActions(new ArrayList<>())
+ .setSourceRectHint(new Rect(0, 0, 100, 100));
+
+ PictureInPictureParams params = builder.build();
+ assertTrue(Float.compare(0.5f, params.getAspectRatio()) == 0);
+ assertTrue(params.getActions().isEmpty());
+ assertEquals(new Rect(0, 0, 100, 100), params.getSourceRectHint());
+
+ // Reset the params
+ builder.setAspectRatio(null)
+ .setActions(null)
+ .setSourceRectHint(null);
+ params = builder.build();
+
+ assertTrue(Float.compare(0f, params.getAspectRatio()) == 0);
+ assertNull(params.getActions());
+ assertNull(params.getSourceRectHint());
+ }
+}
diff --git a/tests/tests/content/res/values/attrs.xml b/tests/tests/content/res/values/attrs.xml
index 12b731b..236ee6c 100644
--- a/tests/tests/content/res/values/attrs.xml
+++ b/tests/tests/content/res/values/attrs.xml
@@ -49,6 +49,7 @@
<attr name="type15" format="reference"/>
<attr name="type16" format="string"/>
<attr name="type17" format="reference|color"/>
+ <attr name="type18" format="reference|string"/>
<attr name="typeEmpty" format="reference"/>
<attr name="typeUndefined" format="reference"/>
<declare-styleable name="style1">
@@ -69,6 +70,7 @@
<attr name="type15"/>
<attr name="type16"/>
<attr name="type17"/>
+ <attr name="type18"/>
<attr name="typeEmpty"/>
<attr name="typeUndefined"/>
</declare-styleable>
diff --git a/tests/tests/content/res/values/styles.xml b/tests/tests/content/res/values/styles.xml
index d1c30d7..b4db3ac 100644
--- a/tests/tests/content/res/values/styles.xml
+++ b/tests/tests/content/res/values/styles.xml
@@ -34,6 +34,7 @@
<item name="type15">@array/difficultyLevel</item>
<item name="type16">Typed Value!</item>
<item name="type17">@color/testcolor_orientation</item>
+ <item name="type18">@font/samplefont</item>
<item name="typeEmpty">@empty</item>
<item name="typeUndefined">@null</item>
</style>
@@ -181,4 +182,8 @@
<style name="Theme_OrientationDependent">
<item name="themeDimension">999px</item>
</style>
+
+ <style name="Theme_InlineString">
+ <item name="testString">"This is a string"</item>
+ </style>
</resources>
diff --git a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
index b7a621f..24c61ae 100644
--- a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
+++ b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
@@ -83,6 +83,16 @@
}
@SmallTest
+ public void testObtainStyledAttributesWithInlineStringInTheme() {
+ mResTheme.applyStyle(R.style.Theme_InlineString, false);
+ final TypedArray ta = mResTheme.obtainStyledAttributes(new int[] { R.attr.testString });
+ assertNotNull(ta);
+ assertEquals(1, ta.length());
+ assertEquals(TypedValue.TYPE_STRING, ta.getType(0));
+ assertEquals("This is a string", ta.getString(0));
+ }
+
+ @SmallTest
public void testResolveAttribute() {
final TypedValue value = new TypedValue();
getContext().getResources().getValue(R.raw.testmp3, value, true);
diff --git a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
index b31b446..5739554 100644
--- a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
+++ b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
@@ -25,6 +25,7 @@
import android.content.pm.ActivityInfo;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
+import android.graphics.Typeface;
import android.test.AndroidTestCase;
import android.util.AttributeSet;
import android.util.TypedValue;
@@ -48,9 +49,9 @@
private static final String EXPECTED_TEXT = "TypedArray Test!";
private static final String[] EXPECTED_TEXT_ARRAY = {"Easy", "Medium", "Hard"};
private static final TypedValue DEF_VALUE = new TypedValue();
- private static final int EXPECTED_INDEX_COUNT = 17;
+ private static final int EXPECTED_INDEX_COUNT = 18;
private static final String EXPTECTED_POS_DESCRIP = "<internal>";
- private static final int EXPECTED_LENGTH = 19;
+ private static final int EXPECTED_LENGTH = 20;
private static final String EXPECTED_NON_RESOURCE_STRING = "testNonResourcesString";
private static final String XML_BEGIN = "resources";
private static final int EXPECTED_INT_ATT = 86400;
@@ -62,7 +63,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mTypedArray = getContext().getTheme().obtainStyledAttributes(R.style.Whatever, R.styleable.style1);
+ mTypedArray = getContext().getTheme()
+ .obtainStyledAttributes(R.style.Whatever, R.styleable.style1);
}
@Override
@@ -167,6 +169,9 @@
actual_indices[idx] = attr_index;
}
+ final Typeface font = t.getFont(R.styleable.style1_type18);
+ assertEquals(mContext.getResources().getFont(R.font.samplefont), font);
+
// NOTE: order does not matter here.
// R.styleable.style1_typeEmpty and R.styleable.style1_typeUndefined are not
// expected because TYPE_NULL values do not get included in the index list.
@@ -187,7 +192,8 @@
R.styleable.style1_type14,
R.styleable.style1_type15,
R.styleable.style1_type16,
- R.styleable.style1_type17);
+ R.styleable.style1_type17,
+ R.styleable.style1_type18);
}
public void testPeekValue() {
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
index a296659..e255f8e 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
@@ -122,6 +122,18 @@
assertSame(sRGB, cs);
}
+ @Test
+ public void createDefaultColorSpace() {
+ ColorSpace sRGB = ColorSpace.get(ColorSpace.Named.SRGB);
+ Bitmap.Config[] configs = new Bitmap.Config[] {
+ Bitmap.Config.ALPHA_8, Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888
+ };
+ for (Bitmap.Config config : configs) {
+ Bitmap bitmap = Bitmap.createBitmap(32, 32, config, true);
+ assertSame(sRGB, bitmap.getColorSpace());
+ }
+ }
+
@Test(expected = IllegalArgumentException.class)
public void createWithoutColorSpace() {
Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888, true, null);
diff --git a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
index a113afa..74f4549 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
@@ -51,6 +51,8 @@
import android.text.SpannedString;
import android.util.DisplayMetrics;
+import com.android.compatibility.common.util.ColorUtils;
+
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
@@ -2179,4 +2181,18 @@
Assert.fail();
}
}
+
+ @Test
+ public void testShadowLayer_paintColorPreserved() {
+ Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ Paint paint = new Paint();
+
+ paint.setShadowLayer(5.0f, 10.0f, 10.0f, 0xFFFF0000);
+ paint.setColor(0xFF0000FF);
+ canvas.drawPaint(paint);
+
+ // Since the shadow is in the background, the canvas should be blue.
+ ColorUtils.verifyColor(0xFF0000FF, bitmap.getPixel(50, 50));
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
index 61d46b2..358e401 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
@@ -15,7 +15,9 @@
*/
package android.graphics.cts;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
@@ -97,5 +99,26 @@
canvas.drawPoint(0, 0, paint);
ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(0, 0));
}
+
+ @Test
+ public void testGetColorMatrix() {
+ ColorMatrixColorFilter filter = new ColorMatrixColorFilter(new ColorMatrix());
+ ColorMatrix getMatrix = new ColorMatrix();
+
+ filter.getColorMatrix(getMatrix);
+ assertEquals(new ColorMatrix(), getMatrix);
+
+ ColorMatrix scaleTranslate = new ColorMatrix(new float[] {
+ 1, 0, 0, 0, 8,
+ 0, 2, 0, 0, 7,
+ 0, 0, 3, 0, 6,
+ 0, 0, 0, 4, 5
+ });
+
+ filter = new ColorMatrixColorFilter(scaleTranslate);
+ filter.getColorMatrix(getMatrix);
+ assertEquals(scaleTranslate, getMatrix);
+ assertArrayEquals(scaleTranslate.getArray(), getMatrix.getArray(), 0);
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
index 3f82150..fdbf92e 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
@@ -435,12 +435,14 @@
assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector.getSource());
assertSame(ColorSpace.get(ColorSpace.Named.DCI_P3), connector.getDestination());
+ assertSame(ColorSpace.RenderIntent.PERCEPTUAL, connector.getRenderIntent());
connector = ColorSpace.connect(
ColorSpace.get(ColorSpace.Named.SRGB),
ColorSpace.get(ColorSpace.Named.SRGB));
assertSame(connector.getDestination(), connector.getSource());
+ assertSame(ColorSpace.RenderIntent.RELATIVE, connector.getRenderIntent());
connector = ColorSpace.connect(ColorSpace.get(ColorSpace.Named.DCI_P3));
assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector.getDestination());
@@ -543,6 +545,7 @@
ColorSpace.get(ColorSpace.Named.SRGB));
assertSame(connector.getSource(), connector.getDestination());
+ assertSame(ColorSpace.RenderIntent.RELATIVE, connector.getRenderIntent());
float[] source = new float[] { 0.11112f, 0.22227f, 0.444448f };
diff --git a/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
index da2b934..c7befa8 100644
--- a/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
@@ -35,6 +35,10 @@
public class LightingColorFilterTest {
private static final int TOLERANCE = 2;
+ private void verifyColor(int expected, int actual) {
+ ColorUtils.verifyColor(expected, actual, TOLERANCE);
+ }
+
@Test
public void testLightingColorFilter() {
Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
@@ -86,7 +90,22 @@
verifyColor(Color.argb(0x80, 30, 30, 30), bitmap.getPixel(0, 0));
}
- private void verifyColor(int expected, int actual) {
- ColorUtils.verifyColor(expected, actual, TOLERANCE);
+ @Test
+ public void testGetColorAdd() {
+ LightingColorFilter filter = new LightingColorFilter(Color.WHITE, Color.BLACK);
+ ColorUtils.verifyColor(Color.BLACK, filter.getColorAdd());
+
+ filter = new LightingColorFilter(0x87654321, 0x12345678);
+ ColorUtils.verifyColor(0x12345678, filter.getColorAdd());
+ }
+
+
+ @Test
+ public void testGetColorMultiply() {
+ LightingColorFilter filter = new LightingColorFilter(Color.WHITE, Color.BLACK);
+ ColorUtils.verifyColor(Color.WHITE, filter.getColorMultiply());
+
+ filter = new LightingColorFilter(0x87654321, 0x12345678);
+ ColorUtils.verifyColor(0x87654321, filter.getColorMultiply());
}
}
diff --git a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java b/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
deleted file mode 100644
index bcecee1..0000000
--- a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2017 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.net.cts;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.IpSecAlgorithm;
-import android.net.IpSecManager;
-import android.net.IpSecTransform;
-import android.os.ParcelFileDescriptor;
-import android.system.Os;
-import android.system.OsConstants;
-import android.test.AndroidTestCase;
-import java.io.ByteArrayOutputStream;
-import java.net.DatagramSocket;
-import java.io.FileDescriptor;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-
-public class IpSecManagerTest extends AndroidTestCase {
-
- private static final String TAG = IpSecManagerTest.class.getSimpleName();
-
- private IpSecManager mISM;
-
- private ConnectivityManager mCM;
-
- private static final InetAddress GOOGLE_DNS_4;
- private static final InetAddress GOOGLE_DNS_6;
-
- static {
- try {
- // Google Public DNS Addresses;
- GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8");
- GOOGLE_DNS_6 = InetAddress.getByName("2001:4860:4860::8888");
- } catch (UnknownHostException e) {
- throw new RuntimeException("Could not resolve DNS Addresses", e);
- }
- }
-
- private static final InetAddress[] GOOGLE_DNS_LIST =
- new InetAddress[] {GOOGLE_DNS_4, GOOGLE_DNS_6};
-
- private static final int DROID_SPI = 0xD1201D;
-
- private static final byte[] CRYPT_KEY =
- new byte[] {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
- 0x0E, 0x0F
- };
- private static final byte[] AUTH_KEY =
- new byte[] {
- 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x7F
- };
-
- protected void setUp() throws Exception {
- super.setUp();
- mCM = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
- mISM = (IpSecManager) getContext().getSystemService(Context.IPSEC_SERVICE);
- }
-
- /*
- * Allocate a random SPI
- * Allocate a specific SPI using previous randomly created SPI value
- * Realloc the same SPI that was specifically created (expect SpiUnavailable)
- * Close SPIs
- */
- public void testAllocSpi() throws Exception {
- for (InetAddress addr : GOOGLE_DNS_LIST) {
- IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null;
- randomSpi = mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, addr);
- assertTrue(
- "Failed to receive a valid SPI",
- randomSpi.getSpi() != IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
-
- droidSpi =
- mISM.reserveSecurityParameterIndex(
- IpSecTransform.DIRECTION_IN, addr, DROID_SPI);
- assertTrue(
- "Failed to allocate specified SPI, " + DROID_SPI,
- droidSpi.getSpi() == DROID_SPI);
-
- try {
- mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_IN, addr, DROID_SPI);
- fail("Duplicate SPI was allowed to be created");
- } catch (IpSecManager.SpiUnavailableException expected) {
- // This is a success case because we expect a dupe SPI to throw
- }
-
- randomSpi.close();
- droidSpi.close();
- }
- }
-
- /*
- * Alloc outbound SPI
- * Alloc inbound SPI
- * Create transport mode transform
- * open socket
- * apply transform to socket
- * send data on socket
- * release transform
- * send data (expect exception)
- */
- public void testCreateTransform() throws Exception {
- InetAddress local = InetAddress.getLoopbackAddress();
- IpSecManager.SecurityParameterIndex outSpi =
- mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, local);
-
- IpSecManager.SecurityParameterIndex inSpi =
- mISM.reserveSecurityParameterIndex(
- IpSecTransform.DIRECTION_IN, local, outSpi.getSpi());
-
- IpSecTransform transform =
- new IpSecTransform.Builder(mContext)
- .setSpi(IpSecTransform.DIRECTION_OUT, outSpi)
- .setEncryption(
- IpSecTransform.DIRECTION_OUT,
- new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
- .setAuthentication(
- IpSecTransform.DIRECTION_OUT,
- new IpSecAlgorithm(
- IpSecAlgorithm.AUTH_HMAC_SHA256,
- AUTH_KEY,
- AUTH_KEY.length * 8))
- .setSpi(IpSecTransform.DIRECTION_IN, inSpi)
- .setEncryption(
- IpSecTransform.DIRECTION_IN,
- new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
- .setAuthentication(
- IpSecTransform.DIRECTION_IN,
- new IpSecAlgorithm(
- IpSecAlgorithm.AUTH_HMAC_SHA256,
- AUTH_KEY,
- CRYPT_KEY.length * 8))
- .buildTransportModeTransform(local);
-
- // Hack to ensure the socket doesn't block indefinitely on failure
- DatagramSocket localSocket = new DatagramSocket(8888);
- localSocket.setSoTimeout(500);
- ParcelFileDescriptor pin = ParcelFileDescriptor.fromDatagramSocket(localSocket);
- FileDescriptor udpSocket = pin.getFileDescriptor();
-
- mISM.applyTransportModeTransform(udpSocket, transform);
- byte[] data = new String("Best test data ever!").getBytes("UTF-8");
-
- byte[] in = new byte[data.length];
- Os.sendto(udpSocket, data, 0, data.length, 0, local, 8888);
- Os.read(udpSocket, in, 0, in.length);
- assertTrue("Encapsulated data did not match.", Arrays.equals(data, in));
- mISM.removeTransportModeTransform(udpSocket, transform);
- Os.close(udpSocket);
- transform.close();
- }
-}
diff --git a/tests/tests/os/src/android/os/cts/BuildTest.java b/tests/tests/os/src/android/os/cts/BuildTest.java
index d489a6a..c9650bd 100644
--- a/tests/tests/os/src/android/os/cts/BuildTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildTest.java
@@ -33,6 +33,7 @@
import junit.framework.TestCase;
+import static android.os.Build.VERSION.CODENAME;
import static android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
public class BuildTest extends TestCase {
@@ -223,21 +224,7 @@
assertTrue(TYPE_PATTERN.matcher(Build.TYPE).matches());
assertNotEmpty(Build.USER);
- }
- public void testBuildConstants_forPrereleaseOrRelease() {
- checkBuildConstants(CUR_DEVELOPMENT);
- }
-
- @RestrictedBuildTest // Expected to fail on prelease/dev builds, http://b/35922665
- public void testBuildConstants_forRelease() {
- checkBuildConstants(CUR_DEVELOPMENT - 1);
- }
-
- /**
- * @param maxAllowedValue the maximum permitted value for constants other than CUR_DEVELOPMENT
- */
- private static void checkBuildConstants(int maxAllowedValue) {
// CUR_DEVELOPMENT must be larger than any released version.
Field[] fields = Build.VERSION_CODES.class.getDeclaredFields();
for (Field field : fields) {
@@ -253,9 +240,12 @@
// It should be okay to change the value of this constant in future, but it
// should at least be a conscious decision.
assertEquals(10000, fieldValue);
+ } else if (fieldName.equals(CODENAME) && !CODENAME.equals("REL")) {
+ // This is the current development version.
+ assertEquals(CUR_DEVELOPMENT, fieldValue);
} else {
- assertTrue("Expected " + fieldName + " value to be <= " + maxAllowedValue
- + ", got " + fieldValue, fieldValue <= maxAllowedValue);
+ assertTrue("Expected " + fieldName + " value to be < " + CUR_DEVELOPMENT
+ + ", got " + fieldValue, fieldValue < CUR_DEVELOPMENT);
}
}
}
diff --git a/tests/tests/graphics/src/android/graphics/fonts/cts/FontRequestTest.java b/tests/tests/provider/src/android/provider/cts/FontRequestTest.java
similarity index 62%
rename from tests/tests/graphics/src/android/graphics/fonts/cts/FontRequestTest.java
rename to tests/tests/provider/src/android/provider/cts/FontRequestTest.java
index 1b00975..d9b8a7f 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/cts/FontRequestTest.java
+++ b/tests/tests/provider/src/android/provider/cts/FontRequestTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.graphics.fonts.cts;
+package android.provider.cts;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@@ -22,7 +22,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
-import android.graphics.fonts.FontRequest;
+import android.provider.FontRequest;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -35,7 +35,7 @@
import java.util.List;
/**
- * Tests for {@link android.graphics.fonts.FontRequest}.
+ * Tests for {@link android.provider.FontRequest}.
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -47,46 +47,6 @@
Base64.decode("e04fd020ea3a6910a2d808002b30", Base64.DEFAULT);
private static final List<List<byte[]>> CERTS = Arrays.asList(Arrays.asList(BYTE_ARRAY));
- @Test
- public void testWriteToParcel() {
- // GIVEN a FontRequest created with the long constructor
- FontRequest request = new FontRequest(PROVIDER, PACKAGE, QUERY, CERTS);
-
- // WHEN we write it to a Parcel
- Parcel dest = Parcel.obtain();
- request.writeToParcel(dest, 0);
- dest.setDataPosition(0);
-
- // THEN we create from that parcel and get the same values.
- FontRequest result = FontRequest.CREATOR.createFromParcel(dest);
- assertEquals(PROVIDER, result.getProviderAuthority());
- assertEquals(PACKAGE, result.getProviderPackage());
- assertEquals(QUERY, result.getQuery());
- assertEquals(CERTS.size(), result.getCertificates().size());
- List<byte[]> cert = CERTS.get(0);
- List<byte[]> resultCert = result.getCertificates().get(0);
- assertEquals(cert.size(), resultCert.size());
- assertTrue(Arrays.equals(cert.get(0), resultCert.get(0)));
- }
-
- @Test
- public void testWriteToParcel_shortConstructor() {
- // GIVEN a FontRequest created with the short constructor
- FontRequest request = new FontRequest(PROVIDER, PACKAGE, QUERY);
-
- // WHEN we write it to a Parcel
- Parcel dest = Parcel.obtain();
- request.writeToParcel(dest, 0);
- dest.setDataPosition(0);
-
- // THEN we create from that parcel and get the same values.
- FontRequest result = FontRequest.CREATOR.createFromParcel(dest);
- assertEquals(PROVIDER, result.getProviderAuthority());
- assertEquals(PACKAGE, result.getProviderPackage());
- assertEquals(QUERY, result.getQuery());
- assertNotNull(result.getCertificates());
- assertEquals(0, result.getCertificates().size());
- }
@Test(expected = NullPointerException.class)
public void testShortConstructor_nullAuthority() {
diff --git a/tests/tests/provider/src/android/provider/cts/FontsContractTest.java b/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
index 472aed8..745a490 100644
--- a/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
+++ b/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
@@ -29,8 +29,8 @@
import android.content.pm.PackageInfo;
import android.content.Context;
import android.graphics.Typeface;
-import android.graphics.fonts.FontRequest;
import android.graphics.fonts.FontVariationAxis;
+import android.provider.FontRequest;
import android.provider.FontsContract;
import android.provider.FontsContract.FontFamilyResult;
import android.provider.FontsContract.FontInfo;
diff --git a/tests/tests/security/res/raw/bug_34097672.mp4 b/tests/tests/security/res/raw/bug_34097672.mp4
new file mode 100644
index 0000000..79acdf4
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_34097672.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_34360591.mp4 b/tests/tests/security/res/raw/bug_34360591.mp4
new file mode 100644
index 0000000..28c47d3
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_34360591.mp4
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index f120426..031b9f7 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -73,6 +73,10 @@
before any existing test methods
***********************************************************/
+ public void testStagefright_bug_34360591() throws Exception {
+ doStagefrightTest(R.raw.bug_34360591);
+ }
+
public void testStagefright_bug_35763994() throws Exception {
doStagefrightTest(R.raw.bug_35763994);
}
@@ -183,6 +187,11 @@
***********************************************************/
@SecurityTest
+ public void testStagefright_bug_34097672() throws Exception {
+ doStagefrightTest(R.raw.bug_34097672);
+ }
+
+ @SecurityTest
public void testStagefright_bug_33818508() throws Exception {
doStagefrightTest(R.raw.bug_33818508);
}
diff --git a/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java b/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java
index 2cc8993..c40c0fd 100644
--- a/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java
@@ -143,7 +143,7 @@
@UiThreadTest
@Before
- public void setup() {
+ public void setup() throws Throwable {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mActivity = mActivityRule.getActivity();
mSearchView = (SearchView) mActivity.findViewById(R.id.search_view);
@@ -154,14 +154,16 @@
// Use an adapter with our custom layout for each entry. The adapter "maps"
// the content of the text column of our cursor to the @id/text1 view in the
// layout.
- mSuggestionsAdapter = new SimpleCursorAdapter(
- mActivity,
- R.layout.searchview_suggestion_item,
- null,
- new String[] { TEXT_COLUMN_NAME },
- new int[] { android.R.id.text1 },
- CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
- mSearchView.setSuggestionsAdapter(mSuggestionsAdapter);
+ mActivityRule.runOnUiThread(() -> {
+ mSuggestionsAdapter = new SimpleCursorAdapter(
+ mActivity,
+ R.layout.searchview_suggestion_item,
+ null,
+ new String[] { TEXT_COLUMN_NAME },
+ new int[] { android.R.id.text1 },
+ CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
+ mSearchView.setSuggestionsAdapter(mSuggestionsAdapter);
+ });
}
@UiThreadTest
diff --git a/tools/cts-tradefed/res/config/cts-sts.xml b/tools/cts-tradefed/res/config/security-bulletin.xml
similarity index 95%
rename from tools/cts-tradefed/res/config/cts-sts.xml
rename to tools/cts-tradefed/res/config/security-bulletin.xml
index 8e4c030..02175a9 100644
--- a/tools/cts-tradefed/res/config/cts-sts.xml
+++ b/tools/cts-tradefed/res/config/security-bulletin.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Runs Security Patch test cases">
- <option name="plan" value="cts-sts" />
+ <option name="plan" value="security-bulletin" />
<include name="cts"/>
diff --git a/tools/selinux/SELinuxNeverallowTestFrame.py b/tools/selinux/SELinuxNeverallowTestFrame.py
index 7e9c304..f84f2ec 100644
--- a/tools/selinux/SELinuxNeverallowTestFrame.py
+++ b/tools/selinux/SELinuxNeverallowTestFrame.py
@@ -95,7 +95,7 @@
/* run sepolicy-analyze neverallow check on policy file using given neverallow rules */
ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
- devicePolicyFile.getAbsolutePath(), "neverallow", "-n",
+ devicePolicyFile.getAbsolutePath(), "neverallow", "-w", "-n",
neverallowRule);
pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
pb.redirectErrorStream(true);