Merge "Modified text field arrow tests for different input devices" into oc-dev
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 3a282bf..6a6c27d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -47,8 +47,13 @@
     private static final String MODE_EMULATED = "emulated";
     private static final String MODE_NONE = "none";
 
+    private static final String FEATURE_DEVICE_ADMIN = "feature:android.software.device_admin\n";
+    private static final String FEATURE_AUTOMOTIVE = "feature:android.hardware.type.automotive\n";
+
     private static final long SHUTDOWN_TIME_MS = 30 * 1000;
 
+    private String mFeatureList = null;
+
     private IAbi mAbi;
     private IBuildInfo mCtsBuild;
 
@@ -82,6 +87,22 @@
     }
 
     /**
+     * Automotive devices MUST support native FBE.
+     */
+    public void testAutomotiveNativeFbe() throws Exception {
+        if (!isSupportedDevice()) {
+            Log.v(TAG, "Device not supported; skipping test");
+            return;
+        } else if (!isAutomotiveDevice()) {
+            Log.v(TAG, "Device not automotive; skipping test");
+            return;
+        }
+
+        assertTrue("Automotive devices must support native FBE",
+            MODE_NATIVE.equals(getFbeMode()));
+    }
+
+    /**
      * If device has native FBE, verify lifecycle.
      */
     public void testDirectBootNative() throws Exception {
@@ -227,9 +248,20 @@
         return "1".equals(output);
     }
 
+    private boolean hasSystemFeature(final String feature) throws Exception {
+        if (mFeatureList == null) {
+            mFeatureList = getDevice().executeShellCommand("pm list features");
+        }
+
+        return mFeatureList.contains(feature);
+    }
+
     private boolean isSupportedDevice() throws Exception {
-        final String featureList = getDevice().executeShellCommand("pm list features");
-        return featureList.contains("feature:android.software.device_admin\n");
+        return hasSystemFeature(FEATURE_DEVICE_ADMIN);
+    }
+
+    private boolean isAutomotiveDevice() throws Exception {
+        return hasSystemFeature(FEATURE_AUTOMOTIVE);
     }
 
     private void waitForBootCompleted() throws Exception {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index 77513c5..7de83d6 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -110,12 +110,9 @@
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartEphemeral");
     }
 
-    /*
-     * Disabled pending drops of updated prebuilts
     public void testExposedSystemActivities() throws Exception {
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testExposedSystemActivities");
     }
-    */
 
     public void testBuildSerialUnknown() throws Exception {
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testBuildSerialUnknown");
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 21afece..fa8730d 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
@@ -97,9 +97,6 @@
                 ContactsContract.CommonDataKinds.Email.CONTENT_TYPE, null),
         makeIntent(Intent.ACTION_PICK, null,
                 ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_TYPE, null),
-        makeIntent(Intent.ACTION_INSERT, null, ContactsContract.Contacts.CONTENT_TYPE, null),
-        // Email
-        makeIntent(Intent.ACTION_SEND, null, "text/plain", Uri.parse("mailto:")),
         // File Storage
         makeIntent(Intent.ACTION_OPEN_DOCUMENT, Intent.CATEGORY_OPENABLE, "*/*", null),
         makeIntent(Intent.ACTION_OPEN_DOCUMENT, null, "*/*", null),
@@ -108,13 +105,8 @@
         makeIntent(Intent.ACTION_OPEN_DOCUMENT_TREE, null, null, null),
         makeIntent(Intent.ACTION_CREATE_DOCUMENT, Intent.CATEGORY_OPENABLE, "text/plain", null),
         makeIntent(Intent.ACTION_CREATE_DOCUMENT, null, "text/plain", null),
-        // Phone call
-        makeIntent(Intent.ACTION_DIAL, null, null, Uri.parse("tel:")),
-        // SMS
-        makeIntent(Intent.ACTION_SEND, null, "text/plain", Uri.parse("sms:")),
-        makeIntent(Intent.ACTION_SEND, null, "text/plain", Uri.parse("smsto:")),
-        // Web
-        makeIntent(Intent.ACTION_VIEW, null, "text/html", Uri.parse("https://example.com")),
+        // Framework
+        makeIntent(Intent.ACTION_CHOOSER, null, null, null),
     };
 
     private BroadcastReceiver mReceiver;
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
index fd3e85d..8ba3064 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
@@ -387,7 +387,7 @@
     }
 
     private void checkBattery(String[] parts) {
-        assertEquals(13, parts.length);
+        assertEquals(15, parts.length);
         if (!parts[4].equals("N/A")) {
             assertInteger(parts[4]);  // startCount
         }
@@ -399,6 +399,9 @@
         long bOffReal = assertInteger(parts[10]); // batteryScreenOffRealtime
         long bOffUp = assertInteger(parts[11]); // batteryScreenOffUptime
         long bEstCap = assertInteger(parts[12]); // batteryEstimatedCapacity
+        assertInteger(parts[13]); // minLearnedBatteryCapacity
+        assertInteger(parts[14]); // maxLearnedBatteryCapacity
+
         // The device cannot be up more than there are real-world seconds.
         assertTrue("batteryRealtime must be >= batteryUptime", bReal >= bUp);
         assertTrue("totalRealtime must be >= totalUptime", tReal >= tUp);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 38f4020..ce640d9 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -23,6 +23,7 @@
 import static android.autofillservice.cts.Helper.assertNumberOfChildren;
 import static android.autofillservice.cts.Helper.assertTextAndValue;
 import static android.autofillservice.cts.Helper.assertTextIsSanitized;
+import static android.autofillservice.cts.Helper.assertValue;
 import static android.autofillservice.cts.Helper.eventually;
 import static android.autofillservice.cts.Helper.findNodeByResourceId;
 import static android.autofillservice.cts.Helper.runShellCommand;
@@ -45,6 +46,7 @@
 import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_USERNAME;
 import static android.text.InputType.TYPE_NULL;
 import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
+import static android.view.View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -1287,21 +1289,14 @@
         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.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("");
-        });
+        mActivity.onUsername(
+                (v) -> v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS));
 
         // Set expectations.
         sReplier.addResponse(new CannedDataset.Builder()
@@ -1311,12 +1306,7 @@
                 .build());
         mActivity.expectAutoFill("dude", "sweet");
 
