Merge f7cf3ad9372f9dfaa138eddbcf42b304f9769c43 on remote branch

Change-Id: Ie5fac71aee7fe07f3e70d892c7b7d65a9ebd7eef
diff --git a/BATestApp/AndroidManifest.xml b/BATestApp/AndroidManifest.xml
index 92e0693..5685cff 100644
--- a/BATestApp/AndroidManifest.xml
+++ b/BATestApp/AndroidManifest.xml
@@ -31,8 +31,7 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="org.codeaurora.bluetooth.batestapp"
-    android:sharedUserId="android.uid.bluetooth">
+    package="org.codeaurora.bluetooth.batestapp">
 
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
@@ -42,6 +41,7 @@
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
 
     <application
         android:allowBackup="true"
@@ -78,4 +78,4 @@
         </receiver>
     </application>
 
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/BATestApp/src/org/codeaurora/bluetooth/batestapp/BroadcastAudioAppReceiver.java b/BATestApp/src/org/codeaurora/bluetooth/batestapp/BroadcastAudioAppReceiver.java
index 2770f7f..aaa1a47 100644
--- a/BATestApp/src/org/codeaurora/bluetooth/batestapp/BroadcastAudioAppReceiver.java
+++ b/BATestApp/src/org/codeaurora/bluetooth/batestapp/BroadcastAudioAppReceiver.java
@@ -51,7 +51,11 @@
                     BluetoothAdapter.ERROR);
             if (state == BluetoothAdapter.STATE_ON) {
                 Log.d(TAG, "state == BluetoothAdapter.STATE_ON");
-                context.startService(new Intent(context, GattBroadcastService.class));
+                try {
+                    context.startService(new Intent(context, GattBroadcastService.class));
+                } catch (IllegalStateException e) {
+                    Log.e(TAG, " GattBroadcastService start failed " + e.toString());
+                }
             }
         }
     }
diff --git a/certification_tools/blegatt_test/gatt_test.cpp b/certification_tools/blegatt_test/gatt_test.cpp
index 383ad5f..3453369 100644
--- a/certification_tools/blegatt_test/gatt_test.cpp
+++ b/certification_tools/blegatt_test/gatt_test.cpp
@@ -2218,7 +2218,7 @@
 void bdt_init(void)
 {
     bdt_log("INIT BT ");
-    status = sBtInterface->init(&bt_callbacks);
+    status = sBtInterface->init(&bt_callbacks, false, false);
     if (status == BT_STATUS_SUCCESS) {
         // Get Vendor Interface
         btvendorInterface = (btvendor_interface_t *)sBtInterface->get_profile_interface(BT_PROFILE_VENDOR_ID);
@@ -2239,7 +2239,7 @@
         bdt_log("Bluetooth is already enabled");
         return;
     }
-    status = sBtInterface->enable(false);
+    status = sBtInterface->enable();
 
     check_return_status(status);
 }
diff --git a/certification_tools/l2test_ertm/l2test_ertm.cpp b/certification_tools/l2test_ertm/l2test_ertm.cpp
index 2c3b4ae..1e5e84e 100644
--- a/certification_tools/l2test_ertm/l2test_ertm.cpp
+++ b/certification_tools/l2test_ertm/l2test_ertm.cpp
@@ -662,7 +662,7 @@
 void bdt_init(void)
 {
     printf("INIT BT \n");
-    status = (bt_status_t)sBtInterface->init(&bt_callbacks);
+    status = (bt_status_t)sBtInterface->init(&bt_callbacks, false, false);
     if (status == BT_STATUS_SUCCESS) {
         // Get Vendor Interface
         btvendorInterface = (btvendor_interface_t *)sBtInterface->get_profile_interface(BT_PROFILE_VENDOR_ID);
@@ -683,7 +683,7 @@
         printf("Bluetooth is already enabled\n");
         return;
     }
-    status = (bt_status_t)sBtInterface->enable(strict_mode);
+    status = (bt_status_t)sBtInterface->enable();
     return;
 }
 
diff --git a/certification_tools/mcap_tool/mcap_tool.cpp b/certification_tools/mcap_tool/mcap_tool.cpp
index 94f8a8a..17910b5 100644
--- a/certification_tools/mcap_tool/mcap_tool.cpp
+++ b/certification_tools/mcap_tool/mcap_tool.cpp
@@ -804,7 +804,7 @@
 void bdt_init(void)
 {
     bdt_log("INIT BT ");
-    status = (bt_status_t)sBtInterface->init(&bt_callbacks);
+    status = (bt_status_t)sBtInterface->init(&bt_callbacks, false, false);
      if (status == BT_STATUS_SUCCESS) {
         // Get Vendor Interface
         btvendorInterface = (btvendor_interface_t *)sBtInterface->get_profile_interface(BT_PROFILE_VENDOR_ID);
@@ -824,7 +824,7 @@
         bdt_log("Bluetooth is already enabled");
         return;
     }
-    status = (bt_status_t)sBtInterface->enable(strict_mode);
+    status = (bt_status_t)sBtInterface->enable();
 
     check_return_status(status);
 }
diff --git a/certification_tools/rfcommtest/rfcommtest.cpp b/certification_tools/rfcommtest/rfcommtest.cpp
index 2336019..2481d5e 100644
--- a/certification_tools/rfcommtest/rfcommtest.cpp
+++ b/certification_tools/rfcommtest/rfcommtest.cpp
@@ -715,7 +715,7 @@
 void bdt_init(void)
 {
     bdt_log("INIT BT ");
-    status = (bt_status_t)sBtInterface->init(&bt_callbacks);
+    status = (bt_status_t)sBtInterface->init(&bt_callbacks, false, false);
     if (status == BT_STATUS_SUCCESS) {
         // Get Vendor Interface
         btvendorInterface = (btvendor_interface_t *)sBtInterface->get_profile_interface(BT_PROFILE_VENDOR_ID);
@@ -735,7 +735,7 @@
         bdt_log("Bluetooth is already enabled");
         return;
     }
-    status = (bt_status_t)sBtInterface->enable(strict_mode);
+    status = (bt_status_t)sBtInterface->enable();
 
     check_return_status(status);
 }
diff --git a/packages_apps_bluetooth_ext/jni/Android.bp b/packages_apps_bluetooth_ext/jni/Android.bp
index cb15b77..439f7a2 100644
--- a/packages_apps_bluetooth_ext/jni/Android.bp
+++ b/packages_apps_bluetooth_ext/jni/Android.bp
@@ -27,7 +27,4 @@
         "com_android_bluetooth_ba.cpp",
         "com_android_bluetooth_hf_vendor.cpp",
     ],
-    sanitize: {
-        never: true,
-    },
 }
diff --git a/packages_apps_bluetooth_ext/jni/com_android_bluetooth_btservice_vendor.cpp b/packages_apps_bluetooth_ext/jni/com_android_bluetooth_btservice_vendor.cpp
index e4b775d..0a05b7d 100644
--- a/packages_apps_bluetooth_ext/jni/com_android_bluetooth_btservice_vendor.cpp
+++ b/packages_apps_bluetooth_ext/jni/com_android_bluetooth_btservice_vendor.cpp
@@ -77,6 +77,8 @@
 static bt_configstore_interface_t* bt_configstore_intf = NULL;
 static void *bt_configstore_lib_handle = NULL;
 static jboolean spilt_a2dp_supported;
+static jboolean swb_supported;
+static jboolean swb_pm_supported;
 
 static int get_properties(int num_properties, bt_vendor_property_t* properties,
                           jintArray* types, jobjectArray* props) {
@@ -292,6 +294,18 @@
             } else {
               spilt_a2dp_supported = false;
             }
+          } else if(vendorProp.type == BT_PROP_SWB_ENABLE) {
+            if (!strncasecmp(vendorProp.value, "true", sizeof("true"))) {
+              swb_supported = true;
+            } else {
+              swb_supported = false;
+            }
+          } else if(vendorProp.type == BT_PROP_SWBPM_ENABLE) {
+            if (!strncasecmp(vendorProp.value, "true", sizeof("true"))) {
+              swb_pm_supported = true;
+            } else {
+              swb_pm_supported = false;
+            }
           } else if(vendorProp.type == BT_PROP_A2DP_OFFLOAD_CAP) {
             strlcpy(a2dp_offload_Cap, vendorProp.value, sizeof(a2dp_offload_Cap));
             ALOGI("%s:: a2dp_offload_Cap = %s", __func__, a2dp_offload_Cap);
@@ -406,6 +420,17 @@
     return JNI_TRUE;
 }
 
+static bool setPowerBackoffNative(JNIEnv *env, jobject obj, jboolean status) {
+
+    ALOGI("%s", __FUNCTION__);
+
+    jboolean result = JNI_FALSE;
+    if (!sBluetoothVendorInterface) return result;
+
+    sBluetoothVendorInterface->set_Power_back_off_state(status);
+    return JNI_TRUE;
+}
+
 static bool getProfileInfoNative(JNIEnv *env, jobject obj, jint profile_id , jint profile_info) {
 
     ALOGI("%s", __FUNCTION__);
@@ -458,6 +483,18 @@
     return spilt_a2dp_supported;
 }
 
