am 6eb3b8d3: Merge "Upgrade the app to better follow holo guidelines"

* commit '6eb3b8d3b7ffc1d80ae7734042e2c4d36a77a19f':
  Upgrade the app to better follow holo guidelines
diff --git a/src/com/android/bluetooth/btservice/AdapterProperties.java b/src/com/android/bluetooth/btservice/AdapterProperties.java
index 73e795e..9b3c20a 100755
--- a/src/com/android/bluetooth/btservice/AdapterProperties.java
+++ b/src/com/android/bluetooth/btservice/AdapterProperties.java
@@ -445,7 +445,8 @@
                         intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
                         intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, mName);
                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-                        mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);
+                        mService.sendBroadcastAsUser(intent, UserHandle.ALL,
+                                 mService.BLUETOOTH_PERM);
                         debugLog("Name is: " + mName);
                         break;
                     case AbstractionLayer.BT_PROPERTY_BDADDR:
@@ -546,7 +547,7 @@
     }
 
     private void infoLog(String msg) {
-        Log.i(TAG, msg);
+        if (DBG) Log.i(TAG, msg);
     }
 
     private void debugLog(String msg) {
diff --git a/src/com/android/bluetooth/btservice/ProfileService.java b/src/com/android/bluetooth/btservice/ProfileService.java
index 8339418..e3d9196 100644
--- a/src/com/android/bluetooth/btservice/ProfileService.java
+++ b/src/com/android/bluetooth/btservice/ProfileService.java
@@ -77,7 +77,7 @@
                     refCount = refCount+1;
                 }
                 sReferenceCount.put(mName, refCount);
-                log("REFCOUNT: CREATED. INSTANCE_COUNT=" +refCount);
+                if (DBG) log("REFCOUNT: CREATED. INSTANCE_COUNT=" +refCount);
             }
         }
     }
