merge in gingerbread-release history after reset to gingerbread
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 93b5078..08bd98b 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -75,6 +75,8 @@
     <string name="bt_sent_messages">Sent Messages</string>
     <string name="bt_no_messages">No messages</string>
     <string name="bt_make_discoverable">Make Discoverable</string>
+    <string name="bt_insecure_pairing_error_title">Pairing dialog shown?</string>
+    <string name="bt_insecure_pairing_error_message">Insecure connections should not show the pairing dialog!</string>
 
     <string name="bt_secure_client">Secure Client</string>
     <string name="bt_insecure_client">Insecure Client</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java
index a6f9919..b617fc2 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java
@@ -254,6 +254,7 @@
         if (data != null) {
             TestResult result = TestResult.fromActivityResult(resultCode, data);
             TestListItem test = secure ? mSecureClientTest : mInsecureClientTest;
+            test.setResult(result.getResult());
             updateTest(test);
         }
     }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/MessageTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/MessageTestActivity.java
index aabe00c..1d6706d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/MessageTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/MessageTestActivity.java
@@ -18,11 +18,16 @@
 
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
+import com.android.cts.verifier.TestResult;
 
 import android.app.AlertDialog;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -43,12 +48,17 @@
     static final String EXTRA_DEVICE_ADDRESS = "deviceAddress";
     static final String EXTRA_SECURE = "secure";
 
+    /** Broadcast action that should only be fired when pairing for a secure connection. */
+    private static final String ACTION_PAIRING_REQUEST =
+            "android.bluetooth.device.action.PAIRING_REQUEST";
+
     private static final int ENABLE_BLUETOOTH_REQUEST = 1;
 
     private static final String MESSAGE_DELIMITER = "\n";
     private static final Pattern MESSAGE_PATTERN = Pattern.compile("Message (\\d+) to .*");
 
     private BluetoothAdapter mBluetoothAdapter;
+    private PairingActionReceiver mPairingActionReceiver;
     private BluetoothChatService mChatService;
 
     private ArrayAdapter<String> mReceivedMessagesAdapter;
@@ -112,6 +122,10 @@
 
         getPassButton().setEnabled(false);
 
+        mPairingActionReceiver = new PairingActionReceiver();
+        IntentFilter intentFilter = new IntentFilter(ACTION_PAIRING_REQUEST);
+        registerReceiver(mPairingActionReceiver, intentFilter);
+
         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
         if (mBluetoothAdapter.isEnabled()) {
             startChatService();
@@ -284,9 +298,41 @@
         Toast.makeText(this, toast, Toast.LENGTH_LONG).show();
     }
 
+    class PairingActionReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (!mSecure && ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
+                runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        showPairingErrorDialog();
+                    }
+                });
+            }
+        }
+    }
+
+    private void showPairingErrorDialog() {
+        new AlertDialog.Builder(MessageTestActivity.this)
+            .setIcon(android.R.drawable.ic_dialog_alert)
+            .setTitle(R.string.bt_insecure_pairing_error_title)
+            .setMessage(R.string.bt_insecure_pairing_error_message)
+            .setPositiveButton(android.R.string.ok,
+                    new DialogInterface.OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    TestResult.setFailedResult(MessageTestActivity.this);
+                    finish();
+                }
+            })
+            .setCancelable(false)
+            .show();
+    }
+
     @Override
     protected void onDestroy() {
         super.onDestroy();
         mChatService.stop();
+        unregisterReceiver(mPairingActionReceiver);
     }
 }
