Merge "Snap for 6421779 from 31690d4cf4b57c8079036a38952ad1f711513873 to oreo-mr1-vts-release" into oreo-mr1-vts-release
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index a6c63ae..d8c341a 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
       android:versionCode="5"
-      android:versionName="8.1_r19">
+      android:versionName="8.1_r20">
 
     <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="27"/>
 
@@ -1470,6 +1470,8 @@
             <meta-data android:name="test_category" android:value="@string/test_category_sensors"/>
             <meta-data android:name="test_required_features"
                        android:value="android.hardware.sensor.accelerometer"/>
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.automotive"/>
         </activity>
 
         <activity android:name=".sensors.GyroscopeMeasurementTestActivity"
@@ -1482,6 +1484,8 @@
             <meta-data android:name="test_category" android:value="@string/test_category_sensors"/>
             <meta-data android:name="test_required_features"
                        android:value="android.hardware.sensor.gyroscope"/>
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.automotive"/>
         </activity>
 
         <activity android:name=".sensors.HeartRateMonitorTestActivity"
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index b210d33..8816432 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -400,10 +400,7 @@
     <string name="ble_scan_stop">Stop scan</string>
 
     <!-- BLE connection priority test strings -->
-    <string name="ble_client_connection_priority">Testing priority: </string>
-    <string name="ble_connection_priority_balanced">BALANCED</string>
-    <string name="ble_connection_priority_high">HIGH</string>
-    <string name="ble_connection_priority_low">LOW</string>
+    <string name="ble_client_connection_priority">Testing connection priority switching </string>
     <string name="ble_server_connection_priority_result_passed">All test passed</string>
     <string name="ble_server_connection_priority_result_failed">Test failed.</string>
     <string name="ble_server_connection_priority_result_intervals">
@@ -426,9 +423,7 @@
     <string name="ble_write_authenticated_characteristic_name">Bluetooth LE Write Encrypted Characteristic</string>
     <string name="ble_read_authenticated_descriptor_name">Bluetooth LE Read Encrypted Descriptor</string>
     <string name="ble_write_authenticated_descriptor_name">Bluetooth LE Write Encrypted Descriptor</string>
-    <string name="ble_connection_priority_client_high">Bluetooth LE Send With CONNECTION_PRIORITY_HIGH</string>
-    <string name="ble_connection_priority_client_low">Bluetooth LE Send With CONNECTION_PRIORITY_LOW_POWER</string>
-    <string name="ble_connection_priority_client_balanced">Bluetooth LE Send With CONNECTION_PRIORITY_BALANCED</string>
+    <string name="ble_connection_priority_client_description">Client Switching Connection Priority</string>
     <string name="ble_indicate_characteristic_name">Bluetooth LE Indicate Characteristic</string>
     <string name="ble_encrypted_client_name">03 Bluetooth LE Encrypted Client Test</string>
     <string name="ble_encrypted_client_info">Bluetooth LE Encrypted Client read/write on characteristic and descriptor need encrypted.</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientBaseActivity.java
