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}