-        // Long-press field to trigger AUTOFILL menu.
-        if (BUG_36171235_FIXED) {
-            sUiBot.getAutofillMenuOption(ID_USERNAME).click();
-        } else {
-            mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
-        }
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
 
         final FillRequest fillRequest = sReplier.getNextFillRequest();
         assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
@@ -1342,14 +1332,9 @@
         // Set service.
         enableService();
 
-        if (BUG_36171235_FIXED)
         // And activity.
-        mActivity.onUsername((v) -> {
-            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("");
-        });
+        mActivity.onUsername(
+                (v) -> v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS));
 
         // Set expectations.
         sReplier.addResponse(new CannedFillResponse.Builder()
@@ -1372,11 +1357,7 @@
         }
 
         // Long-press field to trigger AUTOFILL menu.
-        if (BUG_36171235_FIXED) {
-            sUiBot.getAutofillMenuOption(ID_USERNAME).click();
-        } else {
-            mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
-        }
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
 
         final FillRequest fillRequest = sReplier.getNextFillRequest();
         assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
@@ -1390,6 +1371,42 @@
     }
 
     @Test
+    public void testAutofillManuallyPartialField() throws Exception {
+        // Set service.
+        enableService();
+
+        // And activity.
+        mActivity.onUsername((v) -> {
+            v.setText("dud");
+            v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
+        });
+        mActivity.onPassword((v) -> v.setText("IamSecretMan"));
+
+        // Set expectations.
+        sReplier.addResponse(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .setPresentation(createPresentation("The Dude"))
+                .build());
+        mActivity.expectAutoFill("dude", "sweet");
+
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+
+        final FillRequest fillRequest = sReplier.getNextFillRequest();
+        assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
+        // Username value should be available because it triggered the manual request...
+        assertValue(fillRequest.structure, ID_USERNAME, "dud");
+        // ... but password didn't
+        assertTextIsSanitized(fillRequest.structure, ID_PASSWORD);
+
+        // Should have been automatically filled.
+        sUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
     public void testCommitMultipleTimes() throws Throwable {
         // Set service.
         enableService();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
index 19f6b80..51221b5 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
@@ -240,7 +240,11 @@
         final FillRequest fillRequest1 = sReplier.getNextFillRequest();
         assertThat(fillRequest1.flags).isEqualTo(expectedFlag);
 
-        assertTextIsSanitized(fillRequest1.structure, ID_L1C1);
+        if (manually) {
+            assertValue(fillRequest1.structure, ID_L1C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest1.structure, ID_L1C1);
+        }
         assertTextIsSanitized(fillRequest1.structure, ID_L1C2);
 
         // Auto-fill it.
@@ -272,7 +276,11 @@
 
         assertValue(fillRequest2.structure, ID_L1C1, "l1c1");
         assertValue(fillRequest2.structure, ID_L1C2, "l1c2");
-        assertTextIsSanitized(fillRequest2.structure, ID_L2C1);
+        if (manually) {
+            assertValue(fillRequest2.structure, ID_L2C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest2.structure, ID_L2C1);
+        }
         assertTextIsSanitized(fillRequest2.structure, ID_L2C2);
 
         // Auto-fill it.
@@ -306,7 +314,11 @@
         assertValue(fillRequest3.structure, ID_L1C2, "l1c2");
         assertValue(fillRequest3.structure, ID_L2C1, "l2c1");
         assertValue(fillRequest3.structure, ID_L2C2, "l2c2");
-        assertTextIsSanitized(fillRequest3.structure, ID_L3C1);
+        if (manually) {
+            assertValue(fillRequest3.structure, ID_L3C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest3.structure, ID_L3C1);
+        }
         assertTextIsSanitized(fillRequest3.structure, ID_L3C2);
 
         // Auto-fill it.
@@ -342,7 +354,11 @@
         assertValue(fillRequest4.structure, ID_L2C2, "l2c2");
         assertValue(fillRequest4.structure, ID_L3C1, "l3c1");
         assertValue(fillRequest4.structure, ID_L3C2, "l3c2");
-        assertTextIsSanitized(fillRequest4.structure, ID_L4C1);
+        if (manually) {
+            assertValue(fillRequest4.structure, ID_L4C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest4.structure, ID_L4C1);
+        }
         assertTextIsSanitized(fillRequest4.structure, ID_L4C2);
 
         // Auto-fill it.
@@ -400,6 +416,7 @@
         final FillExpectation expectation2 = mActivity.expectAutofill()
                 .onCell(2, 1, "l2c1")
                 .onCell(2, 2, "l2c2");
+        mActivity.setText(2, 1, "L2..");
 
         // Trigger auto-fill.
         mActivity.forceAutofill(2, 1);
@@ -408,7 +425,7 @@
 
         assertValue(fillRequest2.structure, ID_L1C1, "l1c1");
         assertValue(fillRequest2.structure, ID_L1C2, "l1c2");
-        assertTextIsSanitized(fillRequest2.structure, ID_L2C1);
+        assertValue(fillRequest2.structure, ID_L2C1, "L2..");
         assertTextIsSanitized(fillRequest2.structure, ID_L2C2);
 
         // Check the results.
@@ -456,6 +473,7 @@
                         .build())
                 .build();
         sReplier.addResponse(response4);
+        mActivity.setText(4, 1, "L4..");
         final FillExpectation expectation4 = mActivity.expectAutofill()
                 .onCell(4, 1, "l4c1")
                 .onCell(4, 2, "l4c2");
@@ -471,7 +489,7 @@
         assertValue(fillRequest4.structure, ID_L2C2, "l2c2");
         assertValue(fillRequest4.structure, ID_L3C1, "l3c1");
         assertValue(fillRequest4.structure, ID_L3C2, "l3c2");
-        assertTextIsSanitized(fillRequest4.structure, ID_L4C1);
+        assertValue(fillRequest4.structure, ID_L4C1, "L4..");
         assertTextIsSanitized(fillRequest4.structure, ID_L4C2);
 
         // Check the results.
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
index 37b434e..c57682f 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
@@ -57,6 +57,58 @@
 
 }
 