+static jboolean isSwbEnabledNative(JNIEnv* env) {
+
+    ALOGI("%s", __FUNCTION__);
+    return swb_supported;
+}
+
+static jboolean isSwbPmEnabledNative(JNIEnv* env) {
+
+    ALOGI("%s", __FUNCTION__);
+    return swb_pm_supported;
+}
+
 static JNINativeMethod sMethods[] = {
     {"classInitNative", "()V", (void *) classInitNative},
     {"initNative", "()V", (void *) initNative},
@@ -465,6 +502,7 @@
     {"bredrcleanupNative", "()V", (void*) bredrcleanupNative},
     {"bredrstartupNative", "()V", (void*) bredrstartupNative},
     {"setWifiStateNative", "(Z)V", (void*) setWifiStateNative},
+    {"setPowerBackoffNative", "(Z)V", (void*) setPowerBackoffNative},
     {"getProfileInfoNative", "(II)Z", (void*) getProfileInfoNative},
     {"getQtiStackStatusNative", "()Z", (void*) getQtiStackStatusNative},
     {"voipNetworkWifiInfoNative", "(ZZ)Z", (void *)voipNetworkWifiInfoNative},
@@ -473,6 +511,8 @@
     {"getA2apOffloadCapabilityNative", "()Ljava/lang/String;",
             (void*) getA2apOffloadCapabilityNative},
     {"isSplitA2dpEnabledNative", "()Z", (void*) isSplitA2dpEnabledNative},
+    {"isSwbEnabledNative", "()Z", (void*) isSwbEnabledNative},
+    {"isSwbPmEnabledNative", "()Z", (void*) isSwbPmEnabledNative},
 };
 
 int load_bt_configstore_lib() {
diff --git a/packages_apps_bluetooth_ext/jni/com_android_bluetooth_hf_vendor.cpp b/packages_apps_bluetooth_ext/jni/com_android_bluetooth_hf_vendor.cpp
index f11d4cd..d9bee6a 100644
--- a/packages_apps_bluetooth_ext/jni/com_android_bluetooth_hf_vendor.cpp
+++ b/packages_apps_bluetooth_ext/jni/com_android_bluetooth_hf_vendor.cpp
@@ -38,6 +38,7 @@
 static btvendor_hf_interface_t *sBluetoothVendorHfInterface = NULL;
 static jobject mCallbacksObj = NULL;
 static jmethodID method_onSWB;
+static jmethodID method_onTwsBatteryStateCallback;
 
 static jbyteArray marshall_bda(RawAddress* bd_addr) {
   CallbackEnv sCallbackEnv(__func__);
@@ -65,14 +66,41 @@
                                  addr.get());
 }
 
+void bt_twsp_battery_status_callback(char* at_string, RawAddress* bd_addr) {
+    ALOGD("TwsBatteryStateCallback :%s, BD_ADDR: %s",
+          at_string, bd_addr->ToString().c_str());
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid() || !mCallbacksObj) return;
+
+    ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
+    if (addr.get() == nullptr) return;
+
+    char null_str[] = "";
+    if (!sCallbackEnv.isValidUtf(at_string)) {
+      android_errorWriteLog(0x534e4554, "109838537");
+      ALOGE("%s: at_string is not a valid UTF string.", __func__);
+      at_string = null_str;
+    }
+
+    ScopedLocalRef<jstring> js_at_string(sCallbackEnv.get(),
+                                         sCallbackEnv->NewStringUTF(at_string));
+
+    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onTwsBatteryStateCallback,
+                                 js_at_string.get(), addr.get());
+}
+
 static btvendor_hf_callbacks_t sBluetoothVendorHfCallbacks = {
     sizeof(sBluetoothVendorHfCallbacks),
     SwbCallback,
+    bt_twsp_battery_status_callback
 };
 
 static void classInitNative(JNIEnv* env, jclass clazz) {
 
     method_onSWB = env->GetMethodID(clazz, "onSWB", "(I[B)V");
+    method_onTwsBatteryStateCallback =
+         env->GetMethodID(clazz, "onTwsBatteryStateCallback",
+                                 "(Ljava/lang/String;[B)V");
     ALOGI("%s: succeeds", __FUNCTION__);
 }
 
diff --git a/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java b/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java
index 8903fcf..4bdfea4 100644
--- a/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java
+++ b/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java
@@ -98,8 +98,6 @@
     private static final String TAG = "Avrcp_ext";
     private static final String ABSOLUTE_VOLUME_BLACKLIST = "absolute_volume_blacklist";
     private static final String AVRCP_VERSION_PROPERTY = "persist.bluetooth.avrcpversion";
-    private static final String AVRCP_1_4_STRING = "avrcp14";
-    private static final String AVRCP_1_5_STRING = "avrcp15";
     private static final String AVRCP_1_6_STRING = "avrcp16";
     private static final String AVRCP_NOTIFICATION_ID = "avrcp_notification";
 
@@ -157,6 +155,8 @@
     private boolean updateAbsVolume = false;
     private static final int NO_PLAYER_ID = 0;
 
+    private boolean is_player_updated_for_browse;
+    private String mCachedBrowsePlayer;
     private int mCurrAddrPlayerID;
     private int mCurrBrowsePlayerID;
     private int mLastUsedPlayerID;
@@ -422,6 +422,8 @@
 
     private Avrcp_ext(Context context, A2dpService svc, int maxConnections ) {
         if (DEBUG) Log.v(TAG, "Avrcp");
+        mCachedBrowsePlayer = null;
+        is_player_updated_for_browse = false;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
         mMediaAttributes = new MediaAttributes(null, null);
         mLastQueueId = MediaSession.QueueItem.UNKNOWN_ID;
@@ -563,8 +565,8 @@
             }
         }
 
-        String avrcpVersion = SystemProperties.get(AVRCP_VERSION_PROPERTY, AVRCP_1_4_STRING);
-        if (DEBUG) Log.d(TAG, "avrcpVersion: " + avrcpVersion);
+        String avrcpVersion = SystemProperties.get(AVRCP_VERSION_PROPERTY, AVRCP_1_6_STRING);
+        if (DEBUG) Log.d(TAG, "avrcpVersion " + avrcpVersion);
         /* Enable Cover Art support is version is 1.6 and flag is set in config */
         if (isCoverArtSupported && avrcpVersion != null &&
             avrcpVersion.equals(AVRCP_1_6_STRING))
@@ -719,7 +721,7 @@
         }
         @Override
         public synchronized void onPlaybackStateChanged(PlaybackState state) {
-            if (DEBUG) Log.v(TAG, "onPlaybackStateChanged: state " + state.toString());
+            if (DEBUG) Log.v(TAG, "onPlaybackStateChanged: state " + ((state != null)? state.toString() : "NULL"));
             updateCurrentMediaState(null);
             Log.v(TAG, " Exit onPlaybackStateChanged");
         }