index 0aa4841..41a7c46 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientBaseActivity.java
@@ -40,17 +40,12 @@
 public class BleConnectionPriorityClientBaseActivity extends PassFailButtons.Activity {

 

     private TestAdapter mTestAdapter;

-    private int mPassed = 0;

+    private boolean mPassed = false;

     private Dialog mDialog;

 

-    private static final int BLE_CONNECTION_HIGH = 0;

-    private static final int BLE_CONNECTION_BALANCED = 1;

-    private static final int BLE_CONNECTION_LOW = 2;

+    private static final int BLE_CONNECTION_UPDATE = 0;

 

-    private static final int PASSED_HIGH = 0x1;

-    private static final int PASSED_BALANCED = 0x2;

-    private static final int PASSED_LOW = 0x4;

-    private static final int ALL_PASSED = 0x7;

+    private static final int ALL_PASSED = 0x1;

 

     private boolean mSecure;

 

@@ -82,9 +77,7 @@
         IntentFilter filter = new IntentFilter();

         filter.addAction(BleConnectionPriorityClientService.ACTION_BLUETOOTH_DISABLED);

         filter.addAction(BleConnectionPriorityClientService.ACTION_CONNECTION_SERVICES_DISCOVERED);

-        filter.addAction(BleConnectionPriorityClientService.ACTION_FINISH_CONNECTION_PRIORITY_HIGH);

-        filter.addAction(BleConnectionPriorityClientService.ACTION_FINISH_CONNECTION_PRIORITY_BALANCED);

-        filter.addAction(BleConnectionPriorityClientService.ACTION_FINISH_CONNECTION_PRIORITY_LOW_POWER);

+        filter.addAction(BleConnectionPriorityClientService.ACTION_CONNECTION_PRIORITY_FINISH);

         filter.addAction(BleConnectionPriorityClientService.ACTION_BLUETOOTH_MISMATCH_SECURE);

         filter.addAction(BleConnectionPriorityClientService.ACTION_BLUETOOTH_MISMATCH_INSECURE);

         filter.addAction(BleConnectionPriorityClientService.ACTION_FINISH_DISCONNECT);

@@ -142,9 +135,7 @@
 

     private List<Integer> setupTestList() {

         ArrayList<Integer> testList = new ArrayList<Integer>();

-        testList.add(R.string.ble_connection_priority_client_high);

-        testList.add(R.string.ble_connection_priority_client_balanced);

-        testList.add(R.string.ble_connection_priority_client_low);

+        testList.add(R.string.ble_connection_priority_client_description);

         return testList;

     }

 

@@ -159,44 +150,24 @@
     private void executeNextTestImpl() {

         switch (mCurrentTest) {

             case -1: {

-                mCurrentTest = BLE_CONNECTION_HIGH;

+                mCurrentTest = BLE_CONNECTION_UPDATE;

                 Intent intent = new Intent(this, BleConnectionPriorityClientService.class);

-                intent.setAction(BleConnectionPriorityClientService.ACTION_CONNECTION_PRIORITY_HIGH);

+                intent.setAction(BleConnectionPriorityClientService.ACTION_CONNECTION_PRIORITY_START);

                 startService(intent);

-                String msg = getString(R.string.ble_client_connection_priority)

-                        + getString(R.string.ble_connection_priority_high);

+                String msg = getString(R.string.ble_client_connection_priority);

                 Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();

             }

                 break;

-            case BLE_CONNECTION_BALANCED: {

-                mCurrentTest = BLE_CONNECTION_LOW;

-                Intent intent = new Intent(this, BleConnectionPriorityClientService.class);

-                intent.setAction(BleConnectionPriorityClientService.ACTION_CONNECTION_PRIORITY_LOW_POWER);

-                startService(intent);

-                String msg = getString(R.string.ble_client_connection_priority)

-                        + getString(R.string.ble_connection_priority_low);

-                Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();

-            }

-                break;

-            case BLE_CONNECTION_HIGH: {

-                mCurrentTest = BLE_CONNECTION_BALANCED;

-                Intent intent = new Intent(this, BleConnectionPriorityClientService.class);

-                intent.setAction(BleConnectionPriorityClientService.ACTION_CONNECTION_PRIORITY_BALANCED);

-                startService(intent);

-                String msg = getString(R.string.ble_client_connection_priority)

-                        + getString(R.string.ble_connection_priority_balanced);

-                Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();

-            }

-                break;

-            case BLE_CONNECTION_LOW:

+            case BLE_CONNECTION_UPDATE: {

                 // all test done

                 closeDialog();

-                if (mPassed == ALL_PASSED) {

+                if (mPassed == true) {

                     Intent intent = new Intent(this, BleConnectionPriorityClientService.class);

                     intent.setAction(BleConnectionPriorityClientService.ACTION_DISCONNECT);

                     startService(intent);

                 }

                 break;

+            }

             default:

                 // something went wrong

                 closeDialog();

@@ -229,21 +200,11 @@
                 showProgressDialog();

                 executeNextTest(3000);

                 break;

-            case BleConnectionPriorityClientService.ACTION_FINISH_CONNECTION_PRIORITY_HIGH:

-                mTestAdapter.setTestPass(BLE_CONNECTION_HIGH);

-                mPassed |= PASSED_HIGH;

+            case BleConnectionPriorityClientService.ACTION_CONNECTION_PRIORITY_FINISH:

+                mTestAdapter.setTestPass(BLE_CONNECTION_UPDATE);

+                mPassed = true;

                 executeNextTest(1000);

                 break;

-            case BleConnectionPriorityClientService.ACTION_FINISH_CONNECTION_PRIORITY_BALANCED:

-                mTestAdapter.setTestPass(BLE_CONNECTION_BALANCED);

-                mPassed |= PASSED_BALANCED;

-                executeNextTest(1000);

-                break;

-            case BleConnectionPriorityClientService.ACTION_FINISH_CONNECTION_PRIORITY_LOW_POWER:

-                mTestAdapter.setTestPass(BLE_CONNECTION_LOW);

-                mPassed |= PASSED_LOW;

-                executeNextTest(100);

-                break;

             case BleConnectionPriorityClientService.ACTION_BLUETOOTH_MISMATCH_SECURE:

                 showErrorDialog(R.string.ble_bluetooth_mismatch_title, R.string.ble_bluetooth_mismatch_secure_message, true);

                 break;

diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientService.java
index 38d37bd..1df40f5 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientService.java
@@ -62,19 +62,11 @@
     public static final String ACTION_BLUETOOTH_MISMATCH_INSECURE =

             "com.android.cts.verifier.bluetooth.action.ACTION_BLUETOOTH_MISMATCH_INSECURE";

 

-    public static final String ACTION_CONNECTION_PRIORITY_BALANCED =

-            "com.android.cts.verifier.bluetooth.action.CONNECTION_PRIORITY_BALANCED";

-    public static final String ACTION_CONNECTION_PRIORITY_HIGH =

-            "com.android.cts.verifier.bluetooth.action.CONNECTION_PRIORITY_HIGH";

-    public static final String ACTION_CONNECTION_PRIORITY_LOW_POWER =

+    public static final String ACTION_CONNECTION_PRIORITY_START =

             "com.android.cts.verifier.bluetooth.action.CONNECTION_PRIORITY_LOW_POWER";

 

-    public static final String ACTION_FINISH_CONNECTION_PRIORITY_BALANCED =

-            "com.android.cts.verifier.bluetooth.action.FINISH_CONNECTION_PRIORITY_BALANCED";

-    public static final String ACTION_FINISH_CONNECTION_PRIORITY_HIGH =

-            "com.android.cts.verifier.bluetooth.action.FINISH_CONNECTION_PRIORITY_HIGH";

-    public static final String ACTION_FINISH_CONNECTION_PRIORITY_LOW_POWER =

-            "com.android.cts.verifier.bluetooth.action.FINISH_CONNECTION_PRIORITY_LOW_POWER";

+    public static final String ACTION_CONNECTION_PRIORITY_FINISH =

+            "com.android.cts.verifier.bluetooth.action.CONNECTION_PRIORITY_FINISH";

 

     public static final String ACTION_CLIENT_CONNECT_SECURE =

             "com.android.cts.verifier.bluetooth.action.CLIENT_CONNECT_SECURE";

@@ -84,20 +76,7 @@
     public static final String ACTION_FINISH_DISCONNECT =

             "com.android.cts.verifier.bluetooth.action.FINISH_DISCONNECT";

 

-    public static final long DEFAULT_INTERVAL = 100L;

-    public static final long DEFAULT_PERIOD = 10000L;

-

-    // this string will be used at writing test and connection priority test.

-    private static final String WRITE_VALUE = "TEST";

-

-    private static final UUID SERVICE_UUID =

-            UUID.fromString("00009999-0000-1000-8000-00805f9b34fb");

-    private static final UUID CHARACTERISTIC_UUID =

-            UUID.fromString("00009998-0000-1000-8000-00805f9b34fb");

-    private static final UUID START_CHARACTERISTIC_UUID =

-            UUID.fromString("00009997-0000-1000-8000-00805f9b34fb");

-    private static final UUID STOP_CHARACTERISTIC_UUID =

-            UUID.fromString("00009995-0000-1000-8000-00805f9b34fb");

+    public static final int NOT_UNDER_TEST = -1;

 

     private BluetoothManager mBluetoothManager;

     private BluetoothAdapter mBluetoothAdapter;

@@ -108,13 +87,12 @@
     private Context mContext;

 

     private String mAction;

-    private long mInterval;

-    private long mPeriod;

-    private Date mStartDate;

-    private int mWriteCount;

     private boolean mSecure;

 

-    private String mPriority;

+    private int mPriority = NOT_UNDER_TEST;

+    private int interval_low = 0;

+    private int interval_balanced = 0;

+    private int interval_high = 0;

 

     private TestTaskQueue mTaskQueue;

 

@@ -129,8 +107,6 @@
         mScanner = mBluetoothAdapter.getBluetoothLeScanner();

         mHandler = new Handler();

         mContext = this;

-        mInterval = DEFAULT_INTERVAL;

-        mPeriod = DEFAULT_PERIOD;

 

         startScan();

     }

@@ -171,15 +147,8 @@
                 case ACTION_CLIENT_CONNECT_SECURE:

                     mSecure = true;

                     break;

-                case ACTION_CONNECTION_PRIORITY_BALANCED:

-                case ACTION_CONNECTION_PRIORITY_HIGH:

-                case ACTION_CONNECTION_PRIORITY_LOW_POWER:

-                    mTaskQueue.addTask(new Runnable() {

-                        @Override

-                        public void run() {

-                            startPeriodicTransmission();

-                        }

-                    });

+                case ACTION_CONNECTION_PRIORITY_START:

+                    myRequestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER);

                     break;

                 case ACTION_DISCONNECT:

                     if (mBluetoothGatt != null) {

@@ -194,120 +163,17 @@
         return START_NOT_STICKY;

     }

 

-    private void startPeriodicTransmission() {

-        mWriteCount = 0;

-

-        // Set connection priority

-        switch (mAction) {

-        case ACTION_CONNECTION_PRIORITY_BALANCED:

-            mPriority = BleConnectionPriorityServerService.CONNECTION_PRIORITY_BALANCED;

-            mBluetoothGatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_BALANCED);

-            break;

-        case ACTION_CONNECTION_PRIORITY_HIGH:

-            mPriority = BleConnectionPriorityServerService.CONNECTION_PRIORITY_HIGH;

-            mBluetoothGatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);

-            break;

-        case ACTION_CONNECTION_PRIORITY_LOW_POWER:

-            mPriority = BleConnectionPriorityServerService.CONNECTION_PRIORITY_LOW_POWER;

-            mBluetoothGatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER);

-            break;

-        default:

-            mPriority = BleConnectionPriorityServerService.CONNECTION_PRIORITY_BALANCED;

-            mBluetoothGatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_BALANCED);

-            break;

-        }

-

-        // Create Timer for Periodic transmission

-        mStartDate = new Date();

-        TimerTask task = new TimerTask() {

-            @Override

-            public void run() {

-                if (mBluetoothGatt == null) {

-                    if (DEBUG) {

-                        Log.d(TAG, "BluetoothGatt is null, return");

-                    }

-                    return;

-                }

-

-                Date currentData = new Date();

-                if ((currentData.getTime() - mStartDate.getTime()) >= mPeriod) {

-                    if (mConnectionTimer != null) {

-                        mConnectionTimer.cancel();

-                        mConnectionTimer = null;

-                    }

-                    // The STOP_CHARACTERISTIC_UUID is critical in syncing the client and server

-                    // states.  Delay the write by 2 seconds to improve the chance of this

-                    // characteristic going through.  Consider changing the code to use callbacks

-                    // in the future to make it more robust.

-                    sleep(2000);

-                    // write termination data (contains current priority and number of messages wrote)

-                    String msg = "" + mPriority + "," + mWriteCount;

-                    writeCharacteristic(STOP_CHARACTERISTIC_UUID, msg);

-                    sleep(1000);

-                    Intent intent = new Intent();

-                    switch (mPriority) {

-                    case BleConnectionPriorityServerService.CONNECTION_PRIORITY_BALANCED:

-                        intent.setAction(ACTION_FINISH_CONNECTION_PRIORITY_BALANCED);

-                        break;

-                    case BleConnectionPriorityServerService.CONNECTION_PRIORITY_HIGH:

-                        intent.setAction(ACTION_FINISH_CONNECTION_PRIORITY_HIGH);

-                        break;

-                    case BleConnectionPriorityServerService.CONNECTION_PRIORITY_LOW_POWER:

-                        intent.setAction(ACTION_FINISH_CONNECTION_PRIORITY_LOW_POWER);

-                        break;

-                    }

-                    sendBroadcast(intent);

-                }

-

-                if (mConnectionTimer != null) {

-                    // write testing data

-                    ++mWriteCount;

-                    writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE);

-                }

-            }

-        };

-

-        // write starting data

-        writeCharacteristic(START_CHARACTERISTIC_UUID, mPriority);