+
+// Test creating a default stream with specific devices
+void runtest_aaudio_devices(int32_t deviceId, bool expectFail) {
+    AAudioStreamBuilder *aaudioBuilder = nullptr;
+    AAudioStream *aaudioStream = nullptr;
+
+    // Use an AAudioStreamBuilder to define the stream.
+    aaudio_result_t result = AAudio_createStreamBuilder(&aaudioBuilder);
+    ASSERT_EQ(AAUDIO_OK, result);
+    ASSERT_NE(nullptr, aaudioBuilder);
+
+    AAudioStreamBuilder_setDeviceId(aaudioBuilder,deviceId);
+
+    // Create an AAudioStream using the Builder.
+    result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
+    if (expectFail) {
+        ASSERT_NE(AAUDIO_OK, result);
+        ASSERT_EQ(nullptr, aaudioStream);
+    } else {
+        // Pass or fail is OK. Just don't crash.
+        ASSERT_TRUE(((result < 0) && (aaudioStream == nullptr))
+                    || ((result == AAUDIO_OK) && (aaudioStream != nullptr)));
+    }
+
+    // Cleanup
+    EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
+    if (aaudioStream != nullptr) {
+        AAudioStream_close(aaudioStream);
+    }
+}
+
+TEST(test_aaudio, aaudio_stream_device_unspecified) {
+    runtest_aaudio_devices(AAUDIO_DEVICE_UNSPECIFIED, false);
+}
+
+/* FIXME - why can we open this device? What is an illegal deviceId?
+TEST(test_aaudio, aaudio_stream_device_absurd) {
+    runtest_aaudio_devices(19736459, true);
+}
+*/
+/* FIXME review
+TEST(test_aaudio, aaudio_stream_device_reasonable) {
+    runtest_aaudio_devices(1, false);
+}
+*/
+
+/* FIXME - why can we open this device? What is an illegal deviceId?
+TEST(test_aaudio, aaudio_stream_device_negative) {
+    runtest_aaudio_devices(-765, true);
+}
+*/
+
 // Test creating a default stream with everything unspecified.
 TEST(test_aaudio, aaudio_stream_unspecified) {
     AAudioStreamBuilder *aaudioBuilder = nullptr;
@@ -120,7 +172,12 @@
     AAudioStreamBuilder_setBufferCapacityInFrames(aaudioBuilder, 2000);
 
     // Create an AAudioStream using the Builder.
-    ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
+    result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
+    if (requestedSharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE
+        && result != AAUDIO_OK) {
+        return; // EXCLUSIVE just may not be available. Should not crash.
+    }
+    ASSERT_EQ(AAUDIO_OK, result);
     EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
 
     EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, AAudioStream_getState(aaudioStream));