@@ -99,14 +99,14 @@
 
     @Override
     public void onCreate() {
-        log("onCreate");
+        if (DBG) log("onCreate");
         super.onCreate();
         mAdapter = BluetoothAdapter.getDefaultAdapter();
         mBinder = initBinder();
     }
 
     public int onStartCommand(Intent intent, int flags, int startId) {
-        log("onStartCommand()");
+        if (DBG) log("onStartCommand()");
         if (mStartError || mAdapter == null) {
             Log.w(mName, "Stopping profile service: device does not have BT");
             doStop(intent);
@@ -138,22 +138,22 @@
     }
 
     public IBinder onBind(Intent intent) {
-        log("onBind");
+        if (DBG) log("onBind");
         return mBinder;
     }
 
     public boolean onUnbind(Intent intent) {
-        log("onUnbind");
+        if (DBG) log("onUnbind");
         return super.onUnbind(intent);
     }
 
     @Override
     public void onDestroy() {
-        log("Destroying service.");
+        if (DBG) log("Destroying service.");
         if (mCleaningUp) {
-            log("Cleanup already started... Skipping cleanup()...");
+            if (DBG) log("Cleanup already started... Skipping cleanup()...");
         } else {
-            log("cleanup()");
+            if (DBG) log("cleanup()");
             mCleaningUp = true;
             cleanup();
             if (mBinder != null) {
@@ -170,7 +170,7 @@
         if (mAdapter == null) {
             Log.e(mName, "Error starting profile. BluetoothAdapter is null");
         } else {
-            log("start()");
+            if (DBG) log("start()");
             mStartError = !start();
             if (!mStartError) {
                 notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON);
@@ -182,7 +182,7 @@
 
     private void doStop(Intent intent) {
         if (stop()) {
-            log("stop()");
+            if (DBG) log("stop()");
             notifyProfileServiceStateChanged(BluetoothAdapter.STATE_OFF);
             stopSelf();
         } else {
diff --git a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
index 2d11501..d9b2b7d 100755
--- a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
+++ b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
@@ -33,6 +33,7 @@
 package com.android.bluetooth.hfp;
 
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothAssignedNumbers;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothProfile;
@@ -1267,6 +1268,30 @@
         log("Audio state " + device + ": " + prevState + "->" + newState);
     }
 
+    /*
+     * Put the AT command, company ID, arguments, and device in an Intent and broadcast it.
+     */
+    private void broadcastVendorSpecificEventIntent(String command,
+                                                    int companyId,
+                                                    int commandType,
+                                                    Object[] arguments,
+                                                    BluetoothDevice device) {
+        log("broadcastVendorSpecificEventIntent(" + command + ")");
+        Intent intent =
+                new Intent(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
+        intent.putExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD, command);
+        intent.putExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE,
+                        commandType);
+        // assert: all elements of args are Serializable
+        intent.putExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS, arguments);
+        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+
+        intent.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY
+            + "." + Integer.toString(companyId));
+
+        mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
+    }
+
     private void configAudioParameters()
     {
         // Reset NREC on connect event. Headset will override later
@@ -1645,6 +1670,66 @@
         }
     }
 
+    /**
+     * Find a character ch, ignoring quoted sections.
+     * Return input.length() if not found.
+     */
+    static private int findChar(char ch, String input, int fromIndex) {
+        for (int i = fromIndex; i < input.length(); i++) {
+            char c = input.charAt(i);
+            if (c == '"') {
+                i = input.indexOf('"', i + 1);
+                if (i == -1) {
+                    return input.length();
+                }
+            } else if (c == ch) {
+                return i;
+            }
+        }
+        return input.length();
+    }
+
+    /**
+     * Break an argument string into individual arguments (comma delimited).
+     * Integer arguments are turned into Integer objects. Otherwise a String
+     * object is used.
+     */
+    static private Object[] generateArgs(String input) {
+        int i = 0;
+        int j;
+        ArrayList<Object> out = new ArrayList<Object>();
+        while (i <= input.length()) {
+            j = findChar(',', input, i);
+
+            String arg = input.substring(i, j);
+            try {
+                out.add(new Integer(arg));
+            } catch (NumberFormatException e) {
+                out.add(arg);
+            }
+
+            i = j + 1; // move past comma
+        }
+        return out.toArray();
+    }
+
+    private void processAtXevent(String atString) {
+        log("processAtXevent - atString = "+ atString);
+        if (atString.startsWith("=") && !atString.startsWith("=?")) {
+            Object[] args = generateArgs(atString.substring(1));
+            broadcastVendorSpecificEventIntent("+XEVENT",
+                                               BluetoothAssignedNumbers.PLANTRONICS,
+                                               BluetoothHeadset.AT_CMD_TYPE_SET,
+                                               args,
+                                               mCurrentDevice);
+            atResponseCodeNative(HeadsetHalConstants.AT_RESPONSE_OK, 0);
+        }
+        else {
+            Log.e(TAG, "processAtXevent: command type error");
+            atResponseCodeNative(HeadsetHalConstants.AT_RESPONSE_ERROR, 0);
+        }
+    }
+
     private void processUnknownAt(String atString) {
         // TODO (BT)
         log("processUnknownAt - atString = "+ atString);
@@ -1656,6 +1741,8 @@
             processAtCpbs(atCommand.substring(5), commandType);
         else if (atCommand.startsWith("+CPBR"))
             processAtCpbr(atCommand.substring(5), commandType, mCurrentDevice);
+        else if (atCommand.startsWith("+XEVENT"))
+            processAtXevent(atCommand.substring(7));
         else
             atResponseCodeNative(HeadsetHalConstants.AT_RESPONSE_ERROR, 0);
     }
diff --git a/src/com/android/bluetooth/hid/HidService.java b/src/com/android/bluetooth/hid/HidService.java
index 2e67154..8f2051f 100755
--- a/src/com/android/bluetooth/hid/HidService.java
+++ b/src/com/android/bluetooth/hid/HidService.java
@@ -179,7 +179,7 @@
                     if(halState == CONN_STATE_CONNECTED &&
                        prevState == BluetoothInputDevice.STATE_DISCONNECTED &&
                        (!okToConnect(device))) {
-                        Log.d(TAG,"Incoming HID connection rejected");
+                        if (DBG) Log.d(TAG,"Incoming HID connection rejected");
                         disconnectHidNative(Utils.getByteAddress(device));
                     } else {
                         broadcastConnectionState(device, convertHalState(halState));
diff --git a/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java b/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
index f9e96f5..bbe7899 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
@@ -69,6 +69,17 @@
         String action = intent.getAction();
 
         if (action.equals(Intent.ACTION_SEND) || action.equals(Intent.ACTION_SEND_MULTIPLE)) {
+            //Check if Bluetooth is available in the beginning instead of at the end
+            if (!isBluetoothAllowed()) {
+                Intent in = new Intent(this, BluetoothOppBtErrorActivity.class);
+                in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                in.putExtra("title", this.getString(R.string.airplane_error_title));
+                in.putExtra("content", this.getString(R.string.airplane_error_msg));
+                startActivity(in);
+                finish();
+                return;
+            }
+
             /*
              * Other application is trying to share a file via Bluetooth,
              * probably Pictures, videos, or vCards. The Intent should contain
@@ -76,8 +87,8 @@
              */
             if (action.equals(Intent.ACTION_SEND)) {
                 // TODO: handle type == null case
-                String type = intent.getType();
-                Uri stream = (Uri)intent.getParcelableExtra(Intent.EXTRA_STREAM);
+                final String type = intent.getType();
+                final Uri stream = (Uri)intent.getParcelableExtra(Intent.EXTRA_STREAM);
                 CharSequence extra_text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT);
                 // If we get ACTION_SEND intent with EXTRA_STREAM, we'll use the
                 // uri data;
@@ -89,16 +100,38 @@
                                 + type);
                     // Save type/stream, will be used when adding transfer
                     // session to DB.
-                    BluetoothOppManager.getInstance(this).saveSendingFileInfo(type,
-                            stream.toString(), false);
+                    Thread t = new Thread(new Runnable() {
+                        public void run() {
+                            BluetoothOppManager.getInstance(BluetoothOppLauncherActivity.this)
+                                .saveSendingFileInfo(type,stream.toString(), false);
+                            //Done getting file info..Launch device picker and finish this activity
+                            launchDevicePicker();
+                            finish();
+                        }
+                    });
+                    t.start();
+                    return;
                 } else if (extra_text != null && type != null) {
                     if (V) Log.v(TAG, "Get ACTION_SEND intent with Extra_text = "
                                 + extra_text.toString() + "; mimetype = " + type);
-                    Uri fileUri = creatFileForSharedContent(this, extra_text);
-
+                    final Uri fileUri = creatFileForSharedContent(this, extra_text);
                     if (fileUri != null) {
-                        BluetoothOppManager.getInstance(this).saveSendingFileInfo(type,
-                                fileUri.toString(), false);
+                        Thread t = new Thread(new Runnable() {
+                            public void run() {
+                                BluetoothOppManager.getInstance(BluetoothOppLauncherActivity.this)
+                                    .saveSendingFileInfo(type,fileUri.toString(), false);
+                                //Done getting file info..Launch device picker
+                                //and finish this activity
+                                launchDevicePicker();
+                                finish();
+                            }
+                        });
+                        t.start();
+                        return;
+                    } else {
+                        Log.w(TAG,"Error trying to do set text...File not created!");
+                        finish();
+                        return;
                     }
                 } else {
                     Log.e(TAG, "type is null; or sending file URI is null");
@@ -106,54 +139,29 @@
                     return;
                 }
             } else if (action.equals(Intent.ACTION_SEND_MULTIPLE)) {
-                ArrayList<Uri> uris = new ArrayList<Uri>();
-                String mimeType = intent.getType();
-                uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
+                final String mimeType = intent.getType();
+                final ArrayList<Uri> uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
                 if (mimeType != null && uris != null) {
                     if (V) Log.v(TAG, "Get ACTION_SHARE_MULTIPLE intent: uris " + uris + "\n Type= "
                                 + mimeType);
-                    BluetoothOppManager.getInstance(this).saveSendingFileInfo(mimeType,
-                            uris, false);
+                    Thread t = new Thread(new Runnable() {
+                        public void run() {
+                            BluetoothOppManager.getInstance(BluetoothOppLauncherActivity.this)
+                                .saveSendingFileInfo(mimeType,uris, false);
+                            //Done getting file info..Launch device picker
+                            //and finish this activity
+                            launchDevicePicker();
+                            finish();
+                        }
+                    });
+                    t.start();
+                    return;
                 } else {
                     Log.e(TAG, "type is null; or sending files URIs are null");
                     finish();
                     return;
                 }
             }
-
-            if (!isBluetoothAllowed()) {
-                Intent in = new Intent(this, BluetoothOppBtErrorActivity.class);
-                in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                in.putExtra("title", this.getString(R.string.airplane_error_title));
-                in.putExtra("content", this.getString(R.string.airplane_error_msg));
-                this.startActivity(in);
-
-                finish();
-                return;
-            }
-
-            // TODO: In the future, we may send intent to DevicePickerActivity
-            // directly,
-            // and let DevicePickerActivity to handle Bluetooth Enable.
-            if (!BluetoothOppManager.getInstance(this).isEnabled()) {
-                if (V) Log.v(TAG, "Prepare Enable BT!! ");
-                Intent in = new Intent(this, BluetoothOppBtEnableActivity.class);
-                in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                this.startActivity(in);
-            } else {
-                if (V) Log.v(TAG, "BT already enabled!! ");
-                Intent in1 = new Intent(BluetoothDevicePicker.ACTION_LAUNCH);
-                in1.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-                in1.putExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
-                in1.putExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE,
-                        BluetoothDevicePicker.FILTER_TYPE_TRANSFER);
-                in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE,
-                        Constants.THIS_PACKAGE_NAME);
-                in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS,
-                        BluetoothOppReceiver.class.getName());
-                if (V) {Log.d(TAG,"Launching " +BluetoothDevicePicker.ACTION_LAUNCH );}
-                this.startActivity(in1);
-            }
         } else if (action.equals(Constants.ACTION_OPEN)) {
             Uri uri = getIntent().getData();
             if (V) Log.v(TAG, "Get ACTION_OPEN intent: Uri = " + uri);
@@ -163,10 +171,41 @@
             intent1.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName());
             intent1.setData(uri);
             this.sendBroadcast(intent1);
