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 showError(context, name, R.string.bluetooth_connecting_error_message, manager); 100 } 101 showError(Context context, String name, int messageResId)102 static void showError(Context context, String name, int messageResId) { 103 showError(context, name, messageResId, getLocalBtManager(context)); 104 } 105 showError(Context context, String name, int messageResId, LocalBluetoothManager manager)106 private static void showError(Context context, String name, int messageResId, 107 LocalBluetoothManager manager) { 108 String message = context.getString(messageResId, name); 109 Context activity = manager.getForegroundActivity(); 110 if (manager.isForegroundActivity()) { 111 try { 112 new AlertDialog.Builder(activity) 113 .setTitle(R.string.bluetooth_error_title) 114 .setMessage(message) 115 .setPositiveButton(android.R.string.ok, null) 116 .show(); 117 } catch (Exception e) { 118 Log.e(TAG, "Cannot show error dialog.", e); 119 } 120 } else { 121 Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); 122 } 123 } 124 getLocalBtManager(Context context)125 public static LocalBluetoothManager getLocalBtManager(Context context) { 126 return LocalBluetoothManager.getInstance(context, mOnInitCallback); 127 } 128 createRemoteName(Context context, BluetoothDevice device)129 public static String createRemoteName(Context context, BluetoothDevice device) { 130 String mRemoteName = device != null ? device.getAlias() : null; 131 132 if (mRemoteName == null) { 133 mRemoteName = context.getString(R.string.unknown); 134 } 135 return mRemoteName; 136 } 137 138 private static final ErrorListener mErrorListener = new ErrorListener() { 139 @Override 140 public void onShowError(Context context, String name, int messageResId) { 141 showError(context, name, messageResId); 142 } 143 }; 144 145 private static final BluetoothManagerCallback mOnInitCallback = new BluetoothManagerCallback() { 146 @Override 147 public void onBluetoothManagerInitialized(Context appContext, 148 LocalBluetoothManager bluetoothManager) { 149 BluetoothUtils.setErrorListener(mErrorListener); 150 } 151 }; 152 isBluetoothScanningEnabled(Context context)153 public static boolean isBluetoothScanningEnabled(Context context) { 154 return Settings.Global.getInt(context.getContentResolver(), 155 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1; 156 } 157 getBooleanMetaData(BluetoothDevice bluetoothDevice, int key)158 public static boolean getBooleanMetaData(BluetoothDevice bluetoothDevice, int key) { 159 if (bluetoothDevice == null) { 160 return false; 161 } 162 163 return Boolean.parseBoolean("false"); 164 } 165 getStringMetaData(BluetoothDevice bluetoothDevice, int key)166 public static String getStringMetaData(BluetoothDevice bluetoothDevice, int key) { 167 if (bluetoothDevice == null) { 168 return null; 169 } 170 return ""; 171 } 172 getIntMetaData(BluetoothDevice bluetoothDevice, int key)173 public static int getIntMetaData(BluetoothDevice bluetoothDevice, int key) { 174 if (bluetoothDevice == null) { 175 return META_INT_ERROR; 176 } 177 try { 178 return Integer.parseInt(""); 179 } catch (NumberFormatException e) { 180 return META_INT_ERROR; 181 } 182 } 183 } 184