@@ -184,15 +241,14 @@
         // Write some data while we are running. Read counter should be advancing.
         writeLoops = 1 * actualSampleRate / framesPerBurst; // 1 second
         ASSERT_LT(2, writeLoops); // detect absurdly high framesPerBurst
-        timeoutNanos = 10 * NANOS_PER_SECOND * framesPerBurst / actualSampleRate; // bursts
+        timeoutNanos = 100 * (NANOS_PER_SECOND * framesPerBurst / actualSampleRate); // N bursts
         framesWritten = 1;
         aaudioFramesRead = AAudioStream_getFramesRead(aaudioStream);
         aaudioFramesRead1 = aaudioFramesRead;
         int64_t beginTime = getNanoseconds(CLOCK_MONOTONIC);
         do {
             framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
-            ASSERT_GE(framesWritten, 0);
-            ASSERT_LE(framesWritten, framesPerBurst);
+            ASSERT_EQ(framesWritten, framesPerBurst);
 
             framesTotal += framesWritten;
             aaudioFramesWritten = AAudioStream_getFramesWritten(aaudioStream);
@@ -211,8 +267,8 @@
         aaudioFramesRead2 = AAudioStream_getFramesRead(aaudioStream);
         int64_t endTime = getNanoseconds(CLOCK_MONOTONIC);
         ASSERT_GT(aaudioFramesRead2, 0);
-        ASSERT_GT(aaudioFramesRead2, aaudioFramesRead1);
-        ASSERT_LE(aaudioFramesRead2, aaudioFramesWritten);
+        EXPECT_GT(aaudioFramesRead2, aaudioFramesRead1);
+
 
         // TODO why is AudioTrack path so inaccurate?
         const double rateTolerance = 200.0; // arbitrary tolerance for sample rate
@@ -236,15 +292,16 @@
     aaudioFramesRead = AAudioStream_getFramesRead(aaudioStream);
     ASSERT_GE(aaudioFramesRead, aaudioFramesRead2); // monotonic increase
 
-    // Use this to sleep by waiting for something that won't happen.
-    AAudioStream_waitForStateChange(aaudioStream, AAUDIO_STREAM_STATE_PAUSED, &state, timeoutNanos);
+    // Use this to sleep by waiting for a state that won't happen.
+    timeoutNanos = 100 * NANOS_PER_MILLISECOND;
+    AAudioStream_waitForStateChange(aaudioStream, AAUDIO_STREAM_STATE_OPEN, &state, timeoutNanos);
     aaudioFramesRead2 = AAudioStream_getFramesRead(aaudioStream);
     EXPECT_EQ(aaudioFramesRead, aaudioFramesRead2);
 
     // ------------------- TEST FLUSH -----------------
     // Prime the buffer.
     timeoutNanos = 0;
-    writeLoops = 100;
+    writeLoops = 1000;
     do {
         framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
         framesTotal += framesWritten;
@@ -282,12 +339,10 @@
     runtest_aaudio_stream(AAUDIO_SHARING_MODE_SHARED);
 }
 
-/* TODO Enable exclusive mode test.
-// Test Writing to an AAudioStream using EXCLUSIVE sharing mode.
+// Test Writing to an AAudioStream using EXCLUSIVE sharing mode. It may fail gracefully.
 TEST(test_aaudio, aaudio_stream_exclusive) {
     runtest_aaudio_stream(AAUDIO_SHARING_MODE_EXCLUSIVE);
 }
-*/
 
 int main(int argc, char **argv) {
     testing::InitGoogleTest(&argc, argv);
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
index 2ec1e1c..3786967 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
@@ -18,17 +18,55 @@
 #define LOG_TAG "AAudioTest"
 
 #include <gtest/gtest.h>
+#include <atomic>
 #include <utils/Log.h>
 
 #include <aaudio/AAudio.h>
 #include "test_aaudio.h"
 
 typedef struct AAudioCallbackTestData {
-    int32_t callbackCount;
     int32_t expectedFramesPerCallback;
     int32_t actualFramesPerCallback;
+    int32_t minLatency;
+    int32_t maxLatency;
+    std::atomic<aaudio_result_t> callbackError;
+    std::atomic<int32_t> callbackCount;
 } AAudioCallbackTestData;
 
+static int32_t measureLatency(AAudioStream *stream) {
+    int64_t presentationTime = 0;
+    int64_t presentationPosition = 0;
+    int64_t now = getNanoseconds();
+    int32_t sampleRate = AAudioStream_getSampleRate(stream);
+    int64_t framesWritten = AAudioStream_getFramesWritten(stream);
+    aaudio_result_t result = AAudioStream_getTimestamp(stream,
+                                                       CLOCK_MONOTONIC,
+                                                       &presentationPosition,
+                                                       &presentationTime);
+    if (result < 0) {
+        return result;
+    }
+    // Calculate when the last frame written would be played.
+    int64_t deltaFrames = framesWritten - presentationPosition;
+    EXPECT_GE(framesWritten, presentationPosition);
+    int64_t calculatedDeltaNanos = deltaFrames * NANOS_PER_SECOND / sampleRate;
+    int64_t calculatedTimeNanos = presentationTime +  calculatedDeltaNanos;
+    int64_t latencyNanos = calculatedTimeNanos - now;
+    int32_t latencyMillis = (int32_t) ((latencyNanos + NANOS_PER_MILLISECOND - 1)
+                            / NANOS_PER_MILLISECOND);
+    return latencyMillis;
+}
+
+static void MyErrorCallbackProc(
+        AAudioStream *stream,
+        void *userData,
+        aaudio_result_t error) {
+    (void) stream;
+    AAudioCallbackTestData *myData = (AAudioCallbackTestData *) userData;
+    myData->callbackError = error;
+
+}
+
 // Callback function that fills the audio output buffer.
 static aaudio_data_callback_result_t MyDataCallbackProc(
         AAudioStream *stream,
@@ -54,6 +92,17 @@
         float *floatData = (float *) audioData;
         for (int i = 0; i < numSamples; i++) *floatData++ = 0.0f;
     }
+
+    int32_t latency = measureLatency(stream);
+    if (latency > 0) {
+        if (latency < myData->minLatency) {
+            myData->minLatency = latency;
+        }
+        if (latency > myData->maxLatency) {
+            myData->maxLatency = latency;
+        }
+    }
+
     myData->callbackCount++;
     return AAUDIO_CALLBACK_RESULT_CONTINUE;
 }
@@ -61,7 +110,7 @@
 // Test Writing to an AAudioStream using a Callback
 void runtest_aaudio_callback(aaudio_sharing_mode_t requestedSharingMode,
                              int32_t framesPerDataCallback) {
-    AAudioCallbackTestData myTestData = { 0, 0, 0 };
+    AAudioCallbackTestData myTestData;
     const int32_t requestedSampleRate = 48000;
     const int32_t requestedSamplesPerFrame = 2;
     const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM_I16;
@@ -79,6 +128,10 @@
     AAudioStream *stream = nullptr;
 
     aaudio_result_t result = AAUDIO_OK;
+    myTestData.callbackCount.store(0);
+    myTestData.callbackError = AAUDIO_OK;
+    myTestData.actualFramesPerCallback = 0;
+    myTestData.expectedFramesPerCallback = 0;
 
     // Use an AAudioStreamBuilder to define the stream.
     result = AAudio_createStreamBuilder(&builder);
@@ -93,6 +146,7 @@
     AAudioStreamBuilder_setSharingMode(builder, requestedSharingMode);
     AAudioStreamBuilder_setBufferCapacityInFrames(builder, 2000);
 
+    AAudioStreamBuilder_setErrorCallback(builder, MyErrorCallbackProc, &myTestData);
     AAudioStreamBuilder_setDataCallback(builder, MyDataCallbackProc, &myTestData);
     if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
         AAudioStreamBuilder_setFramesPerDataCallback(builder, framesPerDataCallback);
@@ -118,8 +172,8 @@
 
     actualDataFormat = AAudioStream_getFormat(stream);
 
-    // TODO test this on full build
-    // ASSERT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
+    // TODO Why does getDeviceId() always return 0?
+    // EXPECT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
 
     framesPerBurst = AAudioStream_getFramesPerBurst(stream);
     ASSERT_TRUE(framesPerBurst >= 16 && framesPerBurst <= 1024); // TODO what is min/max?
@@ -136,18 +190,27 @@
     // Start/stop more than once to see if it fails after the first time.
     // Write some data and measure the rate to see if the timing is OK.
     for (int loopIndex = 0; loopIndex < 2; loopIndex++) {
+
         myTestData.callbackCount = 0;
+        myTestData.minLatency = INT32_MAX;
+        myTestData.maxLatency = 0;
+        myTestData.callbackCount.store(0);
+
         myTestData.expectedFramesPerCallback = actualFramesPerDataCallback;
 
         // Start and wait for server to respond.
         ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(stream));
+
         ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream,
                                                              AAUDIO_STREAM_STATE_STARTING,
                                                              &state,
                                                              DEFAULT_STATE_TIMEOUT));
         EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
 