+            finish();
+        } else {
+            Log.w(TAG, "Unsupported action: " + action);
+            finish();
         }
-        finish();
     }
 
+    /**
+     * Turns on Bluetooth if not already on, or launches device picker if Bluetooth is on
+     * @return
+     */
+    private final void launchDevicePicker() {
+        // TODO: In the future, we may send intent to DevicePickerActivity
+        // directly,
+        // and let DevicePickerActivity to handle Bluetooth Enable.
+        if (!BluetoothOppManager.getInstance(this).isEnabled()) {
+            if (V) Log.v(TAG, "Prepare Enable BT!! ");
+            Intent in = new Intent(this, BluetoothOppBtEnableActivity.class);
+            in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            startActivity(in);
+        } else {
+            if (V) Log.v(TAG, "BT already enabled!! ");
+            Intent in1 = new Intent(BluetoothDevicePicker.ACTION_LAUNCH);
+            in1.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            in1.putExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
+            in1.putExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE,
+                    BluetoothDevicePicker.FILTER_TYPE_TRANSFER);
+            in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE,
+                    Constants.THIS_PACKAGE_NAME);
+            in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS,
+                    BluetoothOppReceiver.class.getName());
+            if (V) {Log.d(TAG,"Launching " +BluetoothDevicePicker.ACTION_LAUNCH );}
+            startActivity(in1);
+        }
+    }
     /* Returns true if Bluetooth is allowed given current airplane mode settings. */
     private final boolean isBluetoothAllowed() {
         final ContentResolver resolver = this.getContentResolver();
diff --git a/src/com/android/bluetooth/opp/BluetoothOppService.java b/src/com/android/bluetooth/opp/BluetoothOppService.java
index 9020006..421ad2e 100755
--- a/src/com/android/bluetooth/opp/BluetoothOppService.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppService.java
@@ -680,7 +680,7 @@
             info.mUri = Uri.parse(stringFromCursor(info.mUri.toString(), cursor,
                     BluetoothShare.URI));
         } else {
-            Log.d(TAG, "updateShare() called for ID " + info.mId + " with null URI");
+            Log.w(TAG, "updateShare() called for ID " + info.mId + " with null URI");
         }
         info.mHint = stringFromCursor(info.mHint, cursor, BluetoothShare.FILENAME_HINT);
         info.mFilename = stringFromCursor(info.mFilename, cursor, BluetoothShare._DATA);