14f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng/*
24f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng * Copyright (C) 2018 The Android Open Source Project
34f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng *
44f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng * Licensed under the Apache License, Version 2.0 (the "License");
54f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng * you may not use this file except in compliance with the License.
64f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng * You may obtain a copy of the License at
74f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng *
84f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng *      http://www.apache.org/licenses/LICENSE-2.0
94f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng *
104f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng * Unless required by applicable law or agreed to in writing, software
114f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng * distributed under the License is distributed on an "AS IS" BASIS,
124f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng * See the License for the specific language governing permissions and
144f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng * limitations under the License.
154f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng */
164f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
174f636b90b8a41bfa3a57678e51d42547c1ba2229timhypengpackage com.android.settings.connecteddevice;
184f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
1978eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport android.bluetooth.BluetoothAdapter;
2078eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport android.content.BroadcastReceiver;
214f636b90b8a41bfa3a57678e51d42547c1ba2229timhypengimport android.content.Context;
2278eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport android.content.Intent;
2378eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport android.content.IntentFilter;
244f636b90b8a41bfa3a57678e51d42547c1ba2229timhypengimport android.content.pm.PackageManager;
254f636b90b8a41bfa3a57678e51d42547c1ba2229timhypengimport android.support.v7.preference.PreferenceScreen;
2678eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport android.text.BidiFormatter;
2778eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport android.text.TextUtils;
284f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
294f636b90b8a41bfa3a57678e51d42547c1ba2229timhypengimport com.android.internal.annotations.VisibleForTesting;
3078eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport com.android.settings.bluetooth.AlwaysDiscoverable;
3178eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport com.android.settings.bluetooth.Utils;
324f636b90b8a41bfa3a57678e51d42547c1ba2229timhypengimport com.android.settings.core.BasePreferenceController;
334f636b90b8a41bfa3a57678e51d42547c1ba2229timhypengimport com.android.settings.dashboard.DashboardFragment;
3478eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport com.android.settings.R;
3578eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport com.android.settingslib.bluetooth.LocalBluetoothAdapter;
3678eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport com.android.settingslib.bluetooth.LocalBluetoothManager;
3778eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport com.android.settingslib.core.lifecycle.events.OnPause;
3878eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport com.android.settingslib.core.lifecycle.events.OnResume;
3978eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengimport com.android.settingslib.core.lifecycle.LifecycleObserver;
404f636b90b8a41bfa3a57678e51d42547c1ba2229timhypengimport com.android.settingslib.widget.FooterPreference;
414f636b90b8a41bfa3a57678e51d42547c1ba2229timhypengimport com.android.settingslib.widget.FooterPreferenceMixin;
424f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
434f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng/**
444f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng * Controller that shows and updates the bluetooth device name
454f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng */
4678eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypengpublic class DiscoverableFooterPreferenceController extends BasePreferenceController
4778eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        implements LifecycleObserver, OnResume, OnPause {
484f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    private static final String KEY = "discoverable_footer_preference";
494f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
5078eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    @VisibleForTesting
5178eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    BroadcastReceiver mBluetoothChangedReceiver;
524f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    private FooterPreferenceMixin mFooterPreferenceMixin;
5378eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    private FooterPreference mPreference;
5478eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    private LocalBluetoothManager mLocalManager;
5578eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    private LocalBluetoothAdapter mLocalAdapter;
5678eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    private AlwaysDiscoverable mAlwaysDiscoverable;
574f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
5878eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    public DiscoverableFooterPreferenceController(Context context) {
5978eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        super(context, KEY);
6078eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        mLocalManager = Utils.getLocalBtManager(context);
6178eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        if (mLocalManager == null) {
6278eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng            return;
6378eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        }
6478eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        mLocalAdapter = mLocalManager.getBluetoothAdapter();
6578eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        mAlwaysDiscoverable = new AlwaysDiscoverable(context, mLocalAdapter);
6678eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        initReceiver();
6778eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    }
684f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
6978eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    private void initReceiver() {
7078eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        mBluetoothChangedReceiver = new BroadcastReceiver() {
7178eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng            @Override
7278eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng            public void onReceive(Context context, Intent intent) {
7378eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng                if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
7478eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng                    final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
7578eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng                            BluetoothAdapter.ERROR);
7678eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng                    updateFooterPreferenceTitle(state);
7778eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng                }
7878eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng            }
7978eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        };
8078eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    }
814f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
824f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    public void init(DashboardFragment fragment) {
834f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng        mFooterPreferenceMixin = new FooterPreferenceMixin(fragment, fragment.getLifecycle());
844f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    }
854f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
864f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    @VisibleForTesting
8778eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    void init(FooterPreferenceMixin footerPreferenceMixin, FooterPreference preference,
8878eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng            AlwaysDiscoverable alwaysDiscoverable) {
894f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng        mFooterPreferenceMixin = footerPreferenceMixin;
904f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng        mPreference = preference;
9178eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        mAlwaysDiscoverable = alwaysDiscoverable;
924f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    }
934f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
944f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    @Override
954f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    public void displayPreference(PreferenceScreen screen) {
964f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng        super.displayPreference(screen);
974f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng        addFooterPreference(screen);
984f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    }
994f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
1004f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    @Override
1014f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    public int getAvailabilityStatus() {
1024f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
1034f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng                ? AVAILABLE
1044f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng                : UNSUPPORTED_ON_DEVICE;
1054f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    }
1064f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng
1074f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    private void addFooterPreference(PreferenceScreen screen) {
1084f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng        mPreference = mFooterPreferenceMixin.createFooterPreference();
1094f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng        mPreference.setKey(KEY);
1104f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng        screen.addPreference(mPreference);
1114f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng    }
11278eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng
11378eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    @Override
11478eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    public void onResume() {
11578eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        mContext.registerReceiver(mBluetoothChangedReceiver,
11678eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng                new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
11778eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        mAlwaysDiscoverable.start();
11878eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        updateFooterPreferenceTitle(mLocalAdapter.getState());
11978eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    }
12078eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng
12178eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    @Override
12278eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    public void onPause() {
12378eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        mContext.unregisterReceiver(mBluetoothChangedReceiver);
12478eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        mAlwaysDiscoverable.stop();
12578eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    }
12678eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng
12778eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    private void updateFooterPreferenceTitle (int bluetoothState) {
12878eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        if (bluetoothState == BluetoothAdapter.STATE_ON) {
12978eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng            mPreference.setTitle(getPreferenceTitle());
13078eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        } else {
13178eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng            mPreference.setTitle(R.string.bluetooth_off_footer);
13278eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        }
13378eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    }
13478eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng
13578eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    private CharSequence getPreferenceTitle() {
13678eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        final String deviceName = mLocalAdapter.getName();
13778eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        if (TextUtils.isEmpty(deviceName)) {
13878eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng            return null;
13978eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        }
14078eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng
14178eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng        return TextUtils.expandTemplate(
14278eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng                mContext.getText(R.string.bluetooth_device_name_summary),
14378eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng                BidiFormatter.getInstance().unicodeWrap(deviceName));
14478eb5a81ba4b1236b6764a540546de3a84ca0c3ftimhypeng    }
1454f636b90b8a41bfa3a57678e51d42547c1ba2229timhypeng}