1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.bluetooth; 18 19 import android.annotation.Nullable; 20 import android.app.ActivityManager; 21 import android.bluetooth.BluetoothAdapter; 22 import android.bluetooth.BluetoothDevice; 23 import android.content.Context; 24 import android.content.SharedPreferences; 25 import android.content.res.Configuration; 26 import android.text.TextUtils; 27 import android.util.Log; 28 29 import com.android.settingslib.bluetooth.LocalBluetoothManager; 30 31 /** 32 * LocalBluetoothPreferences provides an interface to the preferences 33 * related to Bluetooth. 34 */ 35 final class LocalBluetoothPreferences { 36 private static final String TAG = "LocalBluetoothPreferences"; 37 private static final boolean DEBUG = Utils.D; 38 private static final String SHARED_PREFERENCES_NAME = "bluetooth_settings"; 39 40 // If a device was picked from the device picker or was in discoverable mode 41 // in the last 60 seconds, show the pairing dialogs in foreground instead 42 // of raising notifications 43 private static final int GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND = 60 * 1000; 44 45 private static final String KEY_LAST_SELECTED_DEVICE = "last_selected_device"; 46 47 private static final String KEY_LAST_SELECTED_DEVICE_TIME = "last_selected_device_time"; 48 49 private static final String KEY_DISCOVERABLE_END_TIMESTAMP = "discoverable_end_timestamp"; 50 LocalBluetoothPreferences()51 private LocalBluetoothPreferences() { 52 } 53 getSharedPreferences(Context context)54 private static SharedPreferences getSharedPreferences(Context context) { 55 return context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); 56 } 57 getDiscoverableEndTimestamp(Context context)58 static long getDiscoverableEndTimestamp(Context context) { 59 return getSharedPreferences(context).getLong( 60 KEY_DISCOVERABLE_END_TIMESTAMP, 0); 61 } 62 shouldShowDialogInForeground(Context context, @Nullable BluetoothDevice device)63 static boolean shouldShowDialogInForeground(Context context, @Nullable BluetoothDevice device) { 64 String deviceAddress = device != null ? device.getAddress() : null; 65 String deviceName = device != null ? device.getName() : null; 66 LocalBluetoothManager manager = Utils.getLocalBtManager(context); 67 if (manager == null) { 68 if (DEBUG) Log.v(TAG, "manager == null - do not show dialog."); 69 return false; 70 } 71 72 // If Bluetooth Settings is visible 73 if (manager.isForegroundActivity()) { 74 return true; 75 } 76 77 // If in appliance mode, do not show dialog in foreground. 78 if ((context.getResources().getConfiguration().uiMode & 79 Configuration.UI_MODE_TYPE_APPLIANCE) == Configuration.UI_MODE_TYPE_APPLIANCE) { 80 if (DEBUG) Log.v(TAG, "in appliance mode - do not show dialog."); 81 return false; 82 } 83 84 long currentTimeMillis = System.currentTimeMillis(); 85 SharedPreferences sharedPreferences = getSharedPreferences(context); 86 87 // If the device was in discoverABLE mode recently 88 long lastDiscoverableEndTime = sharedPreferences.getLong( 89 KEY_DISCOVERABLE_END_TIMESTAMP, 0); 90 if ((lastDiscoverableEndTime + GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND) 91 > currentTimeMillis) { 92 return true; 93 } 94 95 // If the device was discoverING recently 96 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 97 if (adapter != null) { 98 if (adapter.isDiscovering()) { 99 return true; 100 } 101 if ((adapter.getDiscoveryEndMillis() + 102 GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND) > currentTimeMillis) { 103 return true; 104 } 105 } 106 107 // If the device was picked in the device picker recently 108 if (deviceAddress != null) { 109 String lastSelectedDevice = sharedPreferences.getString( 110 KEY_LAST_SELECTED_DEVICE, null); 111 112 if (deviceAddress.equals(lastSelectedDevice)) { 113 long lastDeviceSelectedTime = sharedPreferences.getLong( 114 KEY_LAST_SELECTED_DEVICE_TIME, 0); 115 if ((lastDeviceSelectedTime + GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND) 116 > currentTimeMillis) { 117 return true; 118 } 119 } 120 } 121 122 123 if (!TextUtils.isEmpty(deviceName)) { 124 // If the device is a custom BT keyboard specifically for this device 125 String packagedKeyboardName = context.getString( 126 com.android.internal.R.string.config_packagedKeyboardName); 127 if (deviceName.equals(packagedKeyboardName)) { 128 if (DEBUG) Log.v(TAG, "showing dialog for packaged keyboard"); 129 return true; 130 } 131 } 132 133 if (device != null) { 134 ActivityManager activityManager = context.getSystemService(ActivityManager.class); 135 String packageName = device.getPackageNameOfBondingApplication(); 136 137 if (packageName != null && activityManager.getPackageImportance(packageName) 138 == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { 139 if (DEBUG) { 140 Log.v(TAG, "showing dialog because the initiating application " 141 + "is in foreground"); 142 } 143 return true; 144 } 145 } 146 147 if (DEBUG) Log.v(TAG, "Found no reason to show the dialog - do not show dialog."); 148 return false; 149 } 150 persistSelectedDeviceInPicker(Context context, String deviceAddress)151 static void persistSelectedDeviceInPicker(Context context, String deviceAddress) { 152 SharedPreferences.Editor editor = getSharedPreferences(context).edit(); 153 editor.putString(KEY_LAST_SELECTED_DEVICE, 154 deviceAddress); 155 editor.putLong(KEY_LAST_SELECTED_DEVICE_TIME, 156 System.currentTimeMillis()); 157 editor.apply(); 158 } 159 persistDiscoverableEndTimestamp(Context context, long endTimestamp)160 static void persistDiscoverableEndTimestamp(Context context, long endTimestamp) { 161 SharedPreferences.Editor editor = getSharedPreferences(context).edit(); 162 editor.putLong(KEY_DISCOVERABLE_END_TIMESTAMP, endTimestamp); 163 editor.apply(); 164 } 165 } 166