/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.bluetooth.btservice.storage;

import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProtoEnums;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.util.StatsLog;

import com.android.bluetooth.btservice.AdapterService;
import com.android.internal.annotations.VisibleForTesting;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 * The active device manager is responsible to handle a Room database
 * for Bluetooth persistent data.
 */
public class DatabaseManager {
    private static final boolean DBG = true;
    private static final boolean VERBOSE = true;
    private static final String TAG = "BluetoothDatabase";

    private AdapterService mAdapterService = null;
    private HandlerThread mHandlerThread = null;
    private Handler mHandler = null;
    private MetadataDatabase mDatabase = null;
    private boolean mMigratedFromSettingsGlobal = false;

    @VisibleForTesting
    final Map<String, Metadata> mMetadataCache = new HashMap<>();
    private final Semaphore mSemaphore = new Semaphore(1);

    private static final int LOAD_DATABASE_TIMEOUT = 500; // milliseconds
    private static final int MSG_LOAD_DATABASE = 0;
    private static final int MSG_UPDATE_DATABASE = 1;
    private static final int MSG_DELETE_DATABASE = 2;
    private static final int MSG_CLEAR_DATABASE = 100;
    private static final String LOCAL_STORAGE = "LocalStorage";

    /**
     * Constructor of the DatabaseManager
     */
    public DatabaseManager(AdapterService service) {
        mAdapterService = service;
    }