diff --git a/tests/res/raw/sig_media.bin b/tests/res/raw/sig_media.bin
new file mode 100644
index 0000000..a43bc68
--- /dev/null
+++ b/tests/res/raw/sig_media.bin
Binary files differ
diff --git a/tests/res/raw/sig_platform.bin b/tests/res/raw/sig_platform.bin
new file mode 100644
index 0000000..33a683e
--- /dev/null
+++ b/tests/res/raw/sig_platform.bin
Binary files differ
diff --git a/tests/res/raw/sig_shared.bin b/tests/res/raw/sig_shared.bin
new file mode 100644
index 0000000..094b1b9
--- /dev/null
+++ b/tests/res/raw/sig_shared.bin
Binary files differ
diff --git a/tests/res/raw/sig_testkey.bin b/tests/res/raw/sig_testkey.bin
new file mode 100644
index 0000000..e2bef19
--- /dev/null
+++ b/tests/res/raw/sig_testkey.bin
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
new file mode 100644
index 0000000..cff19af
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import com.android.cts.stub.R;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.Signature;
+import android.content.res.Resources.NotFoundException;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class PackageSignatureTest extends AndroidTestCase {
+
+    private static final String TAG = PackageSignatureTest.class.getSimpleName();
+
+    public void testPackageSignatures() throws Exception {
+        Set<String> badPackages = new HashSet<String>();
+        Set<Signature> wellKnownSignatures = getWellKnownSignatures();
+
+        PackageManager packageManager = mContext.getPackageManager();
+        List<PackageInfo> allPackageInfos = packageManager.getInstalledPackages(
+                PackageManager.GET_UNINSTALLED_PACKAGES |
+                PackageManager.GET_SIGNATURES);
+        for (PackageInfo packageInfo : allPackageInfos) {
+            String packageName = packageInfo.packageName;
+            if (packageName != null && !isWhitelistedPackage(packageName)) {
+                for (Signature signature : packageInfo.signatures) {
+                    if (wellKnownSignatures.contains(signature)) {
+                        badPackages.add(packageInfo.packageName);
+                    }
+                }
+            }
+        }
+
+        assertTrue("These packages should not be signed with a well known key: " + badPackages,
+                badPackages.isEmpty());
+    }
+
+    private Set<Signature> getWellKnownSignatures() throws NotFoundException, IOException {
+        Set<Signature> wellKnownSignatures = new HashSet<Signature>();
+        wellKnownSignatures.add(getSignature(R.raw.sig_media));
+        wellKnownSignatures.add(getSignature(R.raw.sig_platform));
+        wellKnownSignatures.add(getSignature(R.raw.sig_shared));
+        wellKnownSignatures.add(getSignature(R.raw.sig_testkey));
+        return wellKnownSignatures;
+    }
+
+    private boolean isWhitelistedPackage(String packageName) {
+        // Don't check the signatures of CTS test packages on the device.
+        // devicesetup is the APK CTS loads to collect information needed in the final report
+        return packageName.startsWith("com.android.cts")
+                || packageName.equalsIgnoreCase("android.tests.devicesetup");
+    }
+
+    private static final int DEFAULT_BUFFER_BYTES = 1024 * 4;
+
+    private Signature getSignature(int resId) throws NotFoundException, IOException {
+        InputStream input = mContext.getResources().openRawResource(resId);
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+
+        try {
+            byte[] buffer = new byte[DEFAULT_BUFFER_BYTES];
+            int numBytes = 0;
+            while ((numBytes = input.read(buffer)) != -1) {
+                output.write(buffer, 0, numBytes);
+            }
+            return new Signature(output.toByteArray());
+        } finally {
+            input.close();
+            output.close();
+        }
+    }
+
+    /**
+     * Writes a package's signature to a file on the device's external storage.
+     * This method was used to generate the well known signatures used by this test.
+     */
+    @SuppressWarnings("unused")
+    private void writeSignature(String packageName, String fileName)
+            throws NameNotFoundException, IOException {
+        PackageManager packageManager = mContext.getPackageManager();
+        PackageInfo packageInfo = packageManager.getPackageInfo(packageName,
+                PackageManager.GET_SIGNATURES);
+        File directory = mContext.getExternalFilesDir(null);
+        int numSignatures = packageInfo.signatures.length;
+        Log.i(TAG, "Will dump " + numSignatures + " signatures to " + directory);
+        for (int i = 0; i < numSignatures; i++) {
+            Signature signature = packageInfo.signatures[i];
+            byte[] signatureBytes = signature.toByteArray();
+            File signatureFile = new File(directory, fileName + "." + i);
+            FileOutputStream output = null;
+            try {
+                output = new FileOutputStream(signatureFile);
+                output.write(signatureBytes);
+            } finally {
+                if (output != null) {
+                    output.close();
+                }
+            }
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/VoldExploitTest.java b/tests/tests/security/src/android/security/cts/VoldExploitTest.java
index df5e58a..38eece7 100644
--- a/tests/tests/security/src/android/security/cts/VoldExploitTest.java
+++ b/tests/tests/security/src/android/security/cts/VoldExploitTest.java
@@ -51,8 +51,8 @@
         devices.addAll(getSysFsPath("/etc/vold.fstab"));
         devices.addAll(getSysFsPath("/system/etc/vold.fstab"));
         if (devices.isEmpty()) {
-          // FIXME: We should be able to detect this security hole
-          // even if there's no vold.fstab entry
+          // This vulnerability is not exploitable if there's
+          // no entry in vold.fstab
           return;
         }
 
diff --git a/tests/tests/text/src/android/text/method/cts/TouchTest.java b/tests/tests/text/src/android/text/method/cts/TouchTest.java
index 6b53f1d..7217db7 100755
--- a/tests/tests/text/src/android/text/method/cts/TouchTest.java
+++ b/tests/tests/text/src/android/text/method/cts/TouchTest.java
@@ -39,7 +39,9 @@
     private Activity mActivity;
     private static final String LONG_TEXT = "Scrolls the specified widget to the specified " +
             "coordinates, except constrains the X scrolling position to the horizontal regions " +
-            "of the text that will be visible after scrolling to the specified Y position.";
+            "of the text that will be visible after scrolling to the specified Y position." +
+            "This is the description of the test.";
+
     private boolean mReturnFromTouchEvent;
 
     public TouchTest() {
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 05ff747..6e0be6c 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -908,14 +908,21 @@
         args = {String.class},
         notes = "Cannot check highlighting"
     )
-    @UiThreadTest
-    public void testFindAll() throws InterruptedException {
-        String p = "<p>Find all instances of find on the page and highlight them.</p>";
+    public void testFindAll() throws Throwable {
+        getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                String p = "<p>Find all instances of find on the page and highlight them.</p>";
 
-        mWebView.loadData("<html><body>" + p + "</body></html>", "text/html", "UTF-8");
+                mWebView.loadData("<html><body>" + p +"</body></html>", "text/html", "UTF-8");
+            }
+        });
         waitForLoadComplete(mWebView, TEST_TIMEOUT);
 
-        assertEquals(2, mWebView.findAll("find"));
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                assertEquals(2, mWebView.findAll("find"));
+            }
+        });
     }
 
     @TestTargets({