@@ -812,11 +814,16 @@
                         notifyVolumeChanged(vol, false);
                 }
                 if (vol >= 0) {
-                    vol = convertToAvrcpVolume(vol);
-                    Log.d(TAG,"vol = " + vol + "rem vol = " + deviceFeatures[deviceIndex].mRemoteVolume);
-                    if(vol != deviceFeatures[deviceIndex].mRemoteVolume &&
+                    int volume = convertToAvrcpVolume(vol);
+                    int remVol = deviceFeatures[deviceIndex].mRemoteVolume;
+                    if (remVol != -1) {
+                        remVol = convertToAudioStreamVolume(remVol);
+                    }
+                    Log.d(TAG,"vol = " + vol + "remVol = " + remVol);
+                    if (vol != remVol &&
                        deviceFeatures[deviceIndex].mCurrentDevice != null) {
-                       setVolumeNative(vol , getByteAddress(deviceFeatures[deviceIndex].mCurrentDevice));
+                       setVolumeNative(volume , getByteAddress(deviceFeatures[deviceIndex].mCurrentDevice));
+                       deviceFeatures[deviceIndex].mRemoteVolume = volume;
                        if (deviceFeatures[deviceIndex].mCurrentDevice.isTwsPlusDevice()) {
                            AdapterService adapterService = AdapterService.getAdapterService();
                            BluetoothDevice peer_device =
@@ -825,7 +832,7 @@
                                getIndexForDevice(peer_device) != INVALID_DEVICE_INDEX) {
                                // Change volume to peer earbud as well
                                Log.d(TAG,"setting volume to TWS+ peer also");
-                               setVolumeNative(vol, getByteAddress(peer_device));
+                               setVolumeNative(volume, getByteAddress(peer_device));
                            }
                        }
                     }
@@ -1185,6 +1192,7 @@
                         complete and making synchronization to send only one setAbsolute volume
                         during connection*/
                         if(getVolume(deviceFeatures[deviceIndex].mCurrentDevice) != -1) {
+                            deviceFeatures[deviceIndex].mRemoteVolume = absVol;
                             setAbsVolumeFlag(deviceFeatures[deviceIndex].mCurrentDevice);
                             break;
                         }
@@ -1383,7 +1391,7 @@
 
                         if(mHandler.hasMessages(MESSAGE_START_SHO)) {
                             mHandler.removeMessages(MESSAGE_START_SHO);
-                            triggerSHO(SHOQueue.device, SHOQueue.PlayReq);
+                            triggerSHO(SHOQueue.device, SHOQueue.PlayReq, false);
                         }
                     }
                     if(shoComplete == true) {
@@ -1555,21 +1563,29 @@
                 break;
 
             case MESSAGE_START_SHO:
-                if (mA2dpService != null)
-                    break;
-
                 synchronized (Avrcp_ext.this) {
                     if(mHandler.hasMessages(MESSAGE_START_SHO)) {
                         Log.e(TAG, "Queue already has another SHO pending");
                         break;
                     }
                     isShoActive = true;
-                    Log.d(TAG, "2: SHO started. PlayReq = " + msg.arg1);
+                    Log.d(TAG, "2: SHO started. PlayReq = " + msg.arg1 + "SHO Retry = " + msg.arg2);
                 }
 
                 BluetoothDevice dev = (BluetoothDevice)msg.obj;
                 boolean PlayReq = (msg.arg1 == 1);
-                mA2dpService.startSHO(dev);
+                boolean isRetry = (msg.arg2 == 1);
+                boolean ret;
+                ret = mA2dpService.startSHO(dev);
+                if(!ret) {
+                    isShoActive = false;
+                    if(isRetry) {
+                        Log.e(TAG, "SHO failed");
+                    } else {
+                        triggerSHO(dev, PlayReq, true);
+                    }
+                    break;
+                }
 
                 if(!PlayReq) {
                     synchronized (Avrcp_ext.this) {
@@ -1577,7 +1593,7 @@
                         Log.d(TAG, "3: SHO complete");
                         if (mHandler.hasMessages(MESSAGE_START_SHO)) {
                             mHandler.removeMessages(MESSAGE_START_SHO);
-                            triggerSHO(SHOQueue.device, SHOQueue.PlayReq);
+                            triggerSHO(SHOQueue.device, SHOQueue.PlayReq, false);
                         }
                     }
                     CompleteSHO();
@@ -1809,7 +1825,7 @@
                 for (int i = 0; i < maxAvrcpConnections; i++) {
                      if (i != deviceIndex && !deviceFeatures[i].isActiveDevice &&
                           deviceFeatures[i].mLastRspPlayStatus == PLAYSTATUS_PLAYING &&
-                          (state.getState() == PlaybackState.STATE_PLAYING)) {
+                          (state != null && state.getState() == PlaybackState.STATE_PLAYING)) {
                          PlaybackState.Builder playState = new PlaybackState.Builder();
                          playState.setState(PlaybackState.STATE_PAUSED,
                                           PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f);
@@ -2729,7 +2745,7 @@
                     if (deviceFeatures[i].mCurrentDevice != null) {
                         Log.d(TAG, "SendPassThruPlay command sent for = "
                                 + deviceFeatures[i].mCurrentDevice);
-                        if (volume > mLocalVolume) {
+                        /*if (volume > mLocalVolume) {
                             Log.d(TAG, "Vol Passthrough Up");
                             avrcpCtrlService.sendPassThroughCmd(
                                 deviceFeatures[i].mCurrentDevice, AVRC_ID_VOL_UP,
@@ -2745,7 +2761,7 @@
                            avrcpCtrlService.sendPassThroughCmd(
                                 deviceFeatures[i].mCurrentDevice, AVRC_ID_VOL_DOWN,
                                 AvrcpConstants_ext.KEY_STATE_RELEASE);
-                        }
+                         }*/
                         mLocalVolume = volume;
                     }
                 }
@@ -3042,6 +3058,36 @@
         }
     }
 
+
+    private void SetBrowsePackage(String PackageName) {
+        String browseService = (PackageName != null)?getBrowseServiceName(PackageName):null;
+        Log.w(TAG, "SetBrowsePackage for pkg " + PackageName + "svc" + browseService);
+        if (browseService != null && !browseService.isEmpty()) {
+            BluetoothDevice active_device = null;
+            for (int i = 0; i < maxAvrcpConnections; i++) {
+                if (deviceFeatures[i].mCurrentDevice != null &&
+                        deviceFeatures[i].isActiveDevice == true) {
+                    Log.w(TAG,"Device " + deviceFeatures[i].mCurrentDevice.getAddress() +" active");
+                    active_device = deviceFeatures[i].mCurrentDevice;
+                }
+            }
+            if (active_device != null) {
+                is_player_updated_for_browse = true;
+                byte[] addr = getByteAddress(active_device);
+                if (mAvrcpBrowseManager.getBrowsedMediaPlayer(addr) != null) {
+                    mCurrentBrowsingDevice = active_device;
+                    Log.w(TAG, "Addr Player update to Browse " + PackageName);
+                    mAvrcpBrowseManager.getBrowsedMediaPlayer(addr).
+                            setCurrentPackage(PackageName, browseService);
+                }
+            } else {
+                Log.w(TAG, "SetBrowsePackage Active device not set yet cache " + PackageName +
+                        "wait for connection");
+                mCachedBrowsePlayer = PackageName;
+            }
+        }
+    }
+
     private void blackListCurrentDevice(int i) {
         String mAddress = null;
         if (deviceFeatures[i].mCurrentDevice == null) {
@@ -3232,9 +3278,6 @@
         for (int i = 0; i < maxAvrcpConnections; i++ ) {
             if (deviceFeatures[i].mCurrentDevice !=null &&
                     deviceFeatures[i].mCurrentDevice.equals(device)) {
-                //for BT ON/OFF case sometime disconnect is coming for 1 or all device
-                //so storing volume before disconnect
-                storeVolumeForAllDevice(device);
                 // initiate cleanup for all variables;
                 Message msg = mHandler.obtainMessage(MESSAGE_DEVICE_RC_CLEANUP, STACK_CLEANUP,
                        0, device);
@@ -3286,6 +3329,8 @@
             mCurrentBrowsingDevice = null;
             changePathDepth = 0;
             changePathFolderType = 0;
+            is_player_updated_for_browse = false;
+            Log.w(TAG,"Reset is_player_updated_for_browse on device disconnection");
         }
         Log.v(TAG,"Exit setAvrcpDisconnectedDevice");
     }
@@ -3537,6 +3582,7 @@
                     if (newControllers.size() > 0 && getAddressedPlayerInfo() == null) {
                         if (DEBUG)
                             Log.v(TAG, "No addressed player but active sessions, taking first.");
+                        Log.w(TAG,"Trigger setAddressedMediaSessionPkg frm onActiveSessionChanged");
                         setAddressedMediaSessionPackage(newControllers.get(0).getPackageName());
                     }
                     updateCurrentMediaState(null);
@@ -3555,13 +3601,16 @@
         }
         // No change.
         if (getPackageName(mCurrAddrPlayerID).equals(packageName)) return;
-        if (DEBUG) Log.v(TAG, "Changing addressed media session to " + packageName);
+        Log.w(TAG, "Changing addressed media session to " + packageName);
         // If the player doesn't exist, we need to add it.
         if (getMediaPlayerInfo(packageName) == null) {
             addMediaPlayerPackage(packageName);
             updateCurrentMediaState(null);
         }
 
+        Log.w(TAG, "Calling SetBrowsePackage for " + packageName);
+        SetBrowsePackage(packageName);
+
         synchronized (this) {
             synchronized (mMediaPlayerInfoList) {
                 for (Map.Entry<Integer, MediaPlayerInfo_ext> entry : mMediaPlayerInfoList.entrySet()) {
@@ -3602,6 +3651,9 @@
         synchronized (Avrcp_ext.this) {
             addMediaPlayerController(activeController);
             setAddressedMediaSessionPackage(activeController.getPackageName());
+            mCachedBrowsePlayer = activeController.getPackageName();
+            Log.w(TAG,"Trigger setAddressedMediaSessionPackage from setActiveMediaSession" +
+                    mCachedBrowsePlayer);
         }
     }
 
@@ -3616,6 +3668,9 @@
 
         addMediaPlayerController(mController);
         setAddressedMediaSessionPackage(mController.getPackageName());
+        mCachedBrowsePlayer = mController.getPackageName();
+        Log.w(TAG,"Trigger setAddressedMediaSessionPkg from setActiveMediaSession" +
+                mCachedBrowsePlayer);
     }
 
     private boolean startBrowseService(byte[] bdaddr, String packageName) {
@@ -4373,7 +4428,7 @@
         deviceFeatures[index].mLastLocalVolume = -1;
     }
 
-    private synchronized void onConnectionStateChanged(
+    private void onConnectionStateChanged(
             boolean rc_connected, boolean br_connected, byte[] address) {
         BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
         Log.d(TAG, "onConnectionStateChanged " + rc_connected + " " + br_connected + " Addr:"
@@ -4859,27 +4914,6 @@
         return INVALID_DEVICE_INDEX;
     }
 
-    public void storeVolumeForAllDevice(BluetoothDevice device) {
-        SharedPreferences.Editor pref = getVolumeMap().edit();
-        for (int i = 0; i < maxAvrcpConnections; i++) {
-            if (deviceFeatures[i].mCurrentDevice != null &&
-               deviceFeatures[i].mLocalVolume != -1) { //2nd condition to avoid -1 update to audio
-                if(deviceFeatures[i].isActiveDevice)//to get exact volume for active device
-                    deviceFeatures[i].mLocalVolume =
-                        mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
-                if(getVolume(deviceFeatures[i].mCurrentDevice) != deviceFeatures[i].mLocalVolume) {
-                    Log.i(TAG, "storeVolumeForAllDevice: Storing stream volume level for device " +
-                        deviceFeatures[i].mCurrentDevice + " : " + deviceFeatures[i].mLocalVolume);
-                    mVolumeMap.put(deviceFeatures[i].mCurrentDevice, deviceFeatures[i].mLocalVolume);
-                    pref.putInt(deviceFeatures[i].mCurrentDevice.getAddress(),
-                        deviceFeatures[i].mLocalVolume);
-                    // Always use apply() since it is asynchronous, otherwise the call
-                    //can hang waiting for storage to be written.
-                    pref.apply();
-                }
-            }
-        }
-   }
 
     public void storeVolumeForDevice(BluetoothDevice device) {
         SharedPreferences.Editor pref = getVolumeMap().edit();
@@ -4908,8 +4942,12 @@
     }
 
     public boolean startSHO(BluetoothDevice device, boolean PlayReq) {
+        HeadsetService headsetService = HeadsetService.getHeadsetService();
+        boolean isInCall = headsetService != null && headsetService.isScoOrCallActive();
+        boolean isFMActive = mAudioManager.getParameters("fm_status").contains("1");
+        Log.d(TAG, "0: SHO Init: isInCall = " + isInCall + " isFMActive = " + isFMActive);
         synchronized (Avrcp_ext.this) {
-            if(isShoActive) {
+            if (isShoActive) {
                 mHandler.removeMessages (MESSAGE_START_SHO);
                 Message msg = mHandler.obtainMessage(MESSAGE_START_SHO, PlayReq?1:0, 0, device);
                 SHOQueue.device = device;
@@ -4923,14 +4961,28 @@
             }
         }
         boolean ret = mA2dpService.startSHO(device);
+        if(!ret) {
+            isShoActive = false;
+            if (device.isTwsPlusDevice()) {
+                BluetoothDevice activeDevice = mA2dpService.getActiveDevice();
+                if (activeDevice != null &&
+                    isTwsPlusPair(device, activeDevice)) {
+                    Log.e(TAG,"TWS+ switch ignored, do not retry sho");
+                    CompleteSHO();
+                    return ret;
+                }
+            }
+            mHandler.removeMessages(MESSAGE_START_SHO);
+            triggerSHO(device, PlayReq, true);
+        }
         synchronized (Avrcp_ext.this) {
-            if (!PlayReq) {
+            if (!PlayReq || isInCall || isFMActive) {
                 isShoActive = false;
                 Log.d(TAG, "6: SHO complete");
 
                 if (mHandler.hasMessages(MESSAGE_START_SHO)) {
                     mHandler.removeMessages(MESSAGE_START_SHO);
-                    triggerSHO(SHOQueue.device, SHOQueue.PlayReq);
+                    triggerSHO(SHOQueue.device, SHOQueue.PlayReq, false);
                 }
             }
         }
@@ -4938,9 +4990,14 @@
         return ret;
     }
 
-    private void triggerSHO(BluetoothDevice device, boolean PlayReq) {
-        Message msg = mHandler.obtainMessage(MESSAGE_START_SHO, PlayReq?1:0, 0, device);
-        mHandler.sendMessage(msg);
+    private void triggerSHO(BluetoothDevice device, boolean PlayReq, boolean isRetry) {
+        Message msg = mHandler.obtainMessage(MESSAGE_START_SHO, PlayReq?1:0, isRetry?1:0, device);
+        if(isRetry) {
+            mHandler.sendMessageDelayed(msg, 2000);
+            Log.e(TAG, "Retry SHO after delay");
+        } else {
+            mHandler.sendMessage(msg);
+        }
     }
 
     public void CompleteSHO() {
@@ -4963,6 +5020,12 @@
             return;
         }
         deviceFeatures[deviceIndex].isActiveDevice = true;
+
+        Log.w(TAG, "Active device Calling SetBrowsePackage for " + mCachedBrowsePlayer);
+        if (mCachedBrowsePlayer != null && is_player_updated_for_browse == false) {
+            SetBrowsePackage(mCachedBrowsePlayer);
+        }
+
         if (updateAbsVolume == true && deviceFeatures[deviceIndex].mCurrentDevice.isTwsPlusDevice()) {
             Log.d(TAG,"setting absVolume flag for TWS+ device");
             mAudioManager.avrcpSupportsAbsoluteVolume(device.getAddress(),true);
@@ -5396,6 +5459,8 @@
         long time = System.currentTimeMillis();
         Log.v(TAG, "recordKeyDispatched: " + event + " dispatched to " + packageName);
         setAddressedMediaSessionPackage(packageName);
+        mCachedBrowsePlayer = packageName;
+        Log.w(TAG,"Trigger setAddressedMediaSessionPkg recordKeyDispatch" + mCachedBrowsePlayer);
         synchronized (mPassthroughPending) {
             Iterator<MediaKeyLog> pending = mPassthroughPending.iterator();
             while (pending.hasNext()) {
@@ -5415,11 +5480,13 @@
             new MediaSessionManager.Callback() {
                 @Override
                 public void onMediaKeyEventDispatched(KeyEvent event, MediaSession.Token token) {
-                    // Get the package name
-                    android.media.session.MediaController controller =
-                            new android.media.session.MediaController(mContext, token);
-                    String targetPackage = controller.getPackageName();
-                    recordKeyDispatched(event, targetPackage);
+                    if (token != null) {
+                        // Get the package name
+                        android.media.session.MediaController controller =
+                                new android.media.session.MediaController(mContext, token);
+                        String targetPackage = controller.getPackageName();
+                        recordKeyDispatched(event, targetPackage);
+                    }
                 }
 
                 @Override
@@ -5441,6 +5508,9 @@
                     }
                     // We can still get a passthrough which will revive this player.
                     setAddressedMediaSessionPackage(receiver.getPackageName());
+                    mCachedBrowsePlayer = receiver.getPackageName();
+                    Log.w(TAG,"Trigger setAddressedMediaSessionPackage from onAddrPlayerChanged" +
+                            mCachedBrowsePlayer);
                 }
             };
 
diff --git a/packages_apps_bluetooth_ext/src/avrcpcontroller/CoverArtUtils.java b/packages_apps_bluetooth_ext/src/avrcpcontroller/CoverArtUtils.java
index c3eb7f6..a31fd8d 100644
--- a/packages_apps_bluetooth_ext/src/avrcpcontroller/CoverArtUtils.java
+++ b/packages_apps_bluetooth_ext/src/avrcpcontroller/CoverArtUtils.java
@@ -64,14 +64,14 @@
     }
 
     private void broadcastInValidHandle(Context ctx, MediaMetadata metadata) {
-        Intent intent = new Intent(AvrcpControllerService.ACTION_TRACK_EVENT);
+        /*Intent intent = new Intent(AvrcpControllerService.ACTION_TRACK_EVENT);
         intent.putExtra(AvrcpControllerService.EXTRA_METADATA, metadata);
         intent.putExtra(EXTRA_METADATA_IS_INVALID_HANDLE, true);
         if (DBG) {
             Log.d(TAG, " broadcastInValidHandle = " + metadata.getDescription());
         }
         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-        ctx.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
+        ctx.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM); */
     }
 
     public void onElementAttributeUpdate(byte[] address, byte numAttributes, int[] attributes,
@@ -90,13 +90,13 @@
            attrList.add(attr);
         }
         List<String> attrValList = Arrays.asList(attribVals);
-        TrackInfo trackInfo = new TrackInfo(attrList, attrValList);
-        if (DBG) {
-            Log.d(TAG, "onElementAttributeUpdate " + trackInfo);
-        }
-        Message msg = avrcpCtSm.obtainMessage(
-                AvrcpControllerStateMachine.MESSAGE_PROCESS_TRACK_CHANGED, trackInfo);
-        avrcpCtSm.sendMessage(msg);
+        //TrackInfo trackInfo = new TrackInfo(attrList, attrValList);
+        //if (DBG) {
+        //    Log.d(TAG, "onElementAttributeUpdate " + trackInfo);
+        //}
+        //Message msg = avrcpCtSm.obtainMessage(
+        //        AvrcpControllerStateMachine.MESSAGE_PROCESS_TRACK_CHANGED, trackInfo);
+        //avrcpCtSm.sendMessage(msg);
     }
 
     public void msgDisconnectBip(AvrcpControllerBipStateMachine bipStateMachine,
@@ -119,7 +119,7 @@
 
     public boolean msgTrackChanged(Context ctx, AvrcpControllerBipStateMachine bipStateMachine,
             AvrcpPlayer addressedPlayer, RemoteDevice remoteDevice) {
-        boolean isValidHandle = !addressedPlayer.getCurrentTrack().getCoverArtHandle().isEmpty();
+        /*boolean isValidHandle = !addressedPlayer.getCurrentTrack().getCoverArtHandle().isEmpty();
         if (bipStateMachine != null && isValidHandle) {
             int imageOrThumbnail;
             if (AvrcpControllerBipStateMachine.mImageType.equalsIgnoreCase("thumbnail")) {
@@ -127,16 +127,16 @@
             } else {
                 imageOrThumbnail = AvrcpControllerBipStateMachine.MESSAGE_FETCH_IMAGE;
             }
-            bipStateMachine.sendMessage(imageOrThumbnail,
-                    addressedPlayer.getCurrentTrack().getCoverArtHandle());
+            //bipStateMachine.sendMessage(imageOrThumbnail,
+            //        addressedPlayer.getCurrentTrack().getCoverArtHandle());
         }
         if (!isValidHandle && remoteDevice != null && remoteDevice.isCoverArtSupported()) {
             if (DBG) {
                 Log.d(TAG, " Cover Art Handle not valid ");
             }
-            broadcastInValidHandle(ctx, addressedPlayer.getCurrentTrack().getMediaMetaData());
+            //broadcastInValidHandle(ctx, addressedPlayer.getCurrentTrack().getMediaMetaData());
             return false;
-        }
+        }*/
         return true;
     }
 
@@ -147,50 +147,50 @@
         }
         switch (bipAction) {
             case MESSAGE_BIP_CONNECTED:
-                if (addressedPlayer.getCurrentTrack().getCoverArtHandle().isEmpty()
-                    && remoteDevice != null) {
+               //if (addressedPlayer.getCurrentTrack().getCoverArtHandle().isEmpty()
+               //     && remoteDevice != null) {
                 /*
                  * track changed happened before BIP connection. should fetch cover art handle.
                  * NumAttributes = 0 and attributes list as null will fetch all attributes
                  */
                     AvrcpControllerService.getElementAttributesNative(
                             remoteDevice.getBluetoothAddress(), (byte) 0, null);
-                }
+                //}
             break;
             case MESSAGE_BIP_DISCONNECTED:
                 // clear cover art related info for current track.
-                addressedPlayer.getCurrentTrack().clearCoverArtData();
+                //addressedPlayer.getCurrentTrack().clearCoverArtData();
             break;
             case MESSAGE_BIP_IMAGE_FETCHED:
-                boolean imageUpdated = addressedPlayer.getCurrentTrack().updateImageLocation(
+                /*boolean imageUpdated = addressedPlayer.getCurrentTrack().updateImageLocation(
                 msg.getData().getString(AvrcpControllerBipStateMachine.COVER_ART_HANDLE),
                 msg.getData()
                     .getString(AvrcpControllerBipStateMachine.COVER_ART_IMAGE_LOCATION));
                 if (imageUpdated) {
                     broadcastMetaDataChanged(ctx,
                         addressedPlayer.getCurrentTrack().getMediaMetaData());
-                }
+                } */
             break;
             case MESSAGE_BIP_THUMB_NAIL_FETCHED:
-                boolean thumbNailUpdated = addressedPlayer.getCurrentTrack().updateThumbNailLocation
+                /*boolean thumbNailUpdated = addressedPlayer.getCurrentTrack().updateThumbNailLocation
                     (msg.getData().getString(AvrcpControllerBipStateMachine.COVER_ART_HANDLE),
                      msg.getData()
                      .getString(AvrcpControllerBipStateMachine.COVER_ART_IMAGE_LOCATION));
             if (thumbNailUpdated) {
                 broadcastMetaDataChanged(ctx,
                     addressedPlayer.getCurrentTrack().getMediaMetaData());
-            }
+            }*/
             break;
         }
     }
 
     private void broadcastMetaDataChanged(Context ctx, MediaMetadata metadata) {
-        Intent intent = new Intent(AvrcpControllerService.ACTION_TRACK_EVENT);
+        /*Intent intent = new Intent(AvrcpControllerService.ACTION_TRACK_EVENT);
         intent.putExtra(AvrcpControllerService.EXTRA_METADATA, metadata);
         if (DBG) {
             Log.d(TAG, " broadcastMetaDataChanged = " + metadata.getDescription());
         }
-        ctx.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
+        ctx.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM); */
     }
 
     public String dumpMessageString(int message) {
diff --git a/packages_apps_bluetooth_ext/src/ba/BATService.java b/packages_apps_bluetooth_ext/src/ba/BATService.java
index 9d20265..b658a67 100644
--- a/packages_apps_bluetooth_ext/src/ba/BATService.java
+++ b/packages_apps_bluetooth_ext/src/ba/BATService.java
@@ -453,7 +453,7 @@
         if((mPrevStackBATState == BA_STACK_STATE_PENDING) &&
                 (mCurrStackBATState == BA_STACK_STATE_PAUSED)) {
             Log.d(TAG," updating AudioManager: Connected for BA ");
-            mAudioManager.handleBluetoothA2dpActiveDeviceChange(
+            mAudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
                 mBADevice, BluetoothProfile.STATE_CONNECTED,BluetoothProfile.A2DP, true, -1);
             //BA audio works on the principal of absVol
             //Currently mm-audio tracks value of last updated absVol support,
@@ -471,13 +471,13 @@
                 // as a2dp has to be updated as well. Switching should happen to
                 // A2DP in this case.
                 Log.d(TAG," updating AudioManager: Connected for A2DP ");
-                mAudioManager.handleBluetoothA2dpActiveDeviceChange(
+                mAudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
                     a2dpActiveDevice, BluetoothProfile.STATE_CONNECTED,BluetoothProfile.A2DP,
                     true, -1);
             } else {// a2dp active device is null.
                 // inform BA device as disconnected. we have to send noisy intent
                 // because BA seems to be last device.
-                mAudioManager.handleBluetoothA2dpActiveDeviceChange(
+                mAudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
                         mBADevice, BluetoothProfile.STATE_DISCONNECTED,BluetoothProfile.A2DP,
                         false, -1);
             }
diff --git a/packages_apps_bluetooth_ext/src/btservice/Vendor.java b/packages_apps_bluetooth_ext/src/btservice/Vendor.java
index caa6647..685807a 100644
--- a/packages_apps_bluetooth_ext/src/btservice/Vendor.java
+++ b/packages_apps_bluetooth_ext/src/btservice/Vendor.java
@@ -68,6 +68,11 @@
     private String a2dpOffloadCap;
     // Split A2dp will be enabled by default
     private boolean splitA2dpEnabled = true;
+    private static boolean PowerbackoffStatus = false;
+    // SWB will be enabled by default
+    private boolean isSwbEnabled = true;
+    // SWB-PM will be enabled by default
+    private boolean isSwbPmEnabled = true;
 
     static {
         classInitNative();
@@ -87,6 +92,10 @@
         Log.d(TAG,"a2dpOffloadCap: " + a2dpOffloadCap);
         splitA2dpEnabled = isSplitA2dpEnabledNative();
         Log.d(TAG,"splitA2dpEnabled: " + splitA2dpEnabled);
+        isSwbEnabled = isSwbEnabledNative();
+        Log.d(TAG,"isSwbEnabled: " + isSwbEnabled);
+        isSwbPmEnabled = isSwbPmEnabledNative();
+        Log.d(TAG,"isSwbPmEnabled: " + isSwbPmEnabled);
     }
 
     public void bredrCleanup() {
@@ -102,6 +111,20 @@
         setWifiStateNative(status);
     }
 
+   public void setPowerBackoff(boolean status) {
+
+        if (getPowerBackoff() == status)
+            return;
+        Log.d(TAG,"setPowerBackoff to: " + status);
+        PowerbackoffStatus = status;
+        setPowerBackoffNative(status);
+    }
+
+   public boolean getPowerBackoff() {
+        Log.d(TAG,"getPowerBackoff " );
+        return PowerbackoffStatus;
+    }
+
     public void HCIClose() {
         hcicloseNative();
     }
@@ -240,12 +263,19 @@
     public boolean isSplitA2dpEnabled() {
         return splitA2dpEnabled;
     }
+    public boolean isSwbEnabled() {
+        return isSwbEnabled;
+    }
+    public boolean isSwbPmEnabled() {
+        return isSwbPmEnabled;
+    }
     private native void bredrcleanupNative();
     private native void bredrstartupNative();
     private native void initNative();
     private native static void classInitNative();
     private native void cleanupNative();
     private native void setWifiStateNative(boolean status);
+    private native void setPowerBackoffNative(boolean status);
     private native boolean getProfileInfoNative(int profile_id , int profile_info);
     private native boolean getQtiStackStatusNative();
     private native boolean voipNetworkWifiInfoNative(boolean isVoipStarted, boolean isNetworkWifi);
@@ -253,4 +283,6 @@
     private native String getSocNameNative();
     private native String getA2apOffloadCapabilityNative();
     private native boolean isSplitA2dpEnabledNative();
+    private native boolean isSwbEnabledNative();
+    private native boolean isSwbPmEnabledNative();
 }
diff --git a/packages_apps_bluetooth_ext/src/hfp/vendorhfservice.java b/packages_apps_bluetooth_ext/src/hfp/vendorhfservice.java
index e34999a..aab40ef 100644
--- a/packages_apps_bluetooth_ext/src/hfp/vendorhfservice.java
+++ b/packages_apps_bluetooth_ext/src/hfp/vendorhfservice.java
@@ -68,8 +68,15 @@
     }
 
     private void onSWB(int codec, byte[] address) {
-        /*HeadsetStackEvent event =
+        HeadsetStackEvent event =
                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_SWB, codec, getDevice(address));
+        sendMessageToService(event);
+    }
+
+    private void onTwsBatteryStateCallback(String atString, byte[] address) {
+        /*HeadsetStackEvent event = new HeadsetStackEvent(
+                HeadsetStackEvent.EVENT_TYPE_TWSP_BATTERY_STATE, atString,
+                getDevice(address));
         sendMessageToService(event);*/
     }
 
diff --git a/system_bt_ext/bta/Android.bp b/system_bt_ext/bta/Android.bp
index b87a3ac..1113dc1 100644
--- a/system_bt_ext/bta/Android.bp
+++ b/system_bt_ext/bta/Android.bp
@@ -2,7 +2,7 @@
 // ========================================================
 cc_library_static {
     name: "libbt-bta-ext",
-    defaults: ["fluoride_defaults"],
+    defaults: ["fluoride_defaults_qti"],
     include_dirs: [
         "vendor/qcom/opensource/commonsys/system/bt",
         "vendor/qcom/opensource/commonsys/system/bt/btcore/include",
@@ -40,7 +40,4 @@
         "libbt-utils",
     ],
     cflags: ["-DBUILDCFG"],
-    sanitize: {
-        never: true,
-    },
 }
diff --git a/system_bt_ext/bta/include/bta_ag_twsp.h b/system_bt_ext/bta/include/bta_ag_twsp.h
index bd4d960..c9cfd95 100644
--- a/system_bt_ext/bta/include/bta_ag_twsp.h
+++ b/system_bt_ext/bta/include/bta_ag_twsp.h
@@ -34,6 +34,7 @@
 #ifndef _BTA_AG_TWS_H_
 #define _BTA_AG_TWS_H_
 
+#include "btif_twsp_hf.h"
 #include "bta_ag_int.h"
 
 #define VS_QHCI_TWS_ESCO_SETUP_OPCODE 0x0D
diff --git a/system_bt_ext/bta/include/bta_ag_twsp_dev.h b/system_bt_ext/bta/include/bta_ag_twsp_dev.h
index c1e2b23..fb6f5b5 100644
--- a/system_bt_ext/bta/include/bta_ag_twsp_dev.h
+++ b/system_bt_ext/bta/include/bta_ag_twsp_dev.h
@@ -47,6 +47,9 @@
 #define TWSPLUS_MIN_BATTERY_CHARGE_STATE_POWERFAULT 2
 #define TWSPLUS_MAX_BATTERY_CHARGE 255
 
+#define TWSPLUS_MIN_BATTERY_LEVEL 0
+#define TWSPLUS_MAX_BATTERY_LEVEL 100
+
 #define TWSPLUS_INVALID_MICPATH_DELAY  (-1)
 #define TWSPLUS_MAX_MICPATH_DELAY   (65535)
 #define TWSPLUS_MIN_MICPATH_DELAY  (0)
@@ -82,7 +85,8 @@
 typedef struct {
    tBTA_AG_SCB *p_scb;
    uint8_t mic_quality;
-   uint8_t battery_charge;
+   uint16_t battery_state;
+   uint16_t battery_level;
    uint8_t state;
    int16_t mic_path_delay;
    uint8_t role;
@@ -91,8 +95,9 @@
    uint8_t ring_sent;
 } tTWSPLUS_DEVICE;
 
-void twsp_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd, int16_t int_arg);
 void update_twsp_device(tBTA_AG_SCB* p_scb);
+void twsp_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd,
+                                    tBTA_AG_VAL* val , int16_t int_arg);
 void reset_twsp_device(int eb_idx);
 bool twsp_set_ring_sent(tBTA_AG_SCB *p_scb, bool ring_sent);
 void twsp_clr_all_ring_sent();
diff --git a/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_dev.cc b/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_dev.cc
index 11642e3..d2c25c4 100644
--- a/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_dev.cc
+++ b/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_dev.cc
@@ -37,6 +37,7 @@
 #include "bta_ag_twsp.h"
 #include "internal_include/bt_trace.h"
 #include "bta_ag_int.h"
+#include "utl.h"
 
 
 #if (TWS_AG_ENABLED == TRUE)
@@ -94,15 +95,16 @@
         }
      }
 
-    twsp_devices[eb_idx].p_scb = NULL;
-    twsp_devices[eb_idx].battery_charge = TWSPLUS_MIN_BATTERY_CHARGE;
-    twsp_devices[eb_idx].state = TWSPLUS_EB_STATE_UNKNOWN;
-    twsp_devices[eb_idx].role =  TWSPLUS_EB_ROLE_INVALID;
-    twsp_devices[eb_idx].mic_path_delay = TWSPLUS_INVALID_MICPATH_DELAY;
-    twsp_devices[eb_idx].mic_quality = TWSPLUS_MIN_MIC_QUALITY;
-    twsp_devices[eb_idx].qdsp_nr = TWSPLUS_INVALID_QDSP_VALUE;
-    twsp_devices[eb_idx].qdsp_ec = TWSPLUS_INVALID_QDSP_VALUE;
-    twsp_devices[eb_idx].ring_sent = false;
+     twsp_devices[eb_idx].p_scb = NULL;
+     twsp_devices[eb_idx].battery_state = TWSPLUS_MIN_BATTERY_CHARGE_STATE_DISCHARGING;
+     twsp_devices[eb_idx].battery_level = TWSPLUS_MIN_BATTERY_LEVEL;
+     twsp_devices[eb_idx].state = TWSPLUS_EB_STATE_OFF;
+     twsp_devices[eb_idx].role =  TWSPLUS_EB_ROLE_INVALID;
+     twsp_devices[eb_idx].mic_path_delay = TWSPLUS_INVALID_MICPATH_DELAY;
+     twsp_devices[eb_idx].mic_quality = TWSPLUS_MIN_MIC_QUALITY;
+     twsp_devices[eb_idx].qdsp_nr = TWSPLUS_INVALID_QDSP_VALUE;
+     twsp_devices[eb_idx].qdsp_ec = TWSPLUS_INVALID_QDSP_VALUE;
+     twsp_devices[eb_idx].ring_sent = false;
 }
 
 void update_twsp_device(tBTA_AG_SCB* p_scb) {
@@ -110,8 +112,10 @@
         if (twsp_devices[i].p_scb == NULL) {
             APPL_TRACE_WARNING("%s: idx: %d, p_scb: %x", __func__, i, p_scb);
             twsp_devices[i].p_scb = p_scb;
-            twsp_devices[i].battery_charge = TWSPLUS_MIN_BATTERY_CHARGE;
-            twsp_devices[i].state = TWSPLUS_EB_STATE_UNKNOWN;
+            twsp_devices[i].battery_state =
+                              TWSPLUS_MIN_BATTERY_CHARGE_STATE_DISCHARGING;
+            twsp_devices[i].battery_level = TWSPLUS_MIN_BATTERY_LEVEL;
+            twsp_devices[i].state = TWSPLUS_EB_STATE_OFF;
 
             int other_idx = (i == PRIMARY_EB_IDX) ? SECONDARY_EB_IDX : PRIMARY_EB_IDX;
             if (twsp_devices[other_idx].p_scb != NULL) {
@@ -156,8 +160,10 @@
     APPL_TRACE_DEBUG("%s: p_scb : %x", __func__, twsp_devices[eb_idx].p_scb);
     APPL_TRACE_DEBUG("%s: mic_quality : %d", __func__,
                                twsp_devices[eb_idx].mic_quality);
-    APPL_TRACE_DEBUG("%s: battery_charge : %d", __func__,
-                               twsp_devices[eb_idx].battery_charge);
+    APPL_TRACE_DEBUG("%s: battery_state : %d", __func__,
+                               twsp_devices[eb_idx].battery_state);
+    APPL_TRACE_DEBUG("%s: battery_level : %d", __func__,
+                               twsp_devices[eb_idx].battery_level);
     APPL_TRACE_DEBUG("%s: mic_path_delay : %d", __func__,
                                twsp_devices[eb_idx].mic_path_delay);
     APPL_TRACE_DEBUG("%s: state : %d", __func__, twsp_devices[eb_idx].state);
@@ -350,20 +356,26 @@
     return twsp_devices[eb_idx].qdsp_ec;
 }
 
-bool set_twsp_battery_charge(int eb_idx, uint8_t battery_charge) {
-    APPL_TRACE_DEBUG("%s: battery_charge : %d\n", __func__, battery_charge);
+bool set_twsp_battery_charge(int eb_idx, int16_t state, int16_t level) {
+    APPL_TRACE_DEBUG("%s: state : %d, level : %d\n", __func__, state, level);
 
     if (eb_idx < PRIMARY_EB_IDX || eb_idx > SECONDARY_EB_IDX) {
         APPL_TRACE_WARNING("%s: Invalid eb_idx: %d\n", __func__, eb_idx);
         return false;
     }
 
-    if (battery_charge < TWSPLUS_MIN_BATTERY_CHARGE || battery_charge > TWSPLUS_MAX_BATTERY_CHARGE) {
-        APPL_TRACE_WARNING("%s: Invalid battery_charge: %d\n", __func__, battery_charge);
+    if (state < TWSPLUS_MIN_BATTERY_CHARGE_STATE_CHARGING ||
+       state > TWSPLUS_MIN_BATTERY_CHARGE_STATE_POWERFAULT) {
+        APPL_TRACE_WARNING("%s: Invalid state: %d\n", __func__, state);
         return false;
     }
 
-    twsp_devices[eb_idx].battery_charge = battery_charge;
+    if (level < TWSPLUS_MIN_BATTERY_LEVEL ||
+       state > TWSPLUS_MAX_BATTERY_LEVEL) {
+        APPL_TRACE_WARNING("%s: Invalid level: %d\n", __func__, level);
+        return false;
+    }
+
     return true;
 }
 
@@ -578,10 +590,50 @@
     }
 }
 
-void twsp_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd, int16_t int_arg)
+bool bta_ag_twsp_parse_qbc(tBTA_AG_SCB* p_scb, char* p_s,
+                           int16_t *state, int16_t *level) {
+    int16_t n[2] = {-1, -1};
+    int i;
+    char* p;
+
+    for (i = 0; i < 2; i++) {
+        /* skip to comma delimiter */
+        for (p = p_s; *p != ',' && *p != 0; p++)
+        ;
+
+        /* get integer value */
+        *p = 0;
+        n[i] = utl_str2int(p_s);
+        p_s = p + 1;
+        if (p_s == 0) {
+            break;
+        }
+    }
+
+    /* process values */
+    if (n[0] < TWSPLUS_MIN_BATTERY_CHARGE_STATE_CHARGING ||
+      n[0] > TWSPLUS_MAX_BATTERY_CHARGE) {
+        APPL_TRACE_ERROR("%s: Invalid QBC state: %d", __func__, n[0]);
+        return false;
+    }
+
+    if (n[1] < TWSPLUS_MIN_BATTERY_CHARGE_STATE_CHARGING ||
+      n[1] > TWSPLUS_MAX_BATTERY_CHARGE) {
+        APPL_TRACE_ERROR("%s: Invalid QBC level: %d", __func__, n[1]);
+        return false;
+    }
+
+    *state = n[0];
+    *level = n[1];
+    return true;
+}
+
+void twsp_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd,
+                                    tBTA_AG_VAL* val, int16_t int_arg)
 {
     APPL_TRACE_DEBUG("%s: p_scb : %x cmd : %d", __func__, p_scb, cmd);
-
+    int16_t state, level;
+    char str_to_parse[BTA_AG_AT_MAX_LEN];
     int idx = twsp_get_idx_by_scb(p_scb);
     if (idx < 0) {
         APPL_TRACE_ERROR("%s: Invalid SCB handle: %x", __func__, p_scb);
@@ -591,24 +643,38 @@
 
     //bta_ag_send_ok(p_scb);
     switch(cmd) {
-       case BTA_AG_TWSP_AT_QMQ_EVT: {
-            set_twsp_mic_quality(idx, int_arg);
-       } break;
-       case BTA_AG_TWSP_AT_QES_EVT: {
-            set_twsp_state(idx, int_arg);
-       } break;
-       case BTA_AG_TWSP_AT_QER_EVT: {
+        case BTA_AG_TWSP_AT_QMQ_EVT: {
+           set_twsp_mic_quality(idx, int_arg);
+        } break;
+        case BTA_AG_TWSP_AT_QES_EVT: {
+           set_twsp_state(idx, int_arg);
+        } break;
+        case BTA_AG_TWSP_AT_QER_EVT: {
             set_twsp_role(idx, int_arg);
-       } break;
-       case BTA_AG_TWSP_AT_QBC_EVT: {
-            set_twsp_battery_charge(idx, int_arg);
-       } break;
-       case BTA_AG_TWSP_AT_QMD_EVT: {
+        } break;
+        case BTA_AG_TWSP_AT_QBC_EVT: {
+            strlcpy(str_to_parse, val->str, sizeof(str_to_parse));
+            int ret = bta_ag_twsp_parse_qbc(p_scb,
+                                   str_to_parse, &state, &level);
+            if (ret) {
+                APPL_TRACE_DEBUG("%s: QBC=%d, %d", __func__, state, level);
+                if(set_twsp_battery_charge(idx, state, level)) {
+                    //Generate cb to BTIF/JNI
+                    APPL_TRACE_DEBUG("%s: at_str : %s", __func__, val->str);
+                    (*bta_ag_cb.p_cback)
+                           ((tBTA_AG_EVT)BTA_AG_TWSP_BATTERY_UPDATE,
+                           (tBTA_AG *)val);
+                }
+            } else {
+                APPL_TRACE_ERROR("%s: Fail to parse QBC", __func__)
+            }
+        } break;
+        case BTA_AG_TWSP_AT_QMD_EVT: {
             set_twsp_mic_path_delay(idx, int_arg);
-       } break;
-       case BTA_AG_TWSP_AT_QDSP_EVT: {
+        } break;
+        case BTA_AG_TWSP_AT_QDSP_EVT: {
             set_twsp_qdsp_features(idx, int_arg);
-       } break;
+        } break;
     }
 }
 
diff --git a/system_bt_ext/btconfigstore/Android.bp b/system_bt_ext/btconfigstore/Android.bp
index c1de2b1..2c82531 100644
--- a/system_bt_ext/btconfigstore/Android.bp
+++ b/system_bt_ext/btconfigstore/Android.bp
@@ -33,7 +33,4 @@
     required: [
         "bt_configstore.conf",
     ],
-    sanitize: {
-        never: true,
-    },
 }
diff --git a/system_bt_ext/btif/Android.bp b/system_bt_ext/btif/Android.bp
index 59cfaf2..d2901ed 100644
--- a/system_bt_ext/btif/Android.bp
+++ b/system_bt_ext/btif/Android.bp
@@ -2,7 +2,7 @@
 // ========================================================
 cc_library_static {
     name: "libbtif_ext",
-    defaults: ["fluoride_defaults"],
+    defaults: ["fluoride_defaults_qti"],
     include_dirs: [
         "vendor/qcom/opensource/commonsys/system/bt",
         "vendor/qcom/opensource/commonsys/system/bt/btcore/include",
@@ -52,7 +52,5 @@
         "-DBUILDCFG",
         "-DHAS_NO_BDROID_BUILDCFG",
     ],
-    sanitize: {
-        never: true,
-    },
+
 }
diff --git a/system_bt_ext/btif/include/btif_twsp_hf.h b/system_bt_ext/btif/include/btif_twsp_hf.h
index 658312f..0b11ca9 100644
--- a/system_bt_ext/btif/include/btif_twsp_hf.h
+++ b/system_bt_ext/btif/include/btif_twsp_hf.h
@@ -32,6 +32,12 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#define BTA_AG_TWSP_BATTERY_UPDATE 255
+
+#include "bta_ag_api.h"
+
+void btif_handle_vendor_hf_events(uint16_t event, tBTA_AG* data,
+                                  RawAddress *bd_addr);
 namespace bluetooth {
 namespace headset {
 
diff --git a/system_bt_ext/btif/src/btif_vendor.cc b/system_bt_ext/btif/src/btif_vendor.cc
index 9d1f7f1..b5d0172 100644
--- a/system_bt_ext/btif/src/btif_vendor.cc
+++ b/system_bt_ext/btif/src/btif_vendor.cc
@@ -343,6 +343,12 @@
     BTA_DmSetWifiState(status);
 }
 
+static void set_Power_back_off_state(bool status)
+{
+    LOG_INFO(LOG_TAG,"setPowerBackOffState :%d ", status);
+    BTA_DmPowerBackOff(status);
+}
+
 static bool get_profile_info(profile_t profile, profile_info_t feature_name)
 {
     LOG_INFO(LOG_TAG,"get_profile_info :%d", profile);
@@ -456,6 +462,7 @@
     bredrcleanup,
     bredrstartup,
     set_wifi_state,
+    set_Power_back_off_state,
     get_profile_info,
     set_property_callouts,
     cleanup,
diff --git a/system_bt_ext/btif/src/btif_vendor_hf.cc b/system_bt_ext/btif/src/btif_vendor_hf.cc
index dc4895e..8468db9 100644
--- a/system_bt_ext/btif/src/btif_vendor_hf.cc
+++ b/system_bt_ext/btif/src/btif_vendor_hf.cc
@@ -39,6 +39,8 @@
 #define LOG_TAG "bt_btif_vendor_hf"
 
 #include <hardware/vendor_hf.h>
+#include "bta_ag_swb.h"
+#include "btif_twsp_hf.h"
 #include "btif_api.h"
 
 btvendor_hf_callbacks_t *bt_vendor_hf_callbacks = NULL;
@@ -85,8 +87,25 @@
     enable_swb,
 };
 
-void btif_handle_vendor_hf_events(uint16_t event, uint16_t swb_config, RawAddress *bd_addr) {
-    HAL_CBACK(bt_vendor_hf_callbacks, swb_codec_cb, swb_config, bd_addr);
+void btif_handle_vendor_hf_events(uint16_t event, tBTA_AG* data,
+                                  RawAddress *bd_addr) {
+    BTIF_TRACE_EVENT("%s: event: %d", __func__, event)
+    switch (event) {
+        case BTA_AG_SWB_EVT:
+            HAL_CBACK(bt_vendor_hf_callbacks, swb_codec_cb, data->val.num,
+                        bd_addr);
+            break;
+        case BTA_AG_AT_QCS_EVT:
+            HAL_CBACK(bt_vendor_hf_callbacks, swb_codec_cb, data->val.num,
+                        bd_addr);
+            break;
+        case BTA_AG_TWSP_BATTERY_UPDATE:
+            HAL_CBACK(bt_vendor_hf_callbacks, twsp_batt_status_cb,
+                        data->val.str, bd_addr);
+            break;
+        default:
+            BTIF_TRACE_EVENT("%s: unknown vendor hf event: %d", __func__,event);
+    }
 }
 
 bool get_swb_codec_status() {
diff --git a/system_bt_ext/conf/bt_profile.conf b/system_bt_ext/conf/bt_profile.conf
index ae9cdaf..8082534 100644
--- a/system_bt_ext/conf/bt_profile.conf
+++ b/system_bt_ext/conf/bt_profile.conf
@@ -7,6 +7,7 @@
 #   1.AVRCP
 #   2.PBAP
 #   3.MAP
+#   4.MAX_PWR
 #
 # ******************************* Start of config Database *******************
 #AVRCP profile and its configurable features
@@ -31,3 +32,14 @@
 map_email_support = true
 map_0104_support = true
 
+#Configurable BT MAX_PWR based on BT Technology
+#Host can specify different max. power for different Technology/packet type
+#Currently BR,EDR and BLE packet type are supported
+#Power value 0XFF is meant to disable the max power restriction for particular technology
+# BR_max_pow_support default value 0xFF
+# EDR_max_pow_support default value 0xFF
+# BLE_max_pow_support default value 0xFF
+[MAX_POW]
+#BR_max_pow_support = 0xFF
+#EDR_max_pow_support = 0xFF
+BLE_max_pow_support = 0x18
diff --git a/system_bt_ext/conf/interop_database.conf b/system_bt_ext/conf/interop_database.conf
index e53da04..1edf231 100644
--- a/system_bt_ext/conf/interop_database.conf
+++ b/system_bt_ext/conf/interop_database.conf
@@ -122,6 +122,7 @@
 D0:8A:55 = Address_Based
 48:F0:7B = Address_Based
 00:0A:08 = Address_Based
+00:11:2D = Address_Based
 
 # Some HID pointing devices have proven problematic behaviour if pairing is initiated with
 # them, resulting in no response for authentication request and ultimately resulting
diff --git a/system_bt_ext/device/Android.bp b/system_bt_ext/device/Android.bp
index 8a83a90..5fb1299 100644
--- a/system_bt_ext/device/Android.bp
+++ b/system_bt_ext/device/Android.bp
@@ -2,7 +2,7 @@
 // ========================================================
 cc_library_static {
     name: "libbtdevice_ext",
-    defaults: ["fluoride_defaults"],
+    defaults: ["fluoride_defaults_qti"],
     local_include_dirs: [
         "include",
     ],
@@ -28,7 +28,4 @@
         "libosi_qti",
         "libbluetooth-types",
     ],
-    sanitize: {
-        never: true,
-    },
 }
diff --git a/system_bt_ext/device/include/profile_config.h b/system_bt_ext/device/include/profile_config.h
index fa9e5cd..29fb026 100644
--- a/system_bt_ext/device/include/profile_config.h
+++ b/system_bt_ext/device/include/profile_config.h
@@ -35,4 +35,14 @@
 
 static const char PROFILE_CONFIG_MODULE[] = "profile_config_module";
 
+typedef struct {
+   uint8_t BR_max_pow_support;
+   uint8_t EDR_max_pow_support;
+   uint8_t BLE_max_pow_support;
+   bool BR_max_pow_feature = false;
+   bool EDR_max_pow_feature = false;
+   bool BLE_max_pow_feature = false;
+} max_pow_feature_t;
+
 extern bool profile_feature_fetch(const profile_t profile, profile_info_t feature_name);
+extern max_pow_feature_t max_radiated_power_fetch(const profile_t profile, profile_info_t feature_name);
diff --git a/system_bt_ext/device/src/profile_config.cc b/system_bt_ext/device/src/profile_config.cc
index ed1b0d8..a206fc8 100644
--- a/system_bt_ext/device/src/profile_config.cc
+++ b/system_bt_ext/device/src/profile_config.cc
@@ -96,6 +96,7 @@
     avrcp_feature_t avrcp_feature_entry;
     pbap_feature_t pbap_feature_entry;
     map_feature_t map_feature_entry;
+    max_pow_feature_t max_pow_feature_entry;
   } profile_feature_type;
 
 } profile_db_entry_t;
@@ -111,7 +112,7 @@
 
 // Interface functions
 bool profile_feature_fetch(const profile_t profile, profile_info_t feature_name);
-
+max_pow_feature_t max_radiated_power_fetch(const profile_t profile);
 
 static const char* profile_name_string_(const profile_t profile_name)
 {
@@ -119,6 +120,7 @@
     CASE_RETURN_STR(AVRCP_ID)
     CASE_RETURN_STR(PBAP_ID)
     CASE_RETURN_STR(MAP_ID)
+    CASE_RETURN_STR(MAX_POW_ID)
     CASE_RETURN_STR(END_OF_PROFILE_LIST)
   }
   return "UNKNOWN";
@@ -134,6 +136,9 @@
     CASE_RETURN_STR(MAP_EMAIL_SUPPORT)
     CASE_RETURN_STR(MAP_0104_SUPPORT)
     CASE_RETURN_STR(PBAP_0102_SUPPORT)
+    CASE_RETURN_STR(BR_MAX_POW_SUPPORT)
+    CASE_RETURN_STR(EDR_MAX_POW_SUPPORT)
+    CASE_RETURN_STR(BLE_MAX_POW_SUPPORT)
     CASE_RETURN_STR(END_OF_FEATURE_LIST)
   }
   return "UNKNOWN";
@@ -276,6 +281,58 @@
   }
 }
 
