Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2011 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.bluetooth.BluetoothDevice;
     20 import android.content.BroadcastReceiver;
     21 import android.content.Context;
     22 import android.content.DialogInterface;
     23 import android.content.Intent;
     24 import android.content.IntentFilter;
     25 import android.os.Bundle;
     26 import android.preference.Preference;
     27 import android.util.Log;
     28 import android.view.View;
     29 import android.widget.CheckBox;
     30 import android.widget.CompoundButton;
     31 import android.widget.EditText;
     32 import android.widget.TextView;
     33 import android.widget.Button;
     34 import android.widget.CompoundButton.OnCheckedChangeListener;
     35 
     36 import com.android.internal.app.AlertActivity;
     37 import com.android.internal.app.AlertController;
     38 
     39 import com.android.settings.R;
     40 
     41 /**
     42  * BluetoothPermissionActivity shows a dialog for accepting incoming
     43  * profile connection request from untrusted devices.
     44  * It is also used to show a dialogue for accepting incoming phonebook
     45  * read request. The request could be initiated by PBAP PCE or by HF AT+CPBR.
     46  */
     47 public class BluetoothPermissionActivity extends AlertActivity implements
     48         DialogInterface.OnClickListener, Preference.OnPreferenceChangeListener {
     49     private static final String TAG = "BluetoothPermissionActivity";
     50     private static final boolean DEBUG = Utils.D;
     51 
     52     private View mView;
     53     private TextView messageView;
     54     private Button mOkButton;
     55     private BluetoothDevice mDevice;
     56     private String mReturnPackage = null;
     57     private String mReturnClass = null;
     58 
     59     private CheckBox mRememberChoice;
     60     private boolean mRememberChoiceValue = false;
     61 
     62     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
     63         @Override
     64         public void onReceive(Context context, Intent intent) {
     65             String action = intent.getAction();
     66             if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL)) {
     67                 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
     68                 if (mDevice.equals(device)) dismissDialog();
     69             }
     70         }
     71     };
     72     private boolean mReceiverRegistered = false;
     73 
     74     private void dismissDialog() {
     75         this.dismiss();
     76     }
     77 
     78     @Override
     79     protected void onCreate(Bundle savedInstanceState) {
     80         super.onCreate(savedInstanceState);
     81 
     82         Intent i = getIntent();
     83         String action = i.getAction();
     84         if (!action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST)) {
     85             Log.e(TAG, "Error: this activity may be started only with intent "
     86                   + "ACTION_CONNECTION_ACCESS_REQUEST");
     87             finish();
     88             return;
     89         }
     90 
     91         mDevice = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
     92         mReturnPackage = i.getStringExtra(BluetoothDevice.EXTRA_PACKAGE_NAME);
     93         mReturnClass = i.getStringExtra(BluetoothDevice.EXTRA_CLASS_NAME);
     94         int requestType = i.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
     95                                      BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
     96 
     97         if (requestType == BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION) {
     98             showConnectionDialog();
     99         } else if (requestType == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS) {
    100             showPhonebookDialog();
    101         } else {
    102             Log.e(TAG, "Error: bad request type: " + requestType);
    103             finish();
    104             return;
    105         }
    106         registerReceiver(mReceiver,
    107                          new IntentFilter(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL));
    108         mReceiverRegistered = true;
    109     }
    110 
    111     private void showConnectionDialog() {
    112         final AlertController.AlertParams p = mAlertParams;
    113         p.mIconId = android.R.drawable.ic_dialog_info;
    114         p.mTitle = getString(R.string.bluetooth_connection_permission_request);
    115         p.mView = createConnectionDialogView();
    116         p.mPositiveButtonText = getString(R.string.yes);
    117         p.mPositiveButtonListener = this;
    118         p.mNegativeButtonText = getString(R.string.no);
    119         p.mNegativeButtonListener = this;
    120         mOkButton = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
    121         setupAlert();
    122     }
    123 
    124     private void showPhonebookDialog() {
    125         final AlertController.AlertParams p = mAlertParams;
    126         p.mIconId = android.R.drawable.ic_dialog_info;
    127         p.mTitle = getString(R.string.bluetooth_phonebook_request);
    128         p.mView = createPhonebookDialogView();
    129         p.mPositiveButtonText = getString(android.R.string.yes);
    130         p.mPositiveButtonListener = this;
    131         p.mNegativeButtonText = getString(android.R.string.no);
    132         p.mNegativeButtonListener = this;
    133         mOkButton = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
    134         setupAlert();
    135     }
    136 
    137     private String createConnectionDisplayText() {
    138         String mRemoteName = mDevice != null ? mDevice.getAliasName() : null;
    139 
    140         if (mRemoteName == null) mRemoteName = getString(R.string.unknown);
    141         String mMessage1 = getString(R.string.bluetooth_connection_dialog_text,
    142                 mRemoteName);
    143         return mMessage1;
    144     }
    145 
    146     private String createPhonebookDisplayText() {
    147         String mRemoteName = mDevice != null ? mDevice.getAliasName() : null;
    148 
    149         if (mRemoteName == null) mRemoteName = getString(R.string.unknown);
    150         String mMessage1 = getString(R.string.bluetooth_pb_acceptance_dialog_text,
    151                                      mRemoteName, mRemoteName);
    152         return mMessage1;
    153     }
    154 
    155     private View createConnectionDialogView() {
    156         mView = getLayoutInflater().inflate(R.layout.bluetooth_connection_access, null);
    157         messageView = (TextView)mView.findViewById(R.id.message);
    158         messageView.setText(createConnectionDisplayText());
    159         return mView;
    160     }
    161 
    162     private View createPhonebookDialogView() {
    163         mView = getLayoutInflater().inflate(R.layout.bluetooth_pb_access, null);
    164         messageView = (TextView)mView.findViewById(R.id.message);
    165         messageView.setText(createPhonebookDisplayText());
    166         mRememberChoice = (CheckBox)mView.findViewById(R.id.bluetooth_pb_remember_choice);
    167         mRememberChoice.setChecked(false);
    168         mRememberChoice.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    169             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    170                 if (isChecked) {
    171                     mRememberChoiceValue = true;
    172                 } else {
    173                     mRememberChoiceValue = false;
    174                 }
    175             }
    176             });
    177         return mView;
    178     }
    179 
    180     private void onPositive() {
    181         if (DEBUG) Log.d(TAG, "onPositive mRememberChoiceValue: " + mRememberChoiceValue);
    182 
    183         if (mRememberChoiceValue) {
    184             savePhonebookPermissionChoice(CachedBluetoothDevice.PHONEBOOK_ACCESS_ALLOWED);
    185         }
    186         sendIntentToReceiver(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY, true,
    187                              BluetoothDevice.EXTRA_ALWAYS_ALLOWED, mRememberChoiceValue);
    188         finish();
    189     }
    190 
    191     private void onNegative() {
    192         if (DEBUG) Log.d(TAG, "onNegative mRememberChoiceValue: " + mRememberChoiceValue);
    193 
    194         if (mRememberChoiceValue) {
    195             savePhonebookPermissionChoice(CachedBluetoothDevice.PHONEBOOK_ACCESS_REJECTED);
    196         }
    197         sendIntentToReceiver(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY, false,
    198                              null, false // dummy value, no effect since last param is null
    199                              );
    200         finish();
    201     }
    202 
    203     private void sendIntentToReceiver(final String intentName, final boolean allowed,
    204                                       final String extraName, final boolean extraValue) {
    205         Intent intent = new Intent(intentName);
    206 
    207         if (mReturnPackage != null && mReturnClass != null) {
    208             intent.setClassName(mReturnPackage, mReturnClass);
    209         }
    210 
    211         intent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
    212                         allowed ? BluetoothDevice.CONNECTION_ACCESS_YES :
    213                                   BluetoothDevice.CONNECTION_ACCESS_NO);
    214 
    215         if (extraName != null) {
    216             intent.putExtra(extraName, extraValue);
    217         }
    218         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
    219         sendBroadcast(intent, android.Manifest.permission.BLUETOOTH_ADMIN);
    220     }
    221 
    222     public void onClick(DialogInterface dialog, int which) {
    223         switch (which) {
    224             case DialogInterface.BUTTON_POSITIVE:
    225                 onPositive();
    226                 break;
    227 
    228             case DialogInterface.BUTTON_NEGATIVE:
    229                 onNegative();
    230                 break;
    231             default:
    232                 break;
    233         }
    234     }
    235 
    236     @Override
    237     protected void onDestroy() {
    238         super.onDestroy();
    239         if (mReceiverRegistered) {
    240             unregisterReceiver(mReceiver);
    241             mReceiverRegistered = false;
    242         }
    243     }
    244 
    245     public boolean onPreferenceChange(Preference preference, Object newValue) {
    246         return true;
    247     }
    248 
    249     private void savePhonebookPermissionChoice(int permissionChoice) {
    250         LocalBluetoothManager bluetoothManager = LocalBluetoothManager.getInstance(this);
    251         CachedBluetoothDeviceManager cachedDeviceManager =
    252             bluetoothManager.getCachedDeviceManager();
    253         CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice);
    254         cachedDevice.setPhonebookPermissionChoice(permissionChoice);
    255     }
    256 }
    257