-

-        // start sending

-        sleep(1000);

-        mConnectionTimer = new Timer();

-        mConnectionTimer.schedule(task, 0, mInterval);

+    private void myRequestConnectionPriority(final int priority) {

+        mTaskQueue.addTask(new Runnable() {

+                                @Override

+                                public void run() {

+                                    mPriority = priority;

+                                    mBluetoothGatt.requestConnectionPriority(mPriority);

+                                    //continue in onConnectionUpdated() callback

+                                }

+                            });

     }

 

-    private BluetoothGattService getService() {

-        BluetoothGattService service = null;

-

-        if (mBluetoothGatt != null) {

-            service = mBluetoothGatt.getService(SERVICE_UUID);

-            if (service == null) {

-                showMessage("Service not found");

-            }

-        }

-        return service;

-    }

-

-    private BluetoothGattCharacteristic getCharacteristic(UUID uuid) {

-        BluetoothGattCharacteristic characteristic = null;

-

-        BluetoothGattService service = getService();

-        if (service != null) {

-            characteristic = service.getCharacteristic(uuid);

-            if (characteristic == null) {

-                showMessage("Characteristic not found");

-            }

-        }

-        return characteristic;

-    }

-

-    private void writeCharacteristic(UUID uid, String writeValue) {

-        BluetoothGattCharacteristic characteristic = getCharacteristic(uid);

-        if (characteristic != null){

-            characteristic.setValue(writeValue);

-            mBluetoothGatt.writeCharacteristic(characteristic);

-        }

-    }

 

     private void sleep(int millis) {

         try {

@@ -372,19 +238,56 @@
             if (DEBUG){

                 Log.d(TAG, "onServiceDiscovered");

             }

-            if ((status == BluetoothGatt.GATT_SUCCESS) && (mBluetoothGatt.getService(SERVICE_UUID) != null)) {

+            if (status == BluetoothGatt.GATT_SUCCESS) {

                 showMessage("Service discovered");

                 Intent intent = new Intent(ACTION_CONNECTION_SERVICES_DISCOVERED);

                 sendBroadcast(intent);

             }

-        }

 

-        @Override

-        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

-            String value = characteristic.getStringValue(0);

-            UUID uid = characteristic.getUuid();

-            if (DEBUG) {

-                Log.d(TAG, "onCharacteristicWrite: characteristic.val=" + value + " status=" + status + " uid=" + uid);

+            //onConnectionUpdated is hidden callback, can't be marked as @Override.

+            // We must have a call to it, otherwise compiler will delete it during optimization.

+            if (status == 0xFFEFFEE) {

+                // This should never execute, but will make compiler not remove onConnectionUpdated 

+                onConnectionUpdated(null, 0, 0, 0, 0);

+                throw new IllegalStateException("This should never happen!");

+            }

+        }

+ 

+        // @Override uncomment once this becomes public API

+        public void onConnectionUpdated(BluetoothGatt gatt, int interval, int latency, int timeout,

+            int status) {

+            if (mPriority == NOT_UNDER_TEST) return;

+

+            if (status != 0) {

+                showMessage("onConnectionUpdated() error, status=" + status );

+                Log.e(TAG, "onConnectionUpdated() status=" + status);

+                return;

+            }

+

+            Log.i(TAG, "onConnectionUpdated() status=" + status + ", interval=" + interval);

+            if (mPriority == BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER) {

+                interval_low = interval;

+                myRequestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_BALANCED);

+            } else if (mPriority == BluetoothGatt.CONNECTION_PRIORITY_BALANCED) {

+                interval_balanced = interval;

+                myRequestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);

+            } else if (mPriority == BluetoothGatt.CONNECTION_PRIORITY_HIGH) {

+                interval_high = interval;

+

+                if (interval_low < interval_balanced || interval_balanced < interval_high) {

+                   showMessage("interval value should be descending - failure!");

+                   Log.e(TAG, "interval values should be descending: interval_low=" + interval_low +

+                            ", interval_balanced=" + interval_balanced + ", interval_high=" + interval_high);

+                   return;

+                }

+

+                showMessage("intervals: " + interval_low +" > " + interval_balanced + " > " + interval_high);

+         

+                Intent intent = new Intent();

+                intent.setAction(ACTION_CONNECTION_PRIORITY_FINISH);

+                sendBroadcast(intent);

+        

+                mPriority = NOT_UNDER_TEST;

             }

         }

     };

diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityServerBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityServerBaseActivity.java
index c0a2f09..66e068e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityServerBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityServerBaseActivity.java
@@ -37,12 +37,6 @@
 public class BleConnectionPriorityServerBaseActivity extends PassFailButtons.Activity {

 

     public static final int CONNECTION_PRIORITY_HIGH = 0;

-    public static final int CONNECTION_PRIORITY_BALANCED = 1;

-    public static final int CONNECTION_PRIORITY_LOW_POWER = 2;

-

-    private long mAverageBalanced = -1;

-    private long mAverageHigh = -1;

-    private long mAverageLow = -1;

 

     private TestAdapter mTestAdapter;

 

@@ -71,10 +65,7 @@
 

         IntentFilter filter = new IntentFilter();

         filter.addAction(BleConnectionPriorityServerService.ACTION_BLUETOOTH_DISABLED);

-        filter.addAction(BleConnectionPriorityServerService.ACTION_CONNECTION_WRITE_REQUEST);

-        filter.addAction(BleConnectionPriorityServerService.ACTION_FINICH_CONNECTION_PRIORITY_HIGHT);

-        filter.addAction(BleConnectionPriorityServerService.ACTION_FINICH_CONNECTION_PRIORITY_BALANCED);

-        filter.addAction(BleConnectionPriorityServerService.ACTION_FINICH_CONNECTION_PRIORITY_LOW);

+        filter.addAction(BleConnectionPriorityServerService.ACTION_CONNECTION_PRIORITY_FINISH);

         filter.addAction(BleServerService.BLE_ADVERTISE_UNSUPPORTED);

         filter.addAction(BleServerService.BLE_OPEN_FAIL);

         filter.addAction(BleConnectionPriorityServerService.ACTION_START_CONNECTION_PRIORITY_TEST);

@@ -90,9 +81,7 @@
 

     private List<Integer> setupTestList() {

         ArrayList<Integer> testList = new ArrayList<Integer>();

-        testList.add(R.string.ble_connection_priority_client_high);

-        testList.add(R.string.ble_connection_priority_client_balanced);

-        testList.add(R.string.ble_connection_priority_client_low);

+        testList.add(R.string.ble_connection_priority_client_description);

         return testList;

     }

 

@@ -130,8 +119,8 @@
     private BroadcastReceiver mBroadcast = new BroadcastReceiver() {

         @Override

         public void onReceive(Context context, Intent intent) {

+            boolean passedAll = false;

             String action = intent.getAction();

-            long average = intent.getLongExtra(BleConnectionPriorityServerService.EXTRA_AVERAGE, -1);

             switch (action) {

             case BleConnectionPriorityServerService.ACTION_BLUETOOTH_DISABLED:

                 new AlertDialog.Builder(context)

@@ -148,64 +137,12 @@
             case BleConnectionPriorityServerService.ACTION_START_CONNECTION_PRIORITY_TEST:

                 showProgressDialog();

                 break;

-            case BleConnectionPriorityServerService.ACTION_FINICH_CONNECTION_PRIORITY_HIGHT:

-                mAverageHigh = average;

-                mAverageBalanced = -1;

-                mAverageLow = -1;

-                break;

-            case BleConnectionPriorityServerService.ACTION_FINICH_CONNECTION_PRIORITY_BALANCED:

-                mAverageBalanced = average;

-                break;

-            case BleConnectionPriorityServerService.ACTION_FINICH_CONNECTION_PRIORITY_LOW:

-                mAverageLow = average;

-                break;

-            case BleServerService.BLE_OPEN_FAIL:

-                setTestResultAndFinish(false);

-                runOnUiThread(new Runnable() {

-                    @Override

-                    public void run() {

-                        Toast.makeText(BleConnectionPriorityServerBaseActivity.this, R.string.bt_open_failed_message, Toast.LENGTH_SHORT).show();

-                    }

-                });

-                break;

-            case BleServerService.BLE_ADVERTISE_UNSUPPORTED:

-                showErrorDialog(R.string.bt_advertise_unsupported_title, R.string.bt_advertise_unsupported_message, true);

-                break;

-            }

-

-            boolean passedHigh = (mAverageHigh >= 0);

-            boolean passedAll = false;

-

-            if (passedHigh) {

-                mTestAdapter.setTestPass(CONNECTION_PRIORITY_HIGH);

-            }

-

-            if (passedHigh && (mAverageLow >= 0) && (mAverageBalanced >= 0)) {

-                boolean passedBalanced = (mAverageHigh <= mAverageBalanced);

-                boolean passedLow = (mAverageBalanced <= mAverageLow);

-

-                if (passedBalanced) {

-                    mTestAdapter.setTestPass(CONNECTION_PRIORITY_BALANCED);

-                }

-                if (passedLow) {

-                    mTestAdapter.setTestPass(CONNECTION_PRIORITY_LOW_POWER);

-                }

-

-                String resultMsg;

-                if (passedBalanced && passedLow) {

-                    resultMsg = getString(R.string.ble_server_connection_priority_result_passed);

-                    passedAll = true;

-                } else {

-                    String detailsMsg = String.format(getString(R.string.ble_server_connection_priority_result_intervals),

-                            mAverageHigh,

-                            mAverageBalanced,

-                            mAverageLow);

-                    resultMsg = getString(R.string.ble_server_connection_priority_result_failed)

-                            + "\n\n"

-                            + detailsMsg;

-                }

+            case BleConnectionPriorityServerService.ACTION_CONNECTION_PRIORITY_FINISH:

+                String resultMsg = getString(R.string.ble_server_connection_priority_result_passed);

 

                 closeDialog();

+

+                mTestAdapter.setTestPass(CONNECTION_PRIORITY_HIGH);

                 mDialog = new AlertDialog.Builder(BleConnectionPriorityServerBaseActivity.this)

                         .setMessage(resultMsg)

                         .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

@@ -222,10 +159,25 @@
                         })

                         .create();

                 mDialog.show();

+

+                getPassButton().setEnabled(true);

+                mTestAdapter.notifyDataSetChanged();

+                break;

+

+            case BleServerService.BLE_OPEN_FAIL:

+                setTestResultAndFinish(false);

+                runOnUiThread(new Runnable() {

+                    @Override

+                    public void run() {

+                        Toast.makeText(BleConnectionPriorityServerBaseActivity.this, R.string.bt_open_failed_message, Toast.LENGTH_SHORT).show();

+                    }

+                });

+                break;

+            case BleServerService.BLE_ADVERTISE_UNSUPPORTED:

+                showErrorDialog(R.string.bt_advertise_unsupported_title, R.string.bt_advertise_unsupported_message, true);

+                break;

             }

 

-            getPassButton().setEnabled(passedAll);

-            mTestAdapter.notifyDataSetChanged();

         }

     };

 

diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityServerService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityServerService.java
index e1e4eed..ccffcdb 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityServerService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityServerService.java
@@ -45,43 +45,16 @@
 public class BleConnectionPriorityServerService extends Service {

     public static final boolean DEBUG = true;

     public static final String TAG = "BlePriorityServer";

-    private static final String RESET_COUNT_VALUE = "RESET";

-    private static final String START_VALUE = "START";

-    private static final String STOP_VALUE = "STOP";

-    public static final String CONNECTION_PRIORITY_HIGH = "PR_H";

-    public static final String CONNECTION_PRIORITY_BALANCED = "PR_B";

-    public static final String CONNECTION_PRIORITY_LOW_POWER = "PR_L";

 

     public static final String ACTION_BLUETOOTH_DISABLED =

             "com.android.cts.verifier.bluetooth.action.BLUETOOTH_DISABLED";

 

-    public static final String ACTION_CONNECTION_WRITE_REQUEST =

-            "com.android.cts.verifier.bluetooth.action.CONNECTION_WRITE_REQUEST";

-    public static final String EXTRA_REQUEST_COUNT =

-            "com.android.cts.verifier.bluetooth.intent.EXTRA_REQUEST_COUNT";

-    public static final String ACTION_FINICH_CONNECTION_PRIORITY_HIGHT =

-            "com.android.cts.verifier.bluetooth.action.ACTION_FINICH_CONNECTION_PRIORITY_HIGHT";

-    public static final String ACTION_FINICH_CONNECTION_PRIORITY_BALANCED =

-            "com.android.cts.verifier.bluetooth.action.ACTION_FINICH_CONNECTION_PRIORITY_BALANCED";

-    public static final String ACTION_FINICH_CONNECTION_PRIORITY_LOW =

-            "com.android.cts.verifier.bluetooth.action.ACTION_FINICH_CONNECTION_PRIORITY_LOW";

+    public static final String ACTION_CONNECTION_PRIORITY_FINISH =

+            "com.android.cts.verifier.bluetooth.action.ACTION_CONNECTION_PRIORITY_FINISH";

 

     public static final String ACTION_START_CONNECTION_PRIORITY_TEST =

             "com.android.cts.verifier.bluetooth.action.ACTION_START_CONNECTION_PRIORITY_TEST";

 

-    public static final String EXTRA_AVERAGE =

-            "com.android.cts.verifier.bluetooth.intent.EXTRA_AVERAGE";

-

-    private static final UUID SERVICE_UUID =

-            UUID.fromString("00009999-0000-1000-8000-00805f9b34fb");

-    private static final UUID CHARACTERISTIC_UUID =

-            UUID.fromString("00009998-0000-1000-8000-00805f9b34fb");

-    private static final UUID START_CHARACTERISTIC_UUID =

-            UUID.fromString("00009997-0000-1000-8000-00805f9b34fb");

-    private static final UUID STOP_CHARACTERISTIC_UUID =

-            UUID.fromString("00009995-0000-1000-8000-00805f9b34fb");

-    private static final UUID DESCRIPTOR_UUID =

-            UUID.fromString("00009996-0000-1000-8000-00805f9b34fb");

     public static final UUID ADV_SERVICE_UUID=

             UUID.fromString("00002222-0000-1000-8000-00805f9b34fb");

 

@@ -92,8 +65,10 @@
     private Handler mHandler;

     private BluetoothLeAdvertiser mAdvertiser;

     private long mReceiveWriteCount;

-    private Timer mTimeoutTimer;

-    private TimerTask mTimeoutTimerTask;

+

+    private int interval_low = 0;

+    private int interval_balanced = 0;

+    private int interval_high = 0;

 

     @Override

     public void onCreate() {

@@ -102,10 +77,6 @@
         mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

         mAdvertiser = mBluetoothManager.getAdapter().getBluetoothLeAdvertiser();

         mGattServer = mBluetoothManager.openGattServer(this, mCallbacks);

-        mService = createService();

-        if ((mGattServer != null) && (mAdvertiser != null)) {

-            mGattServer.addService(mService);

-        }

         mDevice = null;

         mHandler = new Handler();

 

@@ -124,14 +95,6 @@
     public void onDestroy() {

         super.onDestroy();

 

-        cancelTimeoutTimer(false);

-

-        if (mTimeoutTimer != null) {

-            mTimeoutTimer.cancel();

-            mTimeoutTimer = null;

-        }

-        mTimeoutTimerTask = null;

-

         stopAdvertise();

         if (mGattServer == null) {

             return;

@@ -194,21 +157,6 @@
         }

     }

 

-    private void notifyServiceAdded() {

-        if (DEBUG) {

-            Log.d(TAG, "notifyServiceAdded");

-        }

-    }

-

-    private void notifyCharacteristicWriteRequest() {

-        if (DEBUG) {

-            Log.d(TAG, "notifyCharacteristicWriteRequest");

-        }

-        Intent intent = new Intent(ACTION_CONNECTION_WRITE_REQUEST);

-        intent.putExtra(EXTRA_REQUEST_COUNT, String.valueOf(mReceiveWriteCount));

-        sendBroadcast(intent);

-    }

-

     private void showMessage(final String msg) {

         mHandler.post(new Runnable() {

             @Override

@@ -218,38 +166,6 @@
         });

     }

 

-    private synchronized void cancelTimeoutTimer(boolean runTimeout) {

-        if (mTimeoutTimerTask != null) {

-            mTimeoutTimer.cancel();

-            if (runTimeout) {

-                mTimeoutTimerTask.run();

-            }

-            mTimeoutTimerTask = null;

-            mTimeoutTimer = null;

-        }

-    }

-

-    private BluetoothGattService createService() {

-        BluetoothGattService service =

-                new BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);

-        // add characteristic to service

-        //   property: 0x0A (read, write)

-        //   permission: 0x11 (read, write)

-        BluetoothGattCharacteristic characteristic =

-                new BluetoothGattCharacteristic(CHARACTERISTIC_UUID, 0x0A, 0x11);

-        BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(DESCRIPTOR_UUID, 0x11);

-        characteristic.addDescriptor(descriptor);

-        service.addCharacteristic(characteristic);

-        characteristic = new BluetoothGattCharacteristic(START_CHARACTERISTIC_UUID, 0x0A, 0x11);

-        characteristic.addDescriptor(descriptor);

-        service.addCharacteristic(characteristic);

-        characteristic = new BluetoothGattCharacteristic(STOP_CHARACTERISTIC_UUID, 0x0A, 0x11);

-        characteristic.addDescriptor(descriptor);

-        service.addCharacteristic(characteristic);

-

-        return service;

-    }

-

     private final BluetoothGattServerCallback mCallbacks = new BluetoothGattServerCallback() {

         @Override

         public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {

@@ -261,120 +177,50 @@
                     mDevice = device;

                     notifyConnected();

                 } else if (status == BluetoothProfile.STATE_DISCONNECTED) {

-                    cancelTimeoutTimer(true);

                     notifyDisconnected();

                     mDevice = null;

                 }

             }

+

+            //onConnectionUpdated is hidden callback, can't be marked as @Override.

+            // We must have a call to it, otherwise compiler will delete it during optimization.

+            if (status == 0xFFEFFEE) {

+                // This should never execute, but will make compiler not remove onConnectionUpdated 

+                onConnectionUpdated(null, 0, 0, 0, 0);

+                throw new IllegalStateException("This should never happen!");

+            }

+

         }

 

