Merge "Revert "PBAP server, send favorite contacts"" into qt-qpr1-dev
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 1525a71..a825010 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -26,10 +26,10 @@
     <string name="airplane_error_title" msgid="2683839635115739939">"وضع الطائرة"</string>
     <string name="airplane_error_msg" msgid="8698965595254137230">"لا يمكنك استخدام البلوتوث في وضع الطائرة."</string>
     <string name="bt_enable_title" msgid="8657832550503456572"></string>
-    <string name="bt_enable_line1" msgid="7203551583048149">"لإستخدام خدمات البلوتوث، يجب تشغيل البلوتوث أولاً."</string>
-    <string name="bt_enable_line2" msgid="4341936569415937994">"هل تريد تشغيل البلوتوث الآن؟"</string>
+    <string name="bt_enable_line1" msgid="7203551583048149">"لإستخدام خدمات البلوتوث، يجب تفعيل البلوتوث أولاً."</string>
+    <string name="bt_enable_line2" msgid="4341936569415937994">"هل تريد تفعيل البلوتوث الآن؟"</string>
     <string name="bt_enable_cancel" msgid="1988832367505151727">"إلغاء"</string>
-    <string name="bt_enable_ok" msgid="3432462749994538265">"تشغيل"</string>
+    <string name="bt_enable_ok" msgid="3432462749994538265">"تفعيل"</string>
     <string name="incoming_file_confirm_title" msgid="8139874248612182627">"نقل الملف"</string>
     <string name="incoming_file_confirm_content" msgid="2752605552743148036">"هل تقبل الملف الوارد؟"</string>
     <string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"رفض"</string>
@@ -77,7 +77,7 @@
     <string name="not_exist_file" msgid="3489434189599716133">"ليست هناك أي ملفات"</string>
     <string name="not_exist_file_desc" msgid="4059531573790529229">"الملف غير موجود. \n"</string>
     <string name="enabling_progress_title" msgid="436157952334723406">"يرجى الانتظار…"</string>
-    <string name="enabling_progress_content" msgid="4601542238119927904">"جارٍ تشغيل البلوتوث..."</string>
+    <string name="enabling_progress_content" msgid="4601542238119927904">"جارٍ تفعيل البلوتوث..."</string>
     <string name="bt_toast_1" msgid="972182708034353383">"سيتم استلام الملف. تحقق من التقدم في لوحة الإشعارات."</string>
     <string name="bt_toast_2" msgid="8602553334099066582">"لا يمكن تلقي الملف."</string>
     <string name="bt_toast_3" msgid="6707884165086862518">"تم إيقاف استلام الملف من \"<xliff:g id="SENDER">%1$s</xliff:g>\""</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index a9e448c..7d371e0 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -122,7 +122,7 @@
     <string name="transfer_menu_open" msgid="3368984869083107200">"Abrir"</string>
     <string name="transfer_menu_clear" msgid="5854038118831427492">"Borrar de la lista"</string>
     <string name="transfer_clear_dlg_title" msgid="2953444575556460386">"Borrar"</string>
-    <string name="bluetooth_a2dp_sink_queue_name" msgid="6864149958708669766">"Está Sonando"</string>
+    <string name="bluetooth_a2dp_sink_queue_name" msgid="6864149958708669766">"Reproduciendo"</string>
     <string name="bluetooth_map_settings_save" msgid="7635491847388074606">"Guardar"</string>
     <string name="bluetooth_map_settings_cancel" msgid="9205350798049865699">"Cancelar"</string>
     <string name="bluetooth_map_settings_intro" msgid="6482369468223987562">"Selecciona las cuentas que quieras compartir por Bluetooth. Tendrás que aceptar cualquier acceso a las cuentas al establecer conexión."</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index f4b7e7a..c9b6335 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -122,7 +122,7 @@
     <string name="transfer_menu_open" msgid="3368984869083107200">"បើក"</string>
     <string name="transfer_menu_clear" msgid="5854038118831427492">"សម្អាត​ពី​បញ្ជី"</string>
     <string name="transfer_clear_dlg_title" msgid="2953444575556460386">"សម្អាត"</string>
-    <string name="bluetooth_a2dp_sink_queue_name" msgid="6864149958708669766">"Now Playing"</string>
+    <string name="bluetooth_a2dp_sink_queue_name" msgid="6864149958708669766">"ឥឡូវកំពុងចាក់"</string>
     <string name="bluetooth_map_settings_save" msgid="7635491847388074606">"រក្សាទុក"</string>
     <string name="bluetooth_map_settings_cancel" msgid="9205350798049865699">"បោះបង់"</string>
     <string name="bluetooth_map_settings_intro" msgid="6482369468223987562">"ជ្រើសគណនីដែលអ្នកចង់ចែករំលែកតាមរយៈប៊្លូធូស។ អ្នកនៅតែត្រូវទទួលយកលទ្ធភាពចូលដំណើរការទាំងឡាយទៅកាន់គណនីនេះដដែល នៅពេលភ្ជាប់។"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 0ed4aa9..a0fa232 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -78,7 +78,7 @@
     <string name="not_exist_file_desc" msgid="4059531573790529229">"Мындай файл жок. \n"</string>
     <string name="enabling_progress_title" msgid="436157952334723406">"Күтө туруңуз…"</string>
     <string name="enabling_progress_content" msgid="4601542238119927904">"Bluetooth жандырылууда…"</string>