+max_pow_feature_t  max_radiated_power_fetch(const profile_t profile, profile_info_t feature_name)
+{
+  static max_pow_feature_t Tech_max_power = {0xFF, 0xFF, 0xFF, false, false, false};
+  assert(profile);
+  LOG_WARN(LOG_TAG, "max_radiated_power_fetch:profile %d", profile);
+
+  profile_db_entry_t *db_entry = profile_entry_fetch(profile);
+  if (db_entry == NULL) {
+    return Tech_max_power;
+  }
+
+  if (profile == MAX_POW_ID) {
+    switch (feature_name) {
+      case BR_MAX_POW_SUPPORT:
+      {
+        if (db_entry->profile_feature_type.max_pow_feature_entry.BR_max_pow_feature == true) {
+          Tech_max_power.BR_max_pow_feature = true;
+          Tech_max_power.BR_max_pow_support =
+             db_entry->profile_feature_type.max_pow_feature_entry.BR_max_pow_support;
+        }
+      }
+      break;
+      case EDR_MAX_POW_SUPPORT:
+      {
+        if (db_entry->profile_feature_type.max_pow_feature_entry.EDR_max_pow_feature == true) {
+          Tech_max_power.EDR_max_pow_feature = true;
+          Tech_max_power.EDR_max_pow_support =
+             db_entry->profile_feature_type.max_pow_feature_entry.EDR_max_pow_support;
+        }
+      }
+      break;
+      case BLE_MAX_POW_SUPPORT:
+      {
+        if (db_entry->profile_feature_type.max_pow_feature_entry.BLE_max_pow_feature == true) {
+          Tech_max_power.BLE_max_pow_feature = true;
+          Tech_max_power.BLE_max_pow_support =
+             db_entry->profile_feature_type.max_pow_feature_entry.BLE_max_pow_support;
+        }
+      }
+      break;
+      default:
+      {
+        LOG_WARN(LOG_TAG, "profile_feature_fetch:profile = %d , feature %d not found" , profile, feature_name);
+      }
+      break;
+    }
+  } else
+    LOG_WARN(LOG_TAG, "max_radiated_power_fetch:profile = %d" , profile);
+
+  return Tech_max_power;
+}
+
 bool profile_feature_fetch(const profile_t profile, profile_info_t feature_name)
 {
 
@@ -478,6 +535,77 @@
       profile_database_add_(entry);
     }
     break;