-        @Override

-        public void onServiceAdded(int status, BluetoothGattService service) {

-            if (DEBUG) {

-                Log.d(TAG, "onServiceAdded()");

-            }

-            if (status == BluetoothGatt.GATT_SUCCESS) {

-                notifyServiceAdded();

-            }

-        }

+        // @Override uncomment once this becomes public API

+        public void onConnectionUpdated(BluetoothDevice device, int interval, int latency, int timeout, int status) {

+            Log.i(TAG, "onConnectionUpdated() status=" + status + ", interval=" + interval);

 

-        String mPriority = null;

-

-        @Override

-        public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,

-                                                 BluetoothGattCharacteristic characteristic,

-                                                 boolean preparedWrite, boolean responseNeeded,

-                                                 int offset, byte[] value) {

-            if (mGattServer == null) {

-                if (DEBUG) {

-                    Log.d(TAG, "GattServer is null, return");

-                }

-                return;

-            }

-            if (DEBUG) {

-                Log.d(TAG, "onCharacteristicWriteRequest: preparedWrite=" + preparedWrite);

+            if (status != 0) {

+               interval_low = interval_balanced = interval_high = 0;

+               return;

             }

 

-            if (characteristic.getUuid().equals(START_CHARACTERISTIC_UUID)) {

-                // time out if previous measurement is running

-                cancelTimeoutTimer(true);

+            // since we don't know when the test started, wait for three descending interval values.

+            // Even though conneciton is updated by service discovery, it never happen three times

+            // descending in any scenario. 

 

-                mPriority = new String(value);

-                Log.d(TAG, "Start Count Up. Priority is " + mPriority);

-                if (BleConnectionPriorityServerService.CONNECTION_PRIORITY_HIGH.equals(mPriority)) {

-                    notifyTestStart();

-                }

+            // shift all values

+            interval_low = interval_balanced;

+            interval_balanced = interval_high;

+            interval_high = interval;

 

-                // start timeout timer

-                mTimeoutTimer = new Timer(getClass().getName() + "_TimeoutTimer");

-                mTimeoutTimerTask = new TimerTask() {

-                    @Override

-                    public void run() {

-                        // measurement timed out

-                        mTimeoutTimerTask = null;

-                        mTimeoutTimer = null;

-                        mReceiveWriteCount = 0;

-                        notifyMeasurementFinished(mPriority, Long.MAX_VALUE);

-                    }

-                };

-                mTimeoutTimer.schedule(mTimeoutTimerTask, (BleConnectionPriorityClientService.DEFAULT_PERIOD * 2));

-

-                mReceiveWriteCount = 0;

-            } else if (characteristic.getUuid().equals(STOP_CHARACTERISTIC_UUID)) {

-                boolean isRunning = (mTimeoutTimerTask != null);

-                cancelTimeoutTimer(false);

-

-                String valeStr = new String(value);

-                String priority = null;

-                int writeCount = -1;

-                int sep = valeStr.indexOf(",");

-                if (sep > 0) {

-                    priority = valeStr.substring(0, sep);

-                    writeCount = Integer.valueOf(valeStr.substring(sep + 1));

-                }

-

-                if ((mPriority != null) && isRunning) {

-                    if (mPriority.equals(priority)) {

-                        long averageTime = BleConnectionPriorityClientService.DEFAULT_PERIOD / mReceiveWriteCount;

-                        notifyMeasurementFinished(mPriority, averageTime);

-                        Log.d(TAG, "Received " + mReceiveWriteCount + " of " + writeCount + " messages");

-                    } else {

-                        Log.d(TAG, "Connection priority does not match");

-                        showMessage("Connection priority does not match");

-                    }

-                } else {

-                    Log.d(TAG, "Not Start Count UP.");

-                }

-                mReceiveWriteCount = 0;

-            } else {

-                if (mTimeoutTimerTask != null) {

-                    ++mReceiveWriteCount;

-                }

-                if (!preparedWrite) {

-                    characteristic.setValue(value);

-                }

-            }

-

-            if (responseNeeded) {

-                mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null);

+            // If we end up with three descending values, test is passed.

+            if (interval_low > interval_balanced && interval_balanced > interval_high) {

+                showMessage("intervals: " + interval_low +" > " + interval_balanced + " > " + interval_high);

+                notifyMeasurementFinished();

             }

         }

     };

 