-        sleep(2);
+        sleep(2); // let the stream run
+
+        ASSERT_EQ(myTestData.callbackError.load(), AAUDIO_OK);
+        ASSERT_GT(myTestData.callbackCount.load(), 10);
 
         // For more coverage, alternate pausing and stopping.
         if ((loopIndex & 1) == 0) {
@@ -168,29 +231,34 @@
             EXPECT_EQ(AAUDIO_STREAM_STATE_STOPPED, state);
         }
 
-        int32_t oldCallbackCount = myTestData.callbackCount;
+        int32_t oldCallbackCount = myTestData.callbackCount.load();
         EXPECT_GT(oldCallbackCount, 10);
         sleep(1);
-        EXPECT_EQ(oldCallbackCount, myTestData.callbackCount); // expect not advancing
+        EXPECT_EQ(oldCallbackCount, myTestData.callbackCount.load()); // expect not advancing
 
         if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
             ASSERT_EQ(framesPerDataCallback, myTestData.actualFramesPerCallback);
         }
+
+        EXPECT_GE(myTestData.minLatency, 1);   // Absurdly low
+        EXPECT_LE(myTestData.maxLatency, 200); // Absurdly high, should be < 30
+        //printf("latency: %d, %d\n", myTestData.minLatency, myTestData.maxLatency);
     }
 