+    case MAX_POW_ID:
+    {
+      LOG_WARN(LOG_TAG, " MAX_POW_ID: key :: %s, value :: %s",
+                    key, value);
+      entry = profile_entry_fetch(MAX_POW_ID);
+      if (entry == NULL) {
+        entry = (profile_db_entry_t *)osi_calloc(sizeof(profile_db_entry_t));
+        entry->profile_id = (profile_t)profile_id;
+      }
+      switch (get_feature(key)) {
+        case BR_MAX_POW_SUPPORT:
+        {
+          uint8_t BR_pow;
+          char *e;
+
+          if ( strlen(key) != 18 ) {
+            LOG_WARN(LOG_TAG,
+            " ignoring %s due to invalid key in config file", key);
+            return false;
+          }
+
+          BR_pow = (uint8_t)strtoul(value, &e, 16);
+          LOG_WARN(LOG_TAG, " MAX_POW_ID: BR_pow :: %x",BR_pow);
+          entry->profile_feature_type.max_pow_feature_entry.BR_max_pow_feature = true;
+          entry->profile_feature_type.max_pow_feature_entry.BR_max_pow_support = BR_pow;
+        }
+        break;
+        case EDR_MAX_POW_SUPPORT:
+        {
+          uint8_t EDR_pow;
+          char *e;
+
+          if ( strlen(key) != 19 ) {
+            LOG_WARN(LOG_TAG,
+            " ignoring %s due to invalid key in config file", key);
+            return false;
+          }
+
+          EDR_pow = (uint8_t)strtoul(value, &e, 16);
+          LOG_WARN(LOG_TAG, " MAX_POW_ID: EDR_pow :: %x",EDR_pow);
+          entry->profile_feature_type.max_pow_feature_entry.EDR_max_pow_feature = true;
+          entry->profile_feature_type.max_pow_feature_entry.EDR_max_pow_support = EDR_pow;
+        }
+        break;
+        case BLE_MAX_POW_SUPPORT:
+        {
+          uint8_t BLE_pow;
+          char *e;
+
+          if ( strlen(key) != 19 ) {
+            LOG_WARN(LOG_TAG,
+            " ignoring %s due to invalid key in config file", key);
+            return false;
+          }
+
+          BLE_pow = (uint8_t)strtoul(value, &e, 16);
+          LOG_WARN(LOG_TAG, " MAX_POW_ID: BLE_pow :: %x",BLE_pow);
+          entry->profile_feature_type.max_pow_feature_entry.BLE_max_pow_feature = true;
+          entry->profile_feature_type.max_pow_feature_entry.BLE_max_pow_support = BLE_pow;
+
+        }
+        break;
+        default:
+        {
+          LOG_WARN(LOG_TAG,"%s is invalid key %s", __func__, key);
+        }
+        break;
+      }
+      profile_database_add_(entry);
+    }
+    break;
     default:
     {
       LOG_WARN(LOG_TAG,"%s is invalid profile entry %s", __func__, key);
diff --git a/system_bt_ext/osi/Android.bp b/system_bt_ext/osi/Android.bp
index 438e8fe..505c7fd 100644
--- a/system_bt_ext/osi/Android.bp
+++ b/system_bt_ext/osi/Android.bp
@@ -2,7 +2,7 @@
 // ========================================================
 cc_library_static {
     name: "libosi_ext",
-    defaults: ["fluoride_defaults"],
+    defaults: ["fluoride_defaults_qti"],
     include_dirs: [
         "vendor/qcom/opensource/commonsys/system/bt",
         "vendor/qcom/opensource/commonsys/system/bt/internal_include",
@@ -24,7 +24,4 @@
         "libbt-utils",
     ],
     cflags: ["-DBUILDCFG"],
-    sanitize: {
-        never: true,
-    },
 }
diff --git a/system_bt_ext/stack/Android.bp b/system_bt_ext/stack/Android.bp
index 97b18e6..047b7d9 100644
--- a/system_bt_ext/stack/Android.bp
+++ b/system_bt_ext/stack/Android.bp
@@ -2,7 +2,7 @@
 // ========================================================
 cc_library_static {
     name: "libbt-stack_ext",
-    defaults: ["fluoride_defaults"],
+    defaults: ["fluoride_defaults_qti"],
     local_include_dirs: [
         "btm",
         "include",
@@ -39,7 +39,4 @@
         "libcutils",
         "liblog",
     ],
-    sanitize: {
-        never: true,
-    },
 }
diff --git a/vhal/include/hardware/vendor.h b/vhal/include/hardware/vendor.h
index 2b6be6f..ccddf2d 100644
--- a/vhal/include/hardware/vendor.h
+++ b/vhal/include/hardware/vendor.h
@@ -64,6 +64,7 @@
   AVRCP_ID = 1,
   PBAP_ID,
   MAP_ID,
+  MAX_POW_ID,
   END_OF_PROFILE_LIST
 } profile_t;
 