-    private void notifyMeasurementFinished(String priority, long averageTime) {

+    private void notifyMeasurementFinished() {

         Intent intent = new Intent();

-        intent.putExtra(EXTRA_AVERAGE, averageTime);

-        switch (priority) {

-            case CONNECTION_PRIORITY_HIGH:

-                intent.setAction(ACTION_FINICH_CONNECTION_PRIORITY_HIGHT);

-                break;

-            case CONNECTION_PRIORITY_BALANCED:

-                intent.setAction(ACTION_FINICH_CONNECTION_PRIORITY_BALANCED);

-                break;

-            case CONNECTION_PRIORITY_LOW_POWER:

-                intent.setAction(ACTION_FINICH_CONNECTION_PRIORITY_LOW);

-                break;

-        }

+        intent.setAction(ACTION_CONNECTION_PRIORITY_FINISH);

         sendBroadcast(intent);

     }

 

diff --git a/common/util/src/com/android/compatibility/common/util/CrashUtils.java b/common/util/src/com/android/compatibility/common/util/CrashUtils.java
index 2b0531c..ef2a633 100644
--- a/common/util/src/com/android/compatibility/common/util/CrashUtils.java
+++ b/common/util/src/com/android/compatibility/common/util/CrashUtils.java
@@ -17,6 +17,10 @@
 package com.android.compatibility.common.util;
 
 import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.json.JSONArray;
@@ -61,12 +65,9 @@
     private static Pattern sAbortMessageCheckPattern =
             Pattern.compile("(?i)Abort message.*?CHECK_");
 
-    /**
-     * returns true if the signal is a segmentation fault or bus error.
-     */
-    public static boolean isSecuritySignal(JSONObject crash) throws JSONException {
-        return crash.getString(SIGNAL).toLowerCase().matches("sig(segv|bus)");
-    }
+    public static final String SIGSEGV = "SIGSEGV";
+    public static final String SIGBUS = "SIGBUS";
+    public static final String SIGABRT = "SIGABRT";
 
     /**
      * returns the filename of the process.
@@ -80,14 +81,12 @@
      * Determines if the given input has a {@link com.android.compatibility.common.util.Crash} that
      * should fail an sts test
      *
-     * @param processPatterns list of patterns that match applicable process names
-     * @param checkMinAddr if the minimum fault address should be respected
      * @param crashes list of crashes to check
+     * @param config crash detection configuration object
      * @return if a crash is serious enough to fail an sts test
      */
-    public static boolean securityCrashDetected(
-            JSONArray crashes, boolean checkMinAddr, Pattern... processPatterns) {
-        return matchSecurityCrashes(crashes, checkMinAddr, processPatterns).length() > 0;
+    public static boolean securityCrashDetected(JSONArray crashes, Config config) {
+        return matchSecurityCrashes(crashes, config).length() > 0;
     }
 
     public static BigInteger getBigInteger(JSONObject source, String name) throws JSONException {
@@ -106,30 +105,36 @@
      * Determines which given inputs have a {@link com.android.compatibility.common.util.Crash} that
      * should fail an sts test
      *
-     * @param processPatterns list of patterns that match applicable process names
-     * @param checkMinAddr if the minimum fault address should be respected
      * @param crashes list of crashes to check
+     * @param config crash detection configuration object
      * @return the list of crashes serious enough to fail an sts test
      */
-    public static JSONArray matchSecurityCrashes(
-            JSONArray crashes, boolean checkMinAddr, Pattern... processPatterns) {
+    public static JSONArray matchSecurityCrashes(JSONArray crashes, Config config) {
         JSONArray securityCrashes = new JSONArray();
         for (int i = 0; i < crashes.length(); i++) {
             try {
                 JSONObject crash = crashes.getJSONObject(i);
-                if (!matchesAny(getProcessFileName(crash), processPatterns)) {
+                // match process patterns
+                if (!matchesAny(getProcessFileName(crash), config.processPatterns)) {
                     continue;
                 }
-                if (!isSecuritySignal(crash)) {
+
+                // match signal
+                String crashSignal = crash.getString(SIGNAL);
+                if (!config.signals.contains(crashSignal)) {
                     continue;
                 }
-                BigInteger faultAddress = getBigInteger(crash, FAULT_ADDRESS);
-                if (checkMinAddr && faultAddress != null
-                        && faultAddress.compareTo(MIN_CRASH_ADDR) < 0) {
-                    continue;
+
+                // if check specified, reject crash if address is unlikely to be security-related
+                if (config.checkMinAddress) {
+                    BigInteger faultAddress = getBigInteger(crash, FAULT_ADDRESS);
+                    if (faultAddress != null
+                            && faultAddress.compareTo(config.minCrashAddress) < 0) {
+                        continue;
+                    }
                 }
                 securityCrashes.put(crash);
-            } catch (JSONException | NullPointerException e) {}
+            } catch (JSONException e) {}
         }
         return securityCrashes;
     }
@@ -137,7 +142,7 @@
     /**
      * returns true if the input matches any of the patterns.
      */
-    private static boolean matchesAny(String input, Pattern... patterns) {
+    private static boolean matchesAny(String input, Collection<Pattern> patterns) {
         for (Pattern p : patterns) {
             if (p.matcher(input).matches()) {
                 return true;
@@ -196,4 +201,53 @@
         }
         return crashes;
     }
+
+    public static class Config {
+        private boolean checkMinAddress = true;
+        private BigInteger minCrashAddress = MIN_CRASH_ADDR;
+        private List<String> signals = Arrays.asList(SIGSEGV, SIGBUS);
+        private List<Pattern> processPatterns = Collections.emptyList();
+
+        public Config setMinAddress(BigInteger minCrashAddress) {
+            this.minCrashAddress = minCrashAddress;
+            return this;
+        }
+
+        public Config checkMinAddress(boolean checkMinAddress) {
+            this.checkMinAddress = checkMinAddress;
+            return this;
+        }
+
+        public Config setSignals(String... signals) {
+            this.signals = Arrays.asList(signals);
+            return this;
+        }
+
+        public Config appendSignals(String... signals) {
+            Collections.addAll(this.signals, signals);
+            return this;
+        }
+
+        public Config setProcessPatterns(String... processPatternStrings) {
+            Pattern[] processPatterns = new Pattern[processPatternStrings.length];
+            for (int i = 0; i < processPatternStrings.length; i++) {
+                processPatterns[i] = Pattern.compile(processPatternStrings[i]);
+            }
+            return setProcessPatterns(processPatterns);
+        }
+
+        public Config setProcessPatterns(Pattern... processPatterns) {
+            this.processPatterns = Arrays.asList(processPatterns);
+            return this;
+        }
+
+        public List<Pattern> getProcessPatterns() {
+            return Collections.unmodifiableList(processPatterns);
+        }
+
+        public Config appendProcessPatterns(Pattern... processPatterns) {
+            Collections.addAll(this.processPatterns, processPatterns);
+            return this;
+        }
+    }
 }
diff --git a/common/util/tests/src/com/android/compatibility/common/util/CrashUtilsTest.java b/common/util/tests/src/com/android/compatibility/common/util/CrashUtilsTest.java
index 2138b7b..071733f 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/CrashUtilsTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/CrashUtilsTest.java
@@ -91,51 +91,61 @@
 
     @Test
     public void testValidCrash() throws Exception {
-        Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, true,
-                Pattern.compile("synthetic_process_0")));
+        Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile("synthetic_process_0"))));
     }
 
     @Test
     public void testMissingName() throws Exception {
-        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, true,
-                Pattern.compile("")));
+        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile(""))));
     }
 
     @Test
     public void testSIGABRT() throws Exception {
-        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, true,
-                Pattern.compile("installd")));
+        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile("installd"))));
     }
 
     @Test
     public void testFaultAddressBelowMin() throws Exception {
-        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, true,
-                Pattern.compile("synthetic_process_1")));
+        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile("synthetic_process_1"))));
     }
 
     @Test
     public void testIgnoreMinAddressCheck() throws Exception {
-        Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, false,
-                Pattern.compile("synthetic_process_1")));
+        Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(false)
+                .setProcessPatterns(Pattern.compile("synthetic_process_1"))));
     }
 
     @Test
     public void testBadAbortMessage() throws Exception {
-        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, true,
-                Pattern.compile("generic")));
+        Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile("generic"))));
     }
 
     @Test
     public void testGoodAndBadCrashes() throws Exception {
-        Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, true,
-                Pattern.compile("synthetic_process_0"), Pattern.compile("generic")));
+        Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(
+                        Pattern.compile("synthetic_process_0"),
+                        Pattern.compile("generic"))));
     }
 
     @Test
     public void testNullFaultAddress() throws Exception {
         JSONArray crashes = new JSONArray();
         crashes.put(createCrashJson(8373, 8414, "loo", "com.android.bluetooth", null, "SIGSEGV"));
-        Assert.assertTrue(CrashUtils.securityCrashDetected(crashes, true,
-                Pattern.compile("com\\.android\\.bluetooth")));
+        Assert.assertTrue(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .checkMinAddress(true)
+                .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
     }
 }
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index d901690..554b6ca 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -50,6 +50,7 @@
 import static org.junit.matchers.JUnitMatchers.hasItems;
 
 import com.google.common.collect.ImmutableSet;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.Context;
 import android.os.Build;
@@ -151,6 +152,10 @@
                 KM_PURPOSE_SIGN, KM_PURPOSE_VERIFY, KM_PURPOSE_SIGN | KM_PURPOSE_VERIFY
         };
 
