1 /* 2 * Copyright (C) 2019 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.car.developeroptions.bluetooth; 18 19 import android.app.settings.SettingsEnums; 20 import android.bluetooth.BluetoothDevice; 21 import android.bluetooth.BluetoothProfile; 22 import android.content.Context; 23 import android.content.DialogInterface; 24 import android.provider.Settings; 25 import android.util.Log; 26 import android.widget.Toast; 27 28 import androidx.annotation.VisibleForTesting; 29 import androidx.appcompat.app.AlertDialog; 30 31 import com.android.car.developeroptions.R; 32 import com.android.car.developeroptions.overlay.FeatureFactory; 33 import com.android.settingslib.bluetooth.BluetoothUtils; 34 import com.android.settingslib.bluetooth.BluetoothUtils.ErrorListener; 35 import com.android.settingslib.bluetooth.LocalBluetoothManager; 36 import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback; 37 38 /** 39 * Utils is a helper class that contains constants for various 40 * Android resource IDs, debug logging flags, and static methods 41 * for creating dialogs. 42 */ 43 public final class Utils { 44 45 private static final String TAG = "BluetoothUtils"; 46 47 static final boolean V = BluetoothUtils.V; // verbose logging 48 static final boolean D = BluetoothUtils.D; // regular logging 49 50 public static final int META_INT_ERROR = -1; 51 Utils()52 private Utils() { 53 } 54 getConnectionStateSummary(int connectionState)55 public static int getConnectionStateSummary(int connectionState) { 56 switch (connectionState) { 57 case BluetoothProfile.STATE_CONNECTED: 58 return R.string.bluetooth_connected; 59 case BluetoothProfile.STATE_CONNECTING: 60 return R.string.bluetooth_connecting; 61 case BluetoothProfile.STATE_DISCONNECTED: 62 return R.string.bluetooth_disconnected; 63 case BluetoothProfile.STATE_DISCONNECTING: 64 return R.string.bluetooth_disconnecting; 65 default: 66 return 0; 67 } 68 } 69 70 // Create (or recycle existing) and show disconnect dialog. showDisconnectDialog(Context context, AlertDialog dialog, DialogInterface.OnClickListener disconnectListener, CharSequence title, CharSequence message)71 static AlertDialog showDisconnectDialog(Context context, 72 AlertDialog dialog, 73 DialogInterface.OnClickListener disconnectListener, 74 CharSequence title, CharSequence message) { 75 if (dialog == null) { 76 dialog = new AlertDialog.Builder(context) 77 .setPositiveButton(android.R.string.ok, disconnectListener) 78 .setNegativeButton(android.R.string.cancel, null) 79 .create(); 80 } else { 81 if (dialog.isShowing()) { 82 dialog.dismiss(); 83 } 84 // use disconnectListener for the correct profile(s) 85 CharSequence okText = context.getText(android.R.string.ok); 86 dialog.setButton(DialogInterface.BUTTON_POSITIVE, 87 okText, disconnectListener); 88 } 89 dialog.setTitle(title); 90 dialog.setMessage(message); 91 dialog.show(); 92 return dialog; 93 } 94 95 @VisibleForTesting showConnectingError(Context context, String name, LocalBluetoothManager manager)96 static void showConnectingError(Context context, String name, LocalBluetoothManager manager) { 97 FeatureFactory.getFactory(context).getMetricsFeatureProvider().visible(context, 98 SettingsEnums.PAGE_UNKNOWN, SettingsEnums.ACTION_SETTINGS_BLUETOOTH_CONNECT_ERROR, 99 0); 100 showError(context, name, R.string.bluetooth_connecting_error_message, manager); 101 } 102 showError(Context context, String name, int messageResId)103 static void showError(Context context, String name, int messageResId) { 104 showError(context, name, messageResId, getLocalBtManager(context)); 105 } 106 showError(Context context, String name, int messageResId, LocalBluetoothManager manager)107 private static void showError(Context context, String name, int messageResId, 108 LocalBluetoothManager manager) { 109 String message = context.getString(messageResId, name); 110 Context activity = manager.getForegroundActivity(); 111 if (manager.isForegroundActivity()) { 112 try { 113 new AlertDialog.Builder(activity) 114 .setTitle(R.string.bluetooth_error_title) 115 .setMessage(message) 116 .setPositiveButton(android.R.string.ok, null) 117 .show(); 118 } catch (Exception e) { 119 Log.e(TAG, "Cannot show error dialog.", e); 120 } 121 } else { 122 Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); 123 } 124 } 125 getLocalBtManager(Context context)126 public static LocalBluetoothManager getLocalBtManager(Context context) { 127 return LocalBluetoothManager.getInstance(context, mOnInitCallback); 128 } 129 createRemoteName(Context context, BluetoothDevice device)130 public static String createRemoteName(Context context, BluetoothDevice device) { 131 String mRemoteName = device != null ? device.getAlias() : null; 132 133 if (mRemoteName == null) { 134 mRemoteName = context.getString(R.string.unknown); 135 } 136 return mRemoteName; 137 } 138 139 private static final ErrorListener mErrorListener = new ErrorListener() { 140 @Override 141 public void onShowError(Context context, String name, int messageResId) { 142 showError(context, name, messageResId); 143 } 144 }; 145 146 private static final BluetoothManagerCallback mOnInitCallback = new BluetoothManagerCallback() { 147 @Override 148 public void onBluetoothManagerInitialized(Context appContext, 149 LocalBluetoothManager bluetoothManager) { 150 BluetoothUtils.setErrorListener(mErrorListener); 151 } 152 }; 153 isBluetoothScanningEnabled(Context context)154 public static boolean isBluetoothScanningEnabled(Context context) { 155 return Settings.Global.getInt(context.getContentResolver(), 156 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1; 157 } 158 getBooleanMetaData(BluetoothDevice bluetoothDevice, int key)159 public static boolean getBooleanMetaData(BluetoothDevice bluetoothDevice, int key) { 160 if (bluetoothDevice == null) { 161 return false; 162 } 163 164 return Boolean.parseBoolean("false"); 165 } 166 getStringMetaData(BluetoothDevice bluetoothDevice, int key)167 public static String getStringMetaData(BluetoothDevice bluetoothDevice, int key) { 168 if (bluetoothDevice == null) { 169 return null; 170 } 171 return ""; 172 } 173 getIntMetaData(BluetoothDevice bluetoothDevice, int key)174 public static int getIntMetaData(BluetoothDevice bluetoothDevice, int key) { 175 if (bluetoothDevice == null) { 176 return META_INT_ERROR; 177 } 178 try { 179 return Integer.parseInt(""); 180 } catch (NumberFormatException e) { 181 return META_INT_ERROR; 182 } 183 } 184 } 185