    class DatabaseHandler extends Handler {
        DatabaseHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_LOAD_DATABASE: {
                    synchronized (mDatabase) {
                        List<Metadata> list = mDatabase.load();
                        cacheMetadata(list);
                    }
                    break;
                }
                case MSG_UPDATE_DATABASE: {
                    Metadata data = (Metadata) msg.obj;
                    synchronized (mDatabase) {
                        mDatabase.insert(data);
                    }
                    break;
                }
                case MSG_DELETE_DATABASE: {
                    String address = (String) msg.obj;
                    synchronized (mDatabase) {
                        mDatabase.delete(address);
                    }
                    break;
                }
                case MSG_CLEAR_DATABASE: {
                    synchronized (mDatabase) {
                        mDatabase.deleteAll();
                    }
                    break;
                }
            }
        }
    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action == null) {
                Log.e(TAG, "Received intent with null action");
                return;
            }
            switch (action) {
                case BluetoothDevice.ACTION_BOND_STATE_CHANGED: {
                    int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                            BluetoothDevice.ERROR);
                    BluetoothDevice device =
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    Objects.requireNonNull(device,
                            "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE");
                    bondStateChanged(device, state);
                    break;
                }
                case BluetoothAdapter.ACTION_STATE_CHANGED: {
                    int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
                            BluetoothAdapter.STATE_OFF);
                    if (!mMigratedFromSettingsGlobal
                            && state == BluetoothAdapter.STATE_TURNING_ON) {
                        migrateSettingsGlobal();
                    }
                    break;
                }
            }
        }
    };

    void bondStateChanged(BluetoothDevice device, int state) {
        synchronized (mMetadataCache) {
            String address = device.getAddress();
            if (state != BluetoothDevice.BOND_NONE) {
                if (mMetadataCache.containsKey(address)) {
                    return;
                }
                createMetadata(address);
            } else {
                Metadata metadata = mMetadataCache.get(address);
                if (metadata != null) {
                    mMetadataCache.remove(address);
                    deleteDatabase(metadata);
                }
            }
        }
    }

    boolean isValidMetaKey(int key) {
        switch (key) {
            case BluetoothDevice.METADATA_MANUFACTURER_NAME:
            case BluetoothDevice.METADATA_MODEL_NAME:
            case BluetoothDevice.METADATA_SOFTWARE_VERSION:
            case BluetoothDevice.METADATA_HARDWARE_VERSION:
            case BluetoothDevice.METADATA_COMPANION_APP:
            case BluetoothDevice.METADATA_MAIN_ICON:
            case BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET:
            case BluetoothDevice.METADATA_UNTHETHERED_LEFT_ICON:
            case BluetoothDevice.METADATA_UNTHETHERED_RIGHT_ICON:
            case BluetoothDevice.METADATA_UNTHETHERED_CASE_ICON:
            case BluetoothDevice.METADATA_UNTHETHERED_LEFT_BATTERY:
            case BluetoothDevice.METADATA_UNTHETHERED_RIGHT_BATTERY:
            case BluetoothDevice.METADATA_UNTHETHERED_CASE_BATTERY:
            case BluetoothDevice.METADATA_UNTHETHERED_LEFT_CHARGING:
            case BluetoothDevice.METADATA_UNTHETHERED_RIGHT_CHARGING:
            case BluetoothDevice.METADATA_UNTHETHERED_CASE_CHARGING:
            case BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI:
                return true;
        }
        Log.w(TAG, "Invalid metadata key " + key);
        return false;
    }

    /**
     * Set customized metadata to database with requested key
     */
    @VisibleForTesting
    public boolean setCustomMeta(BluetoothDevice device, int key, String newValue) {
        synchronized (mMetadataCache) {
            if (device == null) {
                Log.e(TAG, "setCustomMeta: device is null");
                return false;
            }
            if (!isValidMetaKey(key)) {
                Log.e(TAG, "setCustomMeta: meta key invalid " + key);
                return false;
            }

            String address = device.getAddress();
            if (VERBOSE) {
                Log.d(TAG, "setCustomMeta: " + address + ", key=" + key);
            }
            if (!mMetadataCache.containsKey(address)) {
                createMetadata(address);
            }
            Metadata data = mMetadataCache.get(address);
            String oldValue = data.getCustomizedMeta(key);
            if (oldValue != null && oldValue.equals(newValue)) {
                if (VERBOSE) {
                    Log.d(TAG, "setCustomMeta: metadata not changed.");
                }
                return true;
            }
            logManufacturerInfo(device, key, newValue);
            data.setCustomizedMeta(key, newValue);

            updateDatabase(data);
            mAdapterService.metadataChanged(address, key, newValue);
            return true;
        }
    }

    /**
     * Get customized metadata from database with requested key
     */
    @VisibleForTesting
    public String getCustomMeta(BluetoothDevice device, int key) {
        synchronized (mMetadataCache) {
            if (device == null) {
                Log.e(TAG, "getCustomMeta: device is null");
                return null;
            }
            if (!isValidMetaKey(key)) {
                Log.e(TAG, "getCustomMeta: meta key invalid " + key);
                return null;
            }

            String address = device.getAddress();

            if (!mMetadataCache.containsKey(address)) {
                Log.e(TAG, "getCustomMeta: device " + address + " is not in cache");
                return null;
            }

            Metadata data = mMetadataCache.get(address);
            String value = data.getCustomizedMeta(key);
            return value;
        }
    }

    /**
     * Set the device profile prioirty
     *
     * @param device {@link BluetoothDevice} wish to set
     * @param profile The Bluetooth profile; one of {@link BluetoothProfile#HEADSET},
     * {@link BluetoothProfile#HEADSET_CLIENT}, {@link BluetoothProfile#A2DP},
     * {@link BluetoothProfile#A2DP_SINK}, {@link BluetoothProfile#HID_HOST},
     * {@link BluetoothProfile#PAN}, {@link BluetoothProfile#PBAP},
     * {@link BluetoothProfile#MAP}, {@link BluetoothProfile#MAP_CLIENT},
     * {@link BluetoothProfile#SAP}, {@link BluetoothProfile#HEARING_AID}
     * @param newPriority the priority to set; one of
     * {@link BluetoothProfile#PRIORITY_UNDEFINED},
     * {@link BluetoothProfile#PRIORITY_OFF},
     * {@link BluetoothProfile#PRIORITY_ON},
     * {@link BluetoothProfile#PRIORITY_AUTO_CONNECT}
     */
    @VisibleForTesting
    public boolean setProfilePriority(BluetoothDevice device, int profile, int newPriority) {
        synchronized (mMetadataCache) {
            if (device == null) {
                Log.e(TAG, "setProfilePriority: device is null");
                return false;
            }

            if (newPriority != BluetoothProfile.PRIORITY_UNDEFINED
                    && newPriority != BluetoothProfile.PRIORITY_OFF
                    && newPriority != BluetoothProfile.PRIORITY_ON
                    && newPriority != BluetoothProfile.PRIORITY_AUTO_CONNECT) {
                Log.e(TAG, "setProfilePriority: invalid priority " + newPriority);
                return false;
            }

            String address = device.getAddress();
            if (VERBOSE) {
                Log.v(TAG, "setProfilePriority: " + address + ", profile=" + profile
                        + ", priority = " + newPriority);
            }
            if (!mMetadataCache.containsKey(address)) {
                if (newPriority == BluetoothProfile.PRIORITY_UNDEFINED) {
                    return true;
                }
                createMetadata(address);
            }
            Metadata data = mMetadataCache.get(address);
            int oldPriority = data.getProfilePriority(profile);
            if (oldPriority == newPriority) {
                if (VERBOSE) {
                    Log.v(TAG, "setProfilePriority priority not changed.");
                }
                return true;
            }

            data.setProfilePriority(profile, newPriority);
            updateDatabase(data);
            return true;
        }
    }

    /**
     * Get the device profile prioirty
     *
     * @param device {@link BluetoothDevice} wish to get
     * @param profile The Bluetooth profile; one of {@link BluetoothProfile#HEADSET},
     * {@link BluetoothProfile#HEADSET_CLIENT}, {@link BluetoothProfile#A2DP},
     * {@link BluetoothProfile#A2DP_SINK}, {@link BluetoothProfile#HID_HOST},
     * {@link BluetoothProfile#PAN}, {@link BluetoothProfile#PBAP},
     * {@link BluetoothProfile#MAP}, {@link BluetoothProfile#MAP_CLIENT},
     * {@link BluetoothProfile#SAP}, {@link BluetoothProfile#HEARING_AID}
     * @return the profile priority of the device; one of
     * {@link BluetoothProfile#PRIORITY_UNDEFINED},
     * {@link BluetoothProfile#PRIORITY_OFF},
     * {@link BluetoothProfile#PRIORITY_ON},
     * {@link BluetoothProfile#PRIORITY_AUTO_CONNECT}
     */
    @VisibleForTesting
    public int getProfilePriority(BluetoothDevice device, int profile) {
        synchronized (mMetadataCache) {
            if (device == null) {
                Log.e(TAG, "getProfilePriority: device is null");
                return BluetoothProfile.PRIORITY_UNDEFINED;
            }

            String address = device.getAddress();

            if (!mMetadataCache.containsKey(address)) {
                Log.e(TAG, "getProfilePriority: device " + address + " is not in cache");
                return BluetoothProfile.PRIORITY_UNDEFINED;
            }

            Metadata data = mMetadataCache.get(address);
            int priority = data.getProfilePriority(profile);
            if (VERBOSE) {
                Log.v(TAG, "getProfilePriority: " + address + ", profile=" + profile
                        + ", priority = " + priority);
            }
            return priority;
        }
    }

    /**
     * Set the A2DP optional coedc support value
     *
     * @param device {@link BluetoothDevice} wish to set
     * @param newValue the new A2DP optional coedc support value, one of
     * {@link BluetoothA2dp#OPTIONAL_CODECS_SUPPORT_UNKNOWN},
     * {@link BluetoothA2dp#OPTIONAL_CODECS_NOT_SUPPORTED},
     * {@link BluetoothA2dp#OPTIONAL_CODECS_SUPPORTED}
     */
    @VisibleForTesting
    public void setA2dpSupportsOptionalCodecs(BluetoothDevice device, int newValue) {
        synchronized (mMetadataCache) {
            if (device == null) {
                Log.e(TAG, "setA2dpOptionalCodec: device is null");
                return;
            }
            if (newValue != BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN
                    && newValue != BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED
                    && newValue != BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED) {
                Log.e(TAG, "setA2dpSupportsOptionalCodecs: invalid value " + newValue);
                return;
            }

            String address = device.getAddress();

            if (!mMetadataCache.containsKey(address)) {
                return;
            }
            Metadata data = mMetadataCache.get(address);
            int oldValue = data.a2dpSupportsOptionalCodecs;
            if (oldValue == newValue) {
                return;
            }

            data.a2dpSupportsOptionalCodecs = newValue;
            updateDatabase(data);
        }
    }

    /**
     * Get the A2DP optional coedc support value
     *
     * @param device {@link BluetoothDevice} wish to get
     * @return the A2DP optional coedc support value, one of
     * {@link BluetoothA2dp#OPTIONAL_CODECS_SUPPORT_UNKNOWN},
     * {@link BluetoothA2dp#OPTIONAL_CODECS_NOT_SUPPORTED},
     * {@link BluetoothA2dp#OPTIONAL_CODECS_SUPPORTED},
     */
    @VisibleForTesting
    public int getA2dpSupportsOptionalCodecs(BluetoothDevice device) {
        synchronized (mMetadataCache) {
            if (device == null) {
                Log.e(TAG, "setA2dpOptionalCodec: device is null");
                return BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED;
            }

            String address = device.getAddress();

            if (!mMetadataCache.containsKey(address)) {
                Log.e(TAG, "getA2dpOptionalCodec: device " + address + " is not in cache");
                return BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED;
            }

            Metadata data = mMetadataCache.get(address);
            return data.a2dpSupportsOptionalCodecs;
        }
    }

    /**
     * Set the A2DP optional coedc enabled value
     *
     * @param device {@link BluetoothDevice} wish to set
     * @param newValue the new A2DP optional coedc enabled value, one of
     * {@link BluetoothA2dp#OPTIONAL_CODECS_PREF_UNKNOWN},
     * {@link BluetoothA2dp#OPTIONAL_CODECS_PREF_DISABLED},
     * {@link BluetoothA2dp#OPTIONAL_CODECS_PREF_ENABLED}
     */
    @VisibleForTesting
    public void setA2dpOptionalCodecsEnabled(BluetoothDevice device, int newValue) {
        synchronized (mMetadataCache) {
            if (device == null) {
                Log.e(TAG, "setA2dpOptionalCodecEnabled: device is null");
                return;
            }
            if (newValue != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN
                    && newValue != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED
                    && newValue != BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) {
                Log.e(TAG, "setA2dpOptionalCodecsEnabled: invalid value " + newValue);
                return;
            }

            String address = device.getAddress();

            if (!mMetadataCache.containsKey(address)) {
                return;
            }
            Metadata data = mMetadataCache.get(address);
            int oldValue = data.a2dpOptionalCodecsEnabled;
            if (oldValue == newValue) {
                return;
            }

            data.a2dpOptionalCodecsEnabled = newValue;
            updateDatabase(data);
        }
    }

    /**
     * Get the A2DP optional coedc enabled value
     *
     * @param device {@link BluetoothDevice} wish to get
     * @return the A2DP optional coedc enabled value, one of
     * {@link BluetoothA2dp#OPTIONAL_CODECS_PREF_UNKNOWN},
     * {@link BluetoothA2dp#OPTIONAL_CODECS_PREF_DISABLED},
     * {@link BluetoothA2dp#OPTIONAL_CODECS_PREF_ENABLED}
     */
    @VisibleForTesting
    public int getA2dpOptionalCodecsEnabled(BluetoothDevice device) {
        synchronized (mMetadataCache) {
            if (device == null) {
                Log.e(TAG, "getA2dpOptionalCodecEnabled: device is null");
                return BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED;
            }

            String address = device.getAddress();

            if (!mMetadataCache.containsKey(address)) {
                Log.e(TAG, "getA2dpOptionalCodecEnabled: device " + address + " is not in cache");
                return BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED;
            }

            Metadata data = mMetadataCache.get(address);
            return data.a2dpOptionalCodecsEnabled;
        }
    }

    /**
     * Get the {@link Looper} for the handler thread. This is used in testing and helper
     * objects
     *
     * @return {@link Looper} for the handler thread
     */
    @VisibleForTesting
    public Looper getHandlerLooper() {
        if (mHandlerThread == null) {
            return null;
        }
        return mHandlerThread.getLooper();
    }

    /**
     * Start and initialize the DatabaseManager
     *
     * @param database the Bluetooth storage {@link MetadataDatabase}
     */
    public void start(MetadataDatabase database) {
        if (DBG) {
            Log.d(TAG, "start()");
        }

        if (mAdapterService == null) {
            Log.e(TAG, "stat failed, mAdapterService is null.");
            return;
        }

        if (database == null) {
            Log.e(TAG, "stat failed, database is null.");
            return;
        }

        mDatabase = database;

        mHandlerThread = new HandlerThread("BluetoothDatabaseManager");
        mHandlerThread.start();
        mHandler = new DatabaseHandler(mHandlerThread.getLooper());

        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        mAdapterService.registerReceiver(mReceiver, filter);

        loadDatabase();
    }

    String getDatabaseAbsolutePath() {
        //TODO backup database when Bluetooth turn off and FOTA?
        return mAdapterService.getDatabasePath(MetadataDatabase.DATABASE_NAME)
                .getAbsolutePath();
    }

    /**
     * Clear all persistence data in database
     */
    public void factoryReset() {
        Log.w(TAG, "factoryReset");
        Message message = mHandler.obtainMessage(MSG_CLEAR_DATABASE);
        mHandler.sendMessage(message);
    }

    /**
     * Close and de-init the DatabaseManager
     */
    public void cleanup() {
        removeUnusedMetadata();
        mAdapterService.unregisterReceiver(mReceiver);
        if (mHandlerThread != null) {
            mHandlerThread.quit();
            mHandlerThread = null;
        }
        mMetadataCache.clear();
    }

    void createMetadata(String address) {
        if (VERBOSE) {
            Log.v(TAG, "createMetadata " + address);
        }
        Metadata data = new Metadata(address);
        mMetadataCache.put(address, data);
        updateDatabase(data);
    }

    @VisibleForTesting
    void removeUnusedMetadata() {
        BluetoothDevice[] bondedDevices = mAdapterService.getBondedDevices();
        synchronized (mMetadataCache) {
            mMetadataCache.forEach((address, metadata) -> {
                for (BluetoothDevice device : bondedDevices) {
                    if (!device.getAddress().equals(address)
                            && !address.equals(LOCAL_STORAGE)) {
                        // Report metadata change to null
                        List<Integer> list = metadata.getChangedCustomizedMeta();
                        for (int key : list) {
                            mAdapterService.metadataChanged(address, key, null);
                        }
                        Log.i(TAG, "remove unpaired device from database " + address);
                        deleteDatabase(mMetadataCache.get(address));
                    }
                }
            });
        }
    }

    void cacheMetadata(List<Metadata> list) {
        synchronized (mMetadataCache) {
            Log.i(TAG, "cacheMetadata");
            // Unlock the main thread.
            mSemaphore.release();

            if (!isMigrated(list)) {
                // Wait for data migrate from Settings Global
                mMigratedFromSettingsGlobal = false;
                return;
            }
            mMigratedFromSettingsGlobal = true;
            for (Metadata data : list) {
                String address = data.getAddress();
                if (VERBOSE) {
                    Log.v(TAG, "cacheMetadata: found device " + address);
                }
                mMetadataCache.put(address, data);
            }
            if (VERBOSE) {
                Log.v(TAG, "cacheMetadata: Database is ready");
            }
        }
    }

    boolean isMigrated(List<Metadata> list) {
        for (Metadata data : list) {
            String address = data.getAddress();
            if (address.equals(LOCAL_STORAGE) && data.migrated) {
                return true;
            }
        }
        return false;
    }

    void migrateSettingsGlobal() {
        Log.i(TAG, "migrateSettingGlobal");

        BluetoothDevice[] bondedDevices = mAdapterService.getBondedDevices();
        ContentResolver contentResolver = mAdapterService.getContentResolver();

        for (BluetoothDevice device : bondedDevices) {
            int a2dpPriority = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
                    BluetoothProfile.PRIORITY_UNDEFINED);
            int a2dpSinkPriority = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothA2dpSrcPriorityKey(device.getAddress()),
                    BluetoothProfile.PRIORITY_UNDEFINED);
            int hearingaidPriority = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothHearingAidPriorityKey(device.getAddress()),
                    BluetoothProfile.PRIORITY_UNDEFINED);
            int headsetPriority = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()),
                    BluetoothProfile.PRIORITY_UNDEFINED);
            int headsetClientPriority = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()),
                    BluetoothProfile.PRIORITY_UNDEFINED);
            int hidHostPriority = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothHidHostPriorityKey(device.getAddress()),
                    BluetoothProfile.PRIORITY_UNDEFINED);
            int mapPriority = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothMapPriorityKey(device.getAddress()),
                    BluetoothProfile.PRIORITY_UNDEFINED);
            int mapClientPriority = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothMapClientPriorityKey(device.getAddress()),
                    BluetoothProfile.PRIORITY_UNDEFINED);
            int panPriority = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothPanPriorityKey(device.getAddress()),
                    BluetoothProfile.PRIORITY_UNDEFINED);
            int pbapPriority = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothPbapClientPriorityKey(device.getAddress()),
                    BluetoothProfile.PRIORITY_UNDEFINED);
            int sapPriority = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothSapPriorityKey(device.getAddress()),
                    BluetoothProfile.PRIORITY_UNDEFINED);
            int a2dpSupportsOptionalCodec = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothA2dpSupportsOptionalCodecsKey(device.getAddress()),
                    BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
            int a2dpOptionalCodecEnabled = Settings.Global.getInt(contentResolver,
                    Settings.Global.getBluetoothA2dpOptionalCodecsEnabledKey(device.getAddress()),
                    BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);

            String address = device.getAddress();
            Metadata data = new Metadata(address);
            data.setProfilePriority(BluetoothProfile.A2DP, a2dpPriority);
            data.setProfilePriority(BluetoothProfile.A2DP_SINK, a2dpSinkPriority);
            data.setProfilePriority(BluetoothProfile.HEADSET, headsetPriority);
            data.setProfilePriority(BluetoothProfile.HEADSET_CLIENT, headsetClientPriority);
            data.setProfilePriority(BluetoothProfile.HID_HOST, hidHostPriority);
            data.setProfilePriority(BluetoothProfile.PAN, panPriority);
            data.setProfilePriority(BluetoothProfile.PBAP, pbapPriority);
            data.setProfilePriority(BluetoothProfile.MAP, mapPriority);
            data.setProfilePriority(BluetoothProfile.MAP_CLIENT, mapClientPriority);
            data.setProfilePriority(BluetoothProfile.SAP, sapPriority);
            data.setProfilePriority(BluetoothProfile.HEARING_AID, hearingaidPriority);
            data.a2dpSupportsOptionalCodecs = a2dpSupportsOptionalCodec;
            data.a2dpOptionalCodecsEnabled = a2dpOptionalCodecEnabled;
            mMetadataCache.put(address, data);
            updateDatabase(data);
        }

        // Mark database migrated from Settings Global
        Metadata localData = new Metadata(LOCAL_STORAGE);
        localData.migrated = true;
        mMetadataCache.put(LOCAL_STORAGE, localData);
        updateDatabase(localData);

        // Reload database after migration is completed
        loadDatabase();

    }

    private void loadDatabase() {
        if (DBG) {
            Log.d(TAG, "Load Database");
        }
        Message message = mHandler.obtainMessage(MSG_LOAD_DATABASE);
        mHandler.sendMessage(message);
        try {
            // Lock the thread until handler thread finish loading database.
            mSemaphore.tryAcquire(LOAD_DATABASE_TIMEOUT, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Log.e(TAG, "loadDatabase: semaphore acquire failed");
        }
    }

    private void updateDatabase(Metadata data) {
        if (data.getAddress() == null) {
            Log.e(TAG, "updateDatabase: address is null");
            return;
        }
        if (DBG) {
            Log.d(TAG, "updateDatabase " + data.getAddress());
        }
        Message message = mHandler.obtainMessage(MSG_UPDATE_DATABASE);
        message.obj = data;
        mHandler.sendMessage(message);
    }

    private void deleteDatabase(Metadata data) {
        if (data.getAddress() == null) {
            Log.e(TAG, "deleteDatabase: address is null");
            return;
        }
        Log.d(TAG, "deleteDatabase: " + data.getAddress());
        Message message = mHandler.obtainMessage(MSG_DELETE_DATABASE);
        message.obj = data.getAddress();
        mHandler.sendMessage(message);
    }

    private void logManufacturerInfo(BluetoothDevice device, int key, String value) {
        String callingApp = mAdapterService.getPackageManager().getNameForUid(
                Binder.getCallingUid());
        String manufacturerName = "";
        String modelName = "";
        String hardwareVersion = "";
        String softwareVersion = "";
        switch (key) {
            case BluetoothDevice.METADATA_MANUFACTURER_NAME:
                manufacturerName = value;
                break;
            case BluetoothDevice.METADATA_MODEL_NAME:
                modelName = value;
                break;
            case BluetoothDevice.METADATA_HARDWARE_VERSION:
                hardwareVersion = value;
                break;
            case BluetoothDevice.METADATA_SOFTWARE_VERSION:
                softwareVersion = value;
                break;
            default:
                // Do not log anything if metadata doesn't fall into above categories
                return;
        }
        StatsLog.write(StatsLog.BLUETOOTH_DEVICE_INFO_REPORTED,
                mAdapterService.obfuscateAddress(device),
                BluetoothProtoEnums.DEVICE_INFO_EXTERNAL, callingApp, manufacturerName, modelName,
                hardwareVersion, softwareVersion);
    }
}