-    <string name="bt_toast_1" msgid="972182708034353383">"Файл алынат. Эскертмелер тактасынан жүрүшүн байкап турсаңыз болот."</string>
+    <string name="bt_toast_1" msgid="972182708034353383">"Файл алынат. Билдирмелер тактасынан жүрүшүн байкап турсаңыз болот."</string>
     <string name="bt_toast_2" msgid="8602553334099066582">"Файлды алуу мүмкүн эмес."</string>
     <string name="bt_toast_3" msgid="6707884165086862518">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" жөнөткөн файлды алуу токтотулду"</string>
     <string name="bt_toast_4" msgid="4678812947604395649">"Кийинкиге файл жөнөтүлүүдө: \"<xliff:g id="RECIPIENT">%1$s</xliff:g>\""</string>
@@ -125,7 +125,7 @@
     <string name="bluetooth_a2dp_sink_queue_name" msgid="6864149958708669766">"Азыр эмне ойноп жатат?"</string>
     <string name="bluetooth_map_settings_save" msgid="7635491847388074606">"Сактоо"</string>
     <string name="bluetooth_map_settings_cancel" msgid="9205350798049865699">"Жокко чыгаруу"</string>
-    <string name="bluetooth_map_settings_intro" msgid="6482369468223987562">"Bluetooth аркылуу бөлүшө турган каттоо эсептерин тандаңыз. Туташкан сайын каттоо эсептерине кирүү мүмкүнчүлүгүн ырастап турушуңуз керек."</string>
+    <string name="bluetooth_map_settings_intro" msgid="6482369468223987562">"Bluetooth аркылуу бөлүшө турган каттоо эсептерин тандаңыз. Туташкан сайын аккаунттарына кирүү мүмкүнчүлүгүн ырастап турушуңуз керек."</string>
     <string name="bluetooth_map_settings_count" msgid="4557473074937024833">"Калган көзөнөктөр:"</string>
     <string name="bluetooth_map_settings_app_icon" msgid="7105805610929114707">"Колдонмонун сүрөтчөсү"</string>
     <string name="bluetooth_map_settings_title" msgid="7420332483392851321">"Bluetooth билдирүү бөлүшүү жөндөөлөрү"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 08e907f..5198b87 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -20,7 +20,7 @@
     <string name="permdesc_bluetoothShareManager" msgid="8930572979123190223">"BluetoothShare മാനേജർ ആക്‌സസ്സുചെയ്യാനും ഫയലുകൾ കൈമാറാൻ അത് ഉപയോഗിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_bluetoothWhitelist" msgid="7091552898592306386">"വൈറ്റ്‌ലിസ്റ്റ് ബ്ലൂടൂത്ത് ഉപകരണ ആക്‌സസ്സ്."</string>
     <string name="permdesc_bluetoothWhitelist" msgid="5494513855192170109">"ഒരു ബ്ലൂടൂത്ത് ഉപകരണം താൽക്കാലികമായി വൈറ്റ്‌ലിസ്റ്റുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു, അത് ഉപയോക്താവിന്റെ സ്ഥിരീകരണമില്ലാതെ ഈ ഉപകരണത്തിലേക്ക് ഫയലുകൾ അയയ്‌ക്കാൻ ആ ഉപകരണത്തെ അനുവദിക്കുന്നു."</string>
-    <string name="bt_share_picker_label" msgid="6268100924487046932">"ബ്ലൂടൂത്ത്"</string>
+    <string name="bt_share_picker_label" msgid="6268100924487046932">"Bluetooth"</string>
     <string name="unknown_device" msgid="9221903979877041009">"അജ്ഞാത ഉപകരണം"</string>
     <string name="unknownNumber" msgid="4994750948072751566">"അറിയില്ല"</string>
     <string name="airplane_error_title" msgid="2683839635115739939">"ഫ്ലൈറ്റ് മോഡ്"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 4a40dfe..c60c8de 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -128,7 +128,7 @@
     <string name="bluetooth_map_settings_intro" msgid="6482369468223987562">"Chọn tài khoản mà bạn muốn chia sẻ qua Bluetooth. Bạn vẫn phải chấp nhận mọi quyền truy cập vào tài khoản khi kết nối."</string>
     <string name="bluetooth_map_settings_count" msgid="4557473074937024833">"Số khe cắm còn lại:"</string>
     <string name="bluetooth_map_settings_app_icon" msgid="7105805610929114707">"Biểu tượng ứng dụng"</string>