+        // Skip the test if there is no secure lock screen
+        if (!hasSecureLockScreen()) {
+            return;
+        }
         for (int curveIndex = 0; curveIndex < curves.length; ++curveIndex) {
             for (int challengeIndex = 0; challengeIndex < challenges.length; ++challengeIndex) {
                 for (int purposeIndex = 0; purposeIndex < purposes.length; ++purposeIndex) {
@@ -276,6 +281,10 @@
                 },
         };
 
+        // Skip the test if there is no secure lock screen
+        if (!hasSecureLockScreen()) {
+            return;
+        }
         for (int keySize : keySizes) {
             for (byte[] challenge : challenges) {
                 for (int purpose : purposes) {
@@ -909,4 +918,15 @@
             }
         }
     }
+    /*
+     * Device that don't report android.software.device_admin doesn't have secure lock screen
+     * because device with secure lock screen MUST report android.software.device_admin .
+     *
+     * https://source.android.com/compatibility/7.0/android-7.0-cdd.html#3_9_device_administration
+     *
+     */
+    private boolean hasSecureLockScreen() {
+        PackageManager pm = getContext().getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
+    }
 }
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 72bdb3a..37ea62c 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -87,12 +87,12 @@
 
     @SecurityTest
     public void testStagefright_cve_2017_0643() throws Exception {
-        doStagefrightTest(R.raw.cve_2017_0643);
+        doStagefrightTest(R.raw.cve_2017_0643, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
     public void testStagefright_cve_2017_0728() throws Exception {
-        doStagefrightTest(R.raw.cve_2017_0728);
+        doStagefrightTest(R.raw.cve_2017_0728, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
@@ -135,7 +135,7 @@
     }
 
     public void testStagefright_bug_35763994() throws Exception {
-        doStagefrightTest(R.raw.bug_35763994);
+        doStagefrightTest(R.raw.bug_35763994, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
@@ -145,7 +145,7 @@
 
     @SecurityTest
     public void testStagefright_cve_2016_2507() throws Exception {
-        doStagefrightTest(R.raw.cve_2016_2507);
+        doStagefrightTest(R.raw.cve_2016_2507, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
@@ -235,13 +235,14 @@
 
     @SecurityTest
     public void testStagefright_cve_2016_2429_b_27211885() throws Exception {
-        doStagefrightTest(R.raw.cve_2016_2429_b_27211885);
+        doStagefrightTest(R.raw.cve_2016_2429_b_27211885,
+                new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
     public void testStagefright_bug_34031018() throws Exception {
-        doStagefrightTest(R.raw.bug_34031018_32bit);
-        doStagefrightTest(R.raw.bug_34031018_64bit);
+        doStagefrightTest(R.raw.bug_34031018_32bit, new CrashUtils.Config().checkMinAddress(false));
+        doStagefrightTest(R.raw.bug_34031018_64bit, new CrashUtils.Config().checkMinAddress(false));
     }
 
     /***********************************************************
@@ -261,7 +262,8 @@
 
     @SecurityTest
     public void testStagefright_cve_2017_0852_b_62815506() throws Exception {
-        doStagefrightTest(R.raw.cve_2017_0852_b_62815506);
+        doStagefrightTest(R.raw.cve_2017_0852_b_62815506,
+                new CrashUtils.Config().checkMinAddress(false));
     }
 
     /***********************************************************
@@ -296,12 +298,12 @@
 
     @SecurityTest
     public void testStagefright_cve_2017_0600() throws Exception {
-        doStagefrightTest(R.raw.cve_2017_0600);
+        doStagefrightTest(R.raw.cve_2017_0600, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
     public void testStagefright_cve_2017_0599() throws Exception {
-        doStagefrightTest(R.raw.cve_2017_0599);
+        doStagefrightTest(R.raw.cve_2017_0599, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
@@ -311,7 +313,7 @@
 
     @SecurityTest
     public void testStagefright_cve_2016_6712() throws Exception {
-        doStagefrightTest(R.raw.cve_2016_6712);
+        doStagefrightTest(R.raw.cve_2016_6712, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
@@ -321,12 +323,12 @@
 
     @SecurityTest
     public void testStagefright_bug_33818508() throws Exception {
-        doStagefrightTest(R.raw.bug_33818508);
+        doStagefrightTest(R.raw.bug_33818508, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
     public void testStagefright_bug_32873375() throws Exception {
-        doStagefrightTest(R.raw.bug_32873375);
+        doStagefrightTest(R.raw.bug_32873375, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
@@ -351,7 +353,7 @@
 
     @SecurityTest
     public void testStagefright_bug_32322258() throws Exception {
-        doStagefrightTest(R.raw.bug_32322258);
+        doStagefrightTest(R.raw.bug_32322258, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
@@ -366,7 +368,8 @@
 
     @SecurityTest
     public void testStagefright_cve_2015_3862_b_22954006() throws Exception {
-        doStagefrightTest(R.raw.cve_2015_3862_b_22954006);
+        doStagefrightTest(R.raw.cve_2015_3862_b_22954006,
+                new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
@@ -420,12 +423,13 @@
 
     @SecurityTest
     public void testStagefright_cve_2016_3755() throws Exception {
-        doStagefrightTest(R.raw.cve_2016_3755);
+        doStagefrightTest(R.raw.cve_2016_3755, new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
     public void testStagefright_cve_2016_3878_b_29493002() throws Exception {
-        doStagefrightTest(R.raw.cve_2016_3878_b_29493002);
+        doStagefrightTest(R.raw.cve_2016_3878_b_29493002,
+                new CrashUtils.Config().checkMinAddress(false));
     }
 
     @SecurityTest
@@ -435,11 +439,11 @@
 
     @SecurityTest
     public void testStagefright_bug_27855419_CVE_2016_2463() throws Exception {
-        doStagefrightTest(R.raw.bug_27855419);
+        doStagefrightTest(R.raw.bug_27855419, new CrashUtils.Config().checkMinAddress(false));
     }
 
     public void testStagefright_bug_19779574() throws Exception {
-        doStagefrightTest(R.raw.bug_19779574);
+        doStagefrightTest(R.raw.bug_19779574, new CrashUtils.Config().checkMinAddress(false));
     }
 
     /***********************************************************
@@ -449,7 +453,7 @@
 
     @SecurityTest
     public void testStagefright_bug_35467107() throws Exception {
-        doStagefrightTest(R.raw.bug_35467107);
+        doStagefrightTest(R.raw.bug_35467107, new CrashUtils.Config().checkMinAddress(false));
     }
 
     /***********************************************************
@@ -468,27 +472,37 @@
     }
 
     private void doStagefrightTest(final int rid) throws Exception {
-        doStagefrightTestMediaPlayer(rid);
-        doStagefrightTestMediaCodec(rid);
-        doStagefrightTestMediaMetadataRetriever(rid);
+        doStagefrightTest(rid, null);
+    }
+
+    private void doStagefrightTest(final int rid, CrashUtils.Config config) throws Exception {
+        doStagefrightTestMediaPlayer(rid, config);
+        doStagefrightTestMediaCodec(rid, config);
+        doStagefrightTestMediaMetadataRetriever(rid, config);
 
         Context context = getInstrumentation().getContext();
         Resources resources =  context.getResources();
         CtsTestServer server = new CtsTestServer(context);
         String rname = resources.getResourceEntryName(rid);
         String url = server.getAssetUrl("raw/" + rname);
-        doStagefrightTestMediaPlayer(url);
-        doStagefrightTestMediaCodec(url);
-        doStagefrightTestMediaMetadataRetriever(url);
+
+        doStagefrightTestMediaPlayer(url, config);
+        doStagefrightTestMediaCodec(url, config);
+        doStagefrightTestMediaMetadataRetriever(url, config);
         server.shutdown();
     }
 
     private void doStagefrightTest(final int rid, int timeout) throws Exception {
+        doStagefrightTest(rid, null, timeout);
+    }
+
+    private void doStagefrightTest(
+            final int rid, CrashUtils.Config config, int timeout) throws Exception {
         runWithTimeout(new Runnable() {
             @Override
             public void run() {
                 try {
-                  doStagefrightTest(rid);
+                  doStagefrightTest(rid, config);
                 } catch (Exception e) {
                   fail(e.toString());
                 }
@@ -497,7 +511,12 @@
     }
 
     private void doStagefrightTestANR(final int rid) throws Exception {
-        doStagefrightTestMediaPlayerANR(rid, null);
+        doStagefrightTestANR(rid, null);
+    }
+
+    private void doStagefrightTestANR(
+            final int rid, CrashUtils.Config config) throws Exception {
+        doStagefrightTestMediaPlayerANR(rid, null, config);
     }
 
     private Surface getDummySurface() {
@@ -557,14 +576,18 @@
         MediaPlayer.OnPreparedListener,
         MediaPlayer.OnCompletionListener {
 
+        CrashUtils.Config config;
+
         private final Pattern[] validProcessPatterns = {
             Pattern.compile("adsprpcd"),
             Pattern.compile("android\\.hardware\\.cas@\\d+?\\.\\d+?-service"),
             Pattern.compile("android\\.hardware\\.drm@\\d+?\\.\\d+?-service"),
             Pattern.compile("android\\.hardware\\.drm@\\d+?\\.\\d+?-service\\.clearkey"),
             Pattern.compile("android\\.hardware\\.drm@\\d+?\\.\\d+?-service\\.widevine"),
+            Pattern.compile("omx@\\d+?\\.\\d+?-service"),  // name:omx@1.0-service
             Pattern.compile("android\\.process\\.media"),
             Pattern.compile("mediadrmserver"),
+            Pattern.compile("mediaextractor"),
             Pattern.compile("media\\.extractor"),
             Pattern.compile("media\\.metrics"),
             Pattern.compile("mediaserver"),
@@ -576,6 +599,19 @@
             Pattern.compile("vendor.*"),
         };
 
+        MediaPlayerCrashListener() {
+            this(null);
+        }
+
+        MediaPlayerCrashListener(CrashUtils.Config config) {
+            if (config == null) {
+                config = new CrashUtils.Config();
+            }
+            // if a different process is needed for a test, it should be added to the main list.
+            config.setProcessPatterns(validProcessPatterns);
+            this.config = config;
+        }
+
         @Override
         public boolean onError(MediaPlayer mp, int newWhat, int extra) {
             Log.i(TAG, "error: " + newWhat + "/" + extra);
@@ -621,7 +657,7 @@
                 if (crashes == null) {
                     Log.e(TAG, "Crash results not found for test " + getName());
                     return what;
-                } else if (CrashUtils.securityCrashDetected(crashes, true, validProcessPatterns)) {
+                } else if (CrashUtils.securityCrashDetected(crashes, config)) {
                     return what;
                 } else {
                     Log.i(TAG, "Crash ignored due to no security crash found for test " +
@@ -669,11 +705,21 @@
     }
 
     private void doStagefrightTestMediaPlayer(final int rid) throws Exception {
-        doStagefrightTestMediaPlayer(rid, null);
+        doStagefrightTestMediaPlayer(rid, null, null);
+    }
+
+    private void doStagefrightTestMediaPlayer(
+            final int rid, CrashUtils.Config config) throws Exception {
+        doStagefrightTestMediaPlayer(rid, null, config);
     }
 
     private void doStagefrightTestMediaPlayer(final String url) throws Exception {
-        doStagefrightTestMediaPlayer(-1, url);
+        doStagefrightTestMediaPlayer(url, null);
+    }
+
+    private void doStagefrightTestMediaPlayer(
+            final String url, CrashUtils.Config config) throws Exception {
+        doStagefrightTestMediaPlayer(-1, url, config);
     }
 
     private void closeQuietly(AutoCloseable closeable) {
@@ -688,12 +734,17 @@
     }
 
     private void doStagefrightTestMediaPlayer(final int rid, final String uri) throws Exception {
+        doStagefrightTestMediaPlayer(rid, uri, null);
+    }
+
+    private void doStagefrightTestMediaPlayer(final int rid, final String uri,
+            CrashUtils.Config config) throws Exception {
 
         String name = uri != null ? uri :
             getInstrumentation().getContext().getResources().getResourceEntryName(rid);
         Log.i(TAG, "start mediaplayer test for: " + name);
 
-        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(config);
 
         LooperThread t = new LooperThread(new Runnable() {
             @Override
@@ -738,16 +789,31 @@
     }
 
     private void doStagefrightTestMediaCodec(final int rid) throws Exception {
-        doStagefrightTestMediaCodec(rid, null);
+        doStagefrightTestMediaCodec(rid, null, null);
+    }
+
+    private void doStagefrightTestMediaCodec(
+            final int rid, CrashUtils.Config config) throws Exception {
+        doStagefrightTestMediaCodec(rid, null, config);
     }
 
     private void doStagefrightTestMediaCodec(final String url) throws Exception {
-        doStagefrightTestMediaCodec(-1, url);
+        doStagefrightTestMediaCodec(url, null);
+    }
+
+    private void doStagefrightTestMediaCodec(
+            final String url, CrashUtils.Config config) throws Exception {
+        doStagefrightTestMediaCodec(-1, url, config);
     }
 
     private void doStagefrightTestMediaCodec(final int rid, final String url) throws Exception {
+        doStagefrightTestMediaCodec(rid, url, null);
+    }
 
-        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+    private void doStagefrightTestMediaCodec(
+            final int rid, final String url, CrashUtils.Config config) throws Exception {
+
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(config);
 
         LooperThread thr = new LooperThread(new Runnable() {
             @Override
@@ -903,17 +969,31 @@
     }
 
     private void doStagefrightTestMediaMetadataRetriever(final int rid) throws Exception {
-        doStagefrightTestMediaMetadataRetriever(rid, null);
+        doStagefrightTestMediaMetadataRetriever(rid, null, null);
+    }
+    private void doStagefrightTestMediaMetadataRetriever(
+            final int rid, CrashUtils.Config config) throws Exception {
+        doStagefrightTestMediaMetadataRetriever(rid, null, config);
     }
 
     private void doStagefrightTestMediaMetadataRetriever(final String url) throws Exception {
-        doStagefrightTestMediaMetadataRetriever(-1, url);
+        doStagefrightTestMediaMetadataRetriever(url, null);
+    }
+
+    private void doStagefrightTestMediaMetadataRetriever(
+            final String url, CrashUtils.Config config) throws Exception {
+        doStagefrightTestMediaMetadataRetriever(-1, url, config);
     }
 
     private void doStagefrightTestMediaMetadataRetriever(
             final int rid, final String url) throws Exception {
+        doStagefrightTestMediaMetadataRetriever(rid, url, null);
+    }
 
-        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+    private void doStagefrightTestMediaMetadataRetriever(
+            final int rid, final String url, CrashUtils.Config config) throws Exception {
+
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(config);
 
         LooperThread thr = new LooperThread(new Runnable() {
             @Override
@@ -986,11 +1066,13 @@
     }
 
     public void testBug36816007() throws Exception {
-        doStagefrightTestRawBlob(R.raw.bug_36816007, "video/avc", 320, 240);
+        doStagefrightTestRawBlob(R.raw.bug_36816007, "video/avc", 320, 240,
+                new CrashUtils.Config().checkMinAddress(false));
     }
 
     public void testBug36895511() throws Exception {
-        doStagefrightTestRawBlob(R.raw.bug_36895511, "video/hevc", 320, 240);
+        doStagefrightTestRawBlob(R.raw.bug_36895511, "video/hevc", 320, 240,
+                new CrashUtils.Config().checkMinAddress(false));
     }
 
     public void testBug64836894() throws Exception {
@@ -1014,7 +1096,8 @@
 
     @SecurityTest
     public void testBug_70897394() throws Exception {
-        doStagefrightTestRawBlob(R.raw.bug_70897394_avc, "video/avc", 320, 240);
+        doStagefrightTestRawBlob(R.raw.bug_70897394_avc, "video/avc", 320, 240,
+                new CrashUtils.Config().checkMinAddress(false));
     }
 
     private void runWithTimeout(Runnable runner, int timeout) {
@@ -1039,9 +1122,15 @@
         }, 5000);
     }
 
-    private void doStagefrightTestRawBlob(int rid, String mime, int initWidth, int initHeight) throws Exception {
+    private void doStagefrightTestRawBlob(
+            int rid, String mime, int initWidth, int initHeight) throws Exception {
+        doStagefrightTestRawBlob(rid, mime, initWidth, initHeight, new CrashUtils.Config());
+    }
 
-        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+    private void doStagefrightTestRawBlob(int rid, String mime, int initWidth, int initHeight,
+            CrashUtils.Config config) throws Exception {
+
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(config);
         final Context context = getInstrumentation().getContext();
         final Resources resources =  context.getResources();
 
@@ -1154,11 +1243,16 @@
     }
 
     private void doStagefrightTestMediaPlayerANR(final int rid, final String uri) throws Exception {
+        doStagefrightTestMediaPlayerANR(rid, uri, null);
+    }
+
+    private void doStagefrightTestMediaPlayerANR(final int rid, final String uri,
+            CrashUtils.Config config) throws Exception {
         String name = uri != null ? uri :
             getInstrumentation().getContext().getResources().getResourceEntryName(rid);
         Log.i(TAG, "start mediaplayerANR test for: " + name);
 
-        final MediaPlayerCrashListener mpl = new MediaPlayerCrashListener();
+        final MediaPlayerCrashListener mpl = new MediaPlayerCrashListener(config);
 
         LooperThread t = new LooperThread(new Runnable() {
             @Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index 523b90d..d5068e0 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -781,7 +781,9 @@
         public void onPageFinished(WebView view, String url) {
             super.onPageFinished(view, url);
             assertTrue(mOnPageStartedCalled);
-            assertTrue(mOnLoadResourceCalled);
+            assertTrue(
+                    "Expected onLoadResource or onReceivedError to be called before onPageFinished",
+                    mOnLoadResourceCalled || mOnReceivedResourceError != null);
             mOnPageFinishedCalled = true;
         }
 
diff --git a/tools/cts-tradefed/Android.mk b/tools/cts-tradefed/Android.mk
index b731985..f868d62 100644
--- a/tools/cts-tradefed/Android.mk
+++ b/tools/cts-tradefed/Android.mk
@@ -29,7 +29,7 @@
 LOCAL_SUITE_TARGET_ARCH := $(TARGET_ARCH)
 LOCAL_SUITE_NAME := CTS
 LOCAL_SUITE_FULLNAME := "Compatibility Test Suite"
-LOCAL_SUITE_VERSION := 8.1_r19
+LOCAL_SUITE_VERSION := 8.1_r20
 LOCAL_STATIC_JAVA_LIBRARIES += cts-tradefed-harness
 
 LOCAL_MODULE := cts-tradefed