@@ -76,6 +77,9 @@
  MAP_EMAIL_SUPPORT,
  PBAP_0102_SUPPORT,
  MAP_0104_SUPPORT,
+ BR_MAX_POW_SUPPORT,
+ EDR_MAX_POW_SUPPORT,
+ BLE_MAX_POW_SUPPORT,
  END_OF_FEATURE_LIST
  } profile_info_t;
 
@@ -188,6 +192,9 @@
     /** set wifi state */
     void (*set_wifi_state)(bool);
 
+    /** set Power_back_off state */
+    void (*set_Power_back_off_state)(bool);
+
     /** get profile info */
     bool (*get_profile_info)(profile_t, profile_info_t);
 
diff --git a/vhal/include/hardware/vendor_hf.h b/vhal/include/hardware/vendor_hf.h
index 6b07c5c..242561c 100644
--- a/vhal/include/hardware/vendor_hf.h
+++ b/vhal/include/hardware/vendor_hf.h
@@ -43,11 +43,14 @@
 /* SWB callback events */
 typedef void (* bt_swb_update_callback)(uint16_t swb_codec_config, RawAddress *bd_addr);
 
+typedef void (* bt_twsp_battery_status_callback)(char* at_string, RawAddress *bd_addr);
+
 /** BT-Vendor hf callback structure. */
 typedef struct {
     /** set to sizeof(BtVendorhfCallbacks) */
     size_t      size;
     bt_swb_update_callback  swb_codec_cb;
+    bt_twsp_battery_status_callback twsp_batt_status_cb;
 } btvendor_hf_callbacks_t;