-    <string name="bluetooth_map_settings_title" msgid="7420332483392851321">"Cài đặt chia sẻ thư qua Bluetooth"</string>
+    <string name="bluetooth_map_settings_title" msgid="7420332483392851321">"Cài đặt cách chia sẻ thư qua Bluetooth"</string>
     <string name="bluetooth_map_settings_no_account_slots_left" msgid="1796029082612965251">"Không chọn được tài khoản. Còn lại 0 khe cắm"</string>
     <string name="bluetooth_connected" msgid="6718623220072656906">"Đã kết nối âm thanh Bluetooth"</string>
     <string name="bluetooth_disconnected" msgid="3318303728981478873">"Đã ngắt kết nối âm thanh Bluetooth"</string>
diff --git a/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java b/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java
index 87ccfc8..5aa3cbb 100644
--- a/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java
+++ b/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java
@@ -249,9 +249,6 @@
         if (mAudioFocus != AudioManager.AUDIOFOCUS_GAIN) {
             requestAudioFocus();
         }
-        // On the off change mMediaPlayer errors out and dies, we want to make sure we retry this.
-        // This function immediately exits if we have a MediaPlayer object.
-        requestMediaKeyFocus();
     }
 
     private synchronized int requestAudioFocus() {
@@ -278,8 +275,11 @@
     }
 
     /**
-     * Creates a MediaPlayer that plays a silent audio sample so that MediaSessionService will be
-     * aware of the fact that Bluetooth is playing audio.
+     * Plays a silent audio sample so that MediaSessionService will be aware of the fact that
+     * Bluetooth is playing audio.
+     *
+     * Creates a new MediaPlayer if one does not already exist. Repeat calls to this function are
+     * safe and will result in the silent audio sample again.
      *
      * This allows the MediaSession in AVRCP Controller to be routed media key events, if we've
      * chosen to use it.
@@ -287,25 +287,25 @@
     private synchronized void requestMediaKeyFocus() {
         if (DBG) Log.d(TAG, "requestMediaKeyFocus()");
 
-        if (mMediaPlayer != null) return;
-
-        AudioAttributes attrs = new AudioAttributes.Builder()
-                .setUsage(AudioAttributes.USAGE_MEDIA)
-                .build();
-
-        mMediaPlayer = MediaPlayer.create(mContext, R.raw.silent, attrs,
-                mAudioManager.generateAudioSessionId());
         if (mMediaPlayer == null) {
-            Log.e(TAG, "Failed to initialize media player. You may not get media key events");
-            return;
-        }
+            AudioAttributes attrs = new AudioAttributes.Builder()
+                    .setUsage(AudioAttributes.USAGE_MEDIA)
+                    .build();
 
-        mMediaPlayer.setLooping(false);
-        mMediaPlayer.setOnErrorListener((mp, what, extra) -> {
-            Log.e(TAG, "Silent media player error: " + what + ", " + extra);
-            releaseMediaKeyFocus();
-            return false;
-        });
+            mMediaPlayer = MediaPlayer.create(mContext, R.raw.silent, attrs,
+                    mAudioManager.generateAudioSessionId());
+            if (mMediaPlayer == null) {
+                Log.e(TAG, "Failed to initialize media player. You may not get media key events");
+                return;
+            }
+
+            mMediaPlayer.setLooping(false);
+            mMediaPlayer.setOnErrorListener((mp, what, extra) -> {
+                Log.e(TAG, "Silent media player error: " + what + ", " + extra);
+                releaseMediaKeyFocus();
+                return false;
+            });
+        }
 
         mMediaPlayer.start();
         BluetoothMediaBrowserService.setActive(true);
@@ -314,7 +314,6 @@
     private synchronized void abandonAudioFocus() {
         if (DBG) Log.d(TAG, "abandonAudioFocus()");
         stopFluorideStreaming();
-        releaseMediaKeyFocus();
         mAudioManager.abandonAudioFocus(mAudioFocusListener);
         mAudioFocus = AudioManager.AUDIOFOCUS_NONE;
     }
@@ -337,9 +336,11 @@
     private void startFluorideStreaming() {
         mA2dpSinkService.informAudioFocusStateNative(STATE_FOCUS_GRANTED);
         mA2dpSinkService.informAudioTrackGainNative(1.0f);
+        requestMediaKeyFocus();
     }
 
     private void stopFluorideStreaming() {
+        releaseMediaKeyFocus();
         mA2dpSinkService.informAudioFocusStateNative(STATE_FOCUS_LOST);
     }
 
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
index 693b4a2..56684cd 100644
--- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
+++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
@@ -172,9 +172,11 @@
             }
         }
 
+        // If we don't find a node in the tree then do not have any way to browse for the contents.
+        // Return an empty list instead.
         if (requestedNode == null) {
             if (DBG) Log.d(TAG, "Didn't find a node");
-            return null;
+            return new ArrayList(0);
         } else {
             if (!requestedNode.isCached()) {
                 if (DBG) Log.d(TAG, "node is not cached");
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
index 8704b07..c319364 100644
--- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
+++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
@@ -296,9 +296,9 @@
         @Override
         public void enter() {
             if (mMostRecentState == BluetoothProfile.STATE_CONNECTING) {
+                BluetoothMediaBrowserService.addressedPlayerChanged(mSessionCallbacks);
                 BluetoothMediaBrowserService.notifyChanged(mAddressedPlayer.getPlaybackState());
                 broadcastConnectionStateChanged(BluetoothProfile.STATE_CONNECTED);
-                BluetoothMediaBrowserService.addressedPlayerChanged(mSessionCallbacks);
             } else {
                 logD("ReEnteringConnected");
             }
diff --git a/src/com/android/bluetooth/hfpclient/connserv/HfpClientDeviceBlock.java b/src/com/android/bluetooth/hfpclient/connserv/HfpClientDeviceBlock.java
index 05af73e..b567371 100644
--- a/src/com/android/bluetooth/hfpclient/connserv/HfpClientDeviceBlock.java
+++ b/src/com/android/bluetooth/hfpclient/connserv/HfpClientDeviceBlock.java
@@ -224,7 +224,7 @@
         if (DBG) {
             Log.d(mTAG, "prevConn " + prevConn.isClosing() + " new call " + newCall.getState());
         }
-        if (prevConn.isClosing()
+        if (prevConn.isClosing() && prevConn.getCall().getState() != newCall.getState()
                 && newCall.getState() != BluetoothHeadsetClientCall.CALL_STATE_TERMINATED) {
             return true;
         }
diff --git a/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java b/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
index 0ca9c2a..907f0dc 100644
--- a/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
+++ b/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
@@ -23,6 +23,7 @@
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.media.AudioManager;
 import android.os.Looper;
 import android.support.v4.media.session.MediaControllerCompat;
@@ -82,6 +83,9 @@
     @Mock
     private AvrcpControllerService mAvrcpControllerService;
 
+    @Mock
+    private Resources mMockResources;
+
     AvrcpControllerStateMachine mAvrcpStateMachine;
 
     @Before
@@ -102,7 +106,9 @@
         TestUtils.clearAdapterService(mAvrcpAdapterService);
         TestUtils.setAdapterService(mA2dpAdapterService);
         TestUtils.startService(mA2dpServiceRule, A2dpSinkService.class);
-        doReturn(mTargetContext.getResources()).when(mAvrcpControllerService).getResources();
+        when(mMockResources.getBoolean(R.bool.a2dp_sink_automatically_request_audio_focus))
+                .thenReturn(true);
+        doReturn(mMockResources).when(mAvrcpControllerService).getResources();
         doReturn(15).when(mAudioManager).getStreamMaxVolume(anyInt());
         doReturn(8).when(mAudioManager).getStreamVolume(anyInt());
         doReturn(true).when(mAudioManager).isVolumeFixed();
@@ -601,6 +607,8 @@
      */
     @Test
     public void testPlaybackWhileMusicPlaying() {
+        when(mMockResources.getBoolean(R.bool.a2dp_sink_automatically_request_audio_focus))
+                .thenReturn(false);
         Assert.assertEquals(AudioManager.AUDIOFOCUS_NONE, A2dpSinkService.getFocusState());
         doReturn(true).when(mAudioManager).isMusicActive();
         setUpConnectedState(true, true);
@@ -608,7 +616,6 @@
                 AvrcpControllerStateMachine.MESSAGE_PROCESS_PLAY_STATUS_CHANGED,
                 PlaybackStateCompat.STATE_PLAYING);
         TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper());
-        verify(mAudioManager, times(1)).isMusicActive();
         verify(mAvrcpControllerService,
                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)).sendPassThroughCommandNative(
                 eq(mTestAddress), eq(AvrcpControllerService.PASS_THRU_CMD_ID_PAUSE), eq(KEY_DOWN));
@@ -629,7 +636,6 @@
                 AvrcpControllerStateMachine.MESSAGE_PROCESS_PLAY_STATUS_CHANGED,
                 PlaybackStateCompat.STATE_PLAYING);
         TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper());
-        verify(mAudioManager, times(1)).isMusicActive();
         TestUtils.waitForLooperToFinishScheduledTask(
                 A2dpSinkService.getA2dpSinkService().getMainLooper());
         Assert.assertEquals(AudioManager.AUDIOFOCUS_GAIN, A2dpSinkService.getFocusState());