• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
dismissDialog()74     private void dismissDialog() {
75         this.dismiss();
76     }
77 
78     @Override
onCreate(Bundle savedInstanceState)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 
showConnectionDialog()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 
showPhonebookDialog()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 
createConnectionDisplayText()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 
createPhonebookDisplayText()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 
createConnectionDialogView()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 
createPhonebookDialogView()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 
onPositive()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 
onNegative()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 
sendIntentToReceiver(final String intentName, final boolean allowed, final String extraName, final boolean extraValue)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 
onClick(DialogInterface dialog, int which)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
onDestroy()237     protected void onDestroy() {
238         super.onDestroy();
239         if (mReceiverRegistered) {
240             unregisterReceiver(mReceiver);
241             mReceiverRegistered = false;
242         }
243     }
244 
onPreferenceChange(Preference preference, Object newValue)245     public boolean onPreferenceChange(Preference preference, Object newValue) {
246         return true;
247     }
248 
savePhonebookPermissionChoice(int permissionChoice)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         if (cachedDevice != null ) {
255             cachedDevice.setPhonebookPermissionChoice(permissionChoice);
256         } else {
257             cachedDevice = cachedDeviceManager.addDevice(bluetoothManager.getBluetoothAdapter(),
258                                                          bluetoothManager.getProfileManager(),
259                                                          mDevice);
260             cachedDevice.setPhonebookPermissionChoice(permissionChoice);
261         }
262     }
263 }
264