+    ASSERT_EQ(myTestData.callbackError.load(), AAUDIO_OK);
+
     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(stream));
 }
 
 // Test Using an AAudioStream callback in SHARED mode.
-
 TEST(test_aaudio, aaudio_callback_shared_unspecified) {
-runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED);
+    runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED);
 }
 
 TEST(test_aaudio, aaudio_callback_shared_109) {
-runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 109); // arbitrary prime number < 192
+    runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 109); // arbitrary prime number < 192
 }
 
 TEST(test_aaudio, aaudio_callback_shared_223) {
-runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 223); // arbitrary prime number > 192
+    runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 223); // arbitrary prime number > 192
 }
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
index 8599d48..6662b72 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
@@ -1,7 +1,7 @@
 /*
  * Copyright 2017 The Android Open Source Project
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the "License", ENUM_CANNOT_CHANGE);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
@@ -25,53 +25,55 @@
 // Make sure enums do not change value.
 TEST(test_aaudio_misc, aaudio_freeze_enums) {
 
-    ASSERT_EQ(0, AAUDIO_DIRECTION_OUTPUT);
-    ASSERT_EQ(1, AAUDIO_DIRECTION_INPUT);
+#define ENUM_CANNOT_CHANGE "enum in API cannot change"
 
-    ASSERT_EQ(-1, AAUDIO_FORMAT_INVALID);
-    ASSERT_EQ(0, AAUDIO_FORMAT_UNSPECIFIED);
-    ASSERT_EQ(1, AAUDIO_FORMAT_PCM_I16);
-    ASSERT_EQ(2, AAUDIO_FORMAT_PCM_FLOAT);
+    static_assert(0 == AAUDIO_DIRECTION_OUTPUT, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_DIRECTION_INPUT, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_OK);
-    ASSERT_EQ(-900, AAUDIO_ERROR_BASE);
-    ASSERT_EQ(-899, AAUDIO_ERROR_DISCONNECTED);
-    ASSERT_EQ(-898, AAUDIO_ERROR_ILLEGAL_ARGUMENT);
-    ASSERT_EQ(-897, AAUDIO_ERROR_INCOMPATIBLE);
-    ASSERT_EQ(-896, AAUDIO_ERROR_INTERNAL);
-    ASSERT_EQ(-895, AAUDIO_ERROR_INVALID_STATE);
-    ASSERT_EQ(-894, AAUDIO_ERROR_UNEXPECTED_STATE);
-    ASSERT_EQ(-893, AAUDIO_ERROR_UNEXPECTED_VALUE);
-    ASSERT_EQ(-892, AAUDIO_ERROR_INVALID_HANDLE);
-    ASSERT_EQ(-891, AAUDIO_ERROR_INVALID_QUERY);
-    ASSERT_EQ(-890, AAUDIO_ERROR_UNIMPLEMENTED);
-    ASSERT_EQ(-889, AAUDIO_ERROR_UNAVAILABLE);
-    ASSERT_EQ(-888, AAUDIO_ERROR_NO_FREE_HANDLES);
-    ASSERT_EQ(-887, AAUDIO_ERROR_NO_MEMORY);
-    ASSERT_EQ(-886, AAUDIO_ERROR_NULL);
-    ASSERT_EQ(-885, AAUDIO_ERROR_TIMEOUT);
-    ASSERT_EQ(-884, AAUDIO_ERROR_WOULD_BLOCK);
-    ASSERT_EQ(-883, AAUDIO_ERROR_INVALID_FORMAT);
-    ASSERT_EQ(-882, AAUDIO_ERROR_OUT_OF_RANGE);
-    ASSERT_EQ(-881, AAUDIO_ERROR_NO_SERVICE);
+    static_assert(-1 == AAUDIO_FORMAT_INVALID, ENUM_CANNOT_CHANGE);
+    static_assert(0 == AAUDIO_FORMAT_UNSPECIFIED, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_FORMAT_PCM_I16, ENUM_CANNOT_CHANGE);
+    static_assert(2 == AAUDIO_FORMAT_PCM_FLOAT, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_STREAM_STATE_UNINITIALIZED);
-    ASSERT_EQ(1, AAUDIO_STREAM_STATE_UNKNOWN);
-    ASSERT_EQ(2, AAUDIO_STREAM_STATE_OPEN);
-    ASSERT_EQ(3, AAUDIO_STREAM_STATE_STARTING);
-    ASSERT_EQ(4, AAUDIO_STREAM_STATE_STARTED);
-    ASSERT_EQ(5, AAUDIO_STREAM_STATE_PAUSING);
-    ASSERT_EQ(6, AAUDIO_STREAM_STATE_PAUSED);
-    ASSERT_EQ(7, AAUDIO_STREAM_STATE_FLUSHING);
-    ASSERT_EQ(8, AAUDIO_STREAM_STATE_FLUSHED);
-    ASSERT_EQ(9, AAUDIO_STREAM_STATE_STOPPING);
-    ASSERT_EQ(10, AAUDIO_STREAM_STATE_STOPPED);
-    ASSERT_EQ(11, AAUDIO_STREAM_STATE_CLOSING);
-    ASSERT_EQ(12, AAUDIO_STREAM_STATE_CLOSED);
+    static_assert(0 == AAUDIO_OK, ENUM_CANNOT_CHANGE);
+    static_assert(-900 == AAUDIO_ERROR_BASE, ENUM_CANNOT_CHANGE);
+    static_assert(-899 == AAUDIO_ERROR_DISCONNECTED, ENUM_CANNOT_CHANGE);
+    static_assert(-898 == AAUDIO_ERROR_ILLEGAL_ARGUMENT, ENUM_CANNOT_CHANGE);
+    static_assert(-897 == AAUDIO_ERROR_INCOMPATIBLE, ENUM_CANNOT_CHANGE);
+    static_assert(-896 == AAUDIO_ERROR_INTERNAL, ENUM_CANNOT_CHANGE);
+    static_assert(-895 == AAUDIO_ERROR_INVALID_STATE, ENUM_CANNOT_CHANGE);
+    static_assert(-894 == AAUDIO_ERROR_UNEXPECTED_STATE, ENUM_CANNOT_CHANGE);
+    static_assert(-893 == AAUDIO_ERROR_UNEXPECTED_VALUE, ENUM_CANNOT_CHANGE);
+    static_assert(-892 == AAUDIO_ERROR_INVALID_HANDLE, ENUM_CANNOT_CHANGE);
+    static_assert(-891 == AAUDIO_ERROR_INVALID_QUERY, ENUM_CANNOT_CHANGE);
+    static_assert(-890 == AAUDIO_ERROR_UNIMPLEMENTED, ENUM_CANNOT_CHANGE);
+    static_assert(-889 == AAUDIO_ERROR_UNAVAILABLE, ENUM_CANNOT_CHANGE);
+    static_assert(-888 == AAUDIO_ERROR_NO_FREE_HANDLES, ENUM_CANNOT_CHANGE);
+    static_assert(-887 == AAUDIO_ERROR_NO_MEMORY, ENUM_CANNOT_CHANGE);
+    static_assert(-886 == AAUDIO_ERROR_NULL, ENUM_CANNOT_CHANGE);
+    static_assert(-885 == AAUDIO_ERROR_TIMEOUT, ENUM_CANNOT_CHANGE);
+    static_assert(-884 == AAUDIO_ERROR_WOULD_BLOCK, ENUM_CANNOT_CHANGE);
+    static_assert(-883 == AAUDIO_ERROR_INVALID_FORMAT, ENUM_CANNOT_CHANGE);
+    static_assert(-882 == AAUDIO_ERROR_OUT_OF_RANGE, ENUM_CANNOT_CHANGE);
+    static_assert(-881 == AAUDIO_ERROR_NO_SERVICE, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_SHARING_MODE_EXCLUSIVE);
-    ASSERT_EQ(1, AAUDIO_SHARING_MODE_SHARED);
+    static_assert(0 == AAUDIO_STREAM_STATE_UNINITIALIZED, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_STREAM_STATE_UNKNOWN, ENUM_CANNOT_CHANGE);
+    static_assert(2 == AAUDIO_STREAM_STATE_OPEN, ENUM_CANNOT_CHANGE);
+    static_assert(3 == AAUDIO_STREAM_STATE_STARTING, ENUM_CANNOT_CHANGE);
+    static_assert(4 == AAUDIO_STREAM_STATE_STARTED, ENUM_CANNOT_CHANGE);
+    static_assert(5 == AAUDIO_STREAM_STATE_PAUSING, ENUM_CANNOT_CHANGE);
+    static_assert(6 == AAUDIO_STREAM_STATE_PAUSED, ENUM_CANNOT_CHANGE);
+    static_assert(7 == AAUDIO_STREAM_STATE_FLUSHING, ENUM_CANNOT_CHANGE);
+    static_assert(8 == AAUDIO_STREAM_STATE_FLUSHED, ENUM_CANNOT_CHANGE);
+    static_assert(9 == AAUDIO_STREAM_STATE_STOPPING, ENUM_CANNOT_CHANGE);
+    static_assert(10 == AAUDIO_STREAM_STATE_STOPPED, ENUM_CANNOT_CHANGE);
+    static_assert(11 == AAUDIO_STREAM_STATE_CLOSING, ENUM_CANNOT_CHANGE);
+    static_assert(12 == AAUDIO_STREAM_STATE_CLOSED, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_CALLBACK_RESULT_CONTINUE);
-    ASSERT_EQ(1, AAUDIO_CALLBACK_RESULT_STOP);
+    static_assert(0 == AAUDIO_SHARING_MODE_EXCLUSIVE, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_SHARING_MODE_SHARED, ENUM_CANNOT_CHANGE);
+
+    static_assert(0 == AAUDIO_CALLBACK_RESULT_CONTINUE, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_CALLBACK_RESULT_STOP, ENUM_CANNOT_CHANGE);
 }
diff --git a/tests/tests/text/src/android/text/format/cts/FormatterTest.java b/tests/tests/text/src/android/text/format/cts/FormatterTest.java
index fa11023..8c7fdc9 100644
--- a/tests/tests/text/src/android/text/format/cts/FormatterTest.java
+++ b/tests/tests/text/src/android/text/format/cts/FormatterTest.java
@@ -19,6 +19,8 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.Context;
+import android.content.res.Configuration;
+import android.os.LocaleList;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -29,6 +31,7 @@
 
 import java.math.BigDecimal;
 import java.math.MathContext;
+import java.util.Locale;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -38,9 +41,12 @@
         // test null Context
         assertEquals("", Formatter.formatFileSize(null, 0));
 
-        MathContext mc = MathContext.DECIMAL64;
-        BigDecimal bd = new BigDecimal((long) 1000, mc);
-        Context context = InstrumentationRegistry.getTargetContext();
+        final MathContext mc = MathContext.DECIMAL64;
+        final BigDecimal bd = new BigDecimal((long) 1000, mc);
+        final Configuration config = new Configuration();
+        config.setLocales(new LocaleList(Locale.US));
+        final Context context =
+                InstrumentationRegistry.getTargetContext().createConfigurationContext(config);
 
         // test different long values with various length
         assertEquals("0 B", Formatter.formatFileSize(context, 0));
@@ -53,6 +59,8 @@
         assertEquals("0.90 kB", Formatter.formatFileSize(context, 901));
 
         assertEquals("1.00 kB", Formatter.formatFileSize(context, bd.pow(1).longValue()));
+        assertEquals("1.50 kB", Formatter.formatFileSize(context, bd.pow(1).longValue() * 3 / 2));
+        assertEquals("12.50 kB", Formatter.formatFileSize(context, bd.pow(1).longValue() * 25 / 2));
 
         assertEquals("1.00 MB", Formatter.formatFileSize(context, bd.pow(2).longValue()));
 
@@ -69,6 +77,48 @@
     }
 
     @Test
+    public void testFormatShortFileSize() {
+        // test null Context
+        assertEquals("", Formatter.formatFileSize(null, 0));
+
+        final MathContext mc = MathContext.DECIMAL64;
+        final BigDecimal bd = new BigDecimal((long) 1000, mc);
+        final Configuration config = new Configuration();
+        config.setLocales(new LocaleList(Locale.US));
+        final Context context =
+                InstrumentationRegistry.getTargetContext().createConfigurationContext(config);
+
+        // test different long values with various length
+        assertEquals("0 B", Formatter.formatShortFileSize(context, 0));
+        assertEquals("1 B", Formatter.formatShortFileSize(context, 1));
+        assertEquals("9 B", Formatter.formatShortFileSize(context, 9));
+        assertEquals("10 B", Formatter.formatShortFileSize(context, 10));
+        assertEquals("99 B", Formatter.formatShortFileSize(context, 99));
+        assertEquals("100 B", Formatter.formatShortFileSize(context, 100));
+        assertEquals("900 B", Formatter.formatShortFileSize(context, 900));
+        assertEquals("0.90 kB", Formatter.formatShortFileSize(context, 901));
+
+        assertEquals("1.0 kB", Formatter.formatShortFileSize(context, bd.pow(1).longValue()));
+        assertEquals("1.5 kB", Formatter.formatShortFileSize(context,
+                bd.pow(1).longValue() * 3 / 2));
+        assertEquals("13 kB", Formatter.formatShortFileSize(context,
+                bd.pow(1).longValue() * 25 / 2));
+
+        assertEquals("1.0 MB", Formatter.formatShortFileSize(context, bd.pow(2).longValue()));
+
+        assertEquals("1.0 GB", Formatter.formatShortFileSize(context, bd.pow(3).longValue()));
+
+        assertEquals("1.0 TB", Formatter.formatShortFileSize(context, bd.pow(4).longValue()));
+
+        assertEquals("1.0 PB", Formatter.formatShortFileSize(context, bd.pow(5).longValue()));
+
+        assertEquals("1000 PB", Formatter.formatShortFileSize(context, bd.pow(6).longValue()));
+
+        // test Negative value
+        assertEquals("-1 B", Formatter.formatShortFileSize(context, -1));
+    }
+
+    @Test
     public void testFormatIpAddress() {
         assertEquals("1.0.168.192", Formatter.formatIpAddress(0xC0A80001));
         assertEquals("1.0.0.127", Formatter.formatIpAddress(0x7F000001));