• 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 static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
20 
21 import android.bluetooth.BluetoothDevice;
22 import android.content.BroadcastReceiver;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.os.Bundle;
28 import android.telephony.TelephonyManager;
29 import android.util.Log;
30 import android.view.View;
31 import android.widget.Button;
32 import android.widget.TextView;
33 
34 import androidx.preference.Preference;
35 
36 import com.android.internal.annotations.VisibleForTesting;
37 import com.android.internal.app.AlertActivity;
38 import com.android.internal.app.AlertController;
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 
57     private int mRequestType = 0;
58     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
59         @Override
60         public void onReceive(Context context, Intent intent) {
61             String action = intent.getAction();
62             if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL)) {
63                 int requestType = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
64                         BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
65                 if (requestType != mRequestType) return;
66                 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
67                 if (mDevice.equals(device)) dismissDialog();
68             }
69         }
70     };
71     private boolean mReceiverRegistered = false;
72 
dismissDialog()73     private void dismissDialog() {
74         this.dismiss();
75     }
76 
77     @Override
onCreate(Bundle savedInstanceState)78     protected void onCreate(Bundle savedInstanceState) {
79         super.onCreate(savedInstanceState);
80 
81         getWindow().addPrivateFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
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         mRequestType = i.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
93                                      BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
94 
95         if(DEBUG) Log.i(TAG, "onCreate() Request type: " + mRequestType);
96 
97         if (mRequestType == BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION) {
98             showDialog(getString(R.string.bluetooth_connect_access_dialog_title), mRequestType);
99         } else if (mRequestType == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS) {
100             showDialog(getString(R.string.bluetooth_phonebook_access_dialog_title), mRequestType);
101         } else if (mRequestType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) {
102             showDialog(getString(R.string.bluetooth_message_access_dialog_title), mRequestType);
103         } else if (mRequestType == BluetoothDevice.REQUEST_TYPE_SIM_ACCESS) {
104             showDialog(getString(R.string.bluetooth_sim_card_access_dialog_title), mRequestType);
105         }
106         else {
107             Log.e(TAG, "Error: bad request type: " + mRequestType);
108             finish();
109             return;
110         }
111         registerReceiver(mReceiver,
112                          new IntentFilter(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL));
113         mReceiverRegistered = true;
114     }
115 
116 
showDialog(String title, int requestType)117     private void showDialog(String title, int requestType)
118     {
119         final AlertController.AlertParams p = mAlertParams;
120         p.mTitle = title;
121         if(DEBUG) Log.i(TAG, "showDialog() Request type: " + mRequestType + " this: " + this);
122         switch(requestType)
123         {
124         case BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION:
125             p.mView = createConnectionDialogView();
126             break;
127         case BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS:
128             p.mView = createPhonebookDialogView();
129             break;
130         case BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS:
131             p.mView = createMapDialogView();
132             break;
133         case BluetoothDevice.REQUEST_TYPE_SIM_ACCESS:
134             p.mView = createSapDialogView();
135             break;
136         }
137         p.mPositiveButtonText = getString(
138                 requestType == BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION
139                         ? R.string.bluetooth_connect_access_dialog_positive : R.string.allow);
140         p.mPositiveButtonListener = this;
141         p.mNegativeButtonText = getString(
142                 requestType == BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION
143                         ? R.string.bluetooth_connect_access_dialog_negative
144                         : R.string.request_manage_bluetooth_permission_dont_allow);
145         p.mNegativeButtonListener = this;
146         mOkButton = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
147         setupAlert();
148 
149     }
150     @Override
onBackPressed()151     public void onBackPressed() {
152         /*we need an answer so ignore back button presses during auth */
153         if(DEBUG) Log.i(TAG, "Back button pressed! ignoring");
154         return;
155     }
156 
157     // TODO(edjee): createConnectionDialogView, createPhonebookDialogView and createMapDialogView
158     // are similar. Refactor them into one method.
159     // Also, the string resources bluetooth_remember_choice and bluetooth_pb_remember_choice should
160     // be removed.
createConnectionDialogView()161     private View createConnectionDialogView() {
162         String mRemoteName = Utils.createRemoteName(this, mDevice);
163         mView = getLayoutInflater().inflate(R.layout.bluetooth_access, null);
164         messageView = (TextView)mView.findViewById(R.id.message);
165         messageView.setText(getString(R.string.bluetooth_connect_access_dialog_content,
166                 mRemoteName, mRemoteName));
167         return mView;
168     }
169 
createPhonebookDialogView()170     private View createPhonebookDialogView() {
171         String mRemoteName = Utils.createRemoteName(this, mDevice);
172         mView = getLayoutInflater().inflate(R.layout.bluetooth_access, null);
173         messageView = (TextView)mView.findViewById(R.id.message);
174         messageView.setText(getString(R.string.bluetooth_phonebook_access_dialog_content,
175                 mRemoteName, mRemoteName));
176         return mView;
177     }
178 
createMapDialogView()179     private View createMapDialogView() {
180         String mRemoteName = Utils.createRemoteName(this, mDevice);
181         mView = getLayoutInflater().inflate(R.layout.bluetooth_access, null);
182         messageView = (TextView)mView.findViewById(R.id.message);
183         messageView.setText(getString(R.string.bluetooth_message_access_dialog_content,
184                 mRemoteName, mRemoteName));
185         return mView;
186     }
187 
createSapDialogView()188     private View createSapDialogView() {
189         String mRemoteName = Utils.createRemoteName(this, mDevice);
190         TelephonyManager tm = getSystemService(TelephonyManager.class);
191         mView = getLayoutInflater().inflate(R.layout.bluetooth_access, null);
192         messageView = (TextView)mView.findViewById(R.id.message);
193         messageView.setText(getString(R.string.bluetooth_sim_card_access_dialog_content,
194                 mRemoteName, mRemoteName, tm.getLine1Number()));
195         return mView;
196     }
197 
onPositive()198     private void onPositive() {
199         if (DEBUG) Log.d(TAG, "onPositive");
200         sendReplyIntentToReceiver(true, true);
201         finish();
202     }
203 
onNegative()204     private void onNegative() {
205         if (DEBUG) Log.d(TAG, "onNegative");
206         sendReplyIntentToReceiver(false, true);
207     }
208 
209     @VisibleForTesting
sendReplyIntentToReceiver(final boolean allowed, final boolean always)210     void sendReplyIntentToReceiver(final boolean allowed, final boolean always) {
211         Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
212 
213         if (DEBUG) {
214             Log.i(TAG, "sendReplyIntentToReceiver() Request type: " + mRequestType
215                     + " mReturnPackage");
216         }
217 
218         intent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
219                         allowed ? BluetoothDevice.CONNECTION_ACCESS_YES
220                                 : BluetoothDevice.CONNECTION_ACCESS_NO);
221         intent.putExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, always);
222         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
223         intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, mRequestType);
224         sendBroadcast(intent, android.Manifest.permission.BLUETOOTH_CONNECT);
225     }
226 
onClick(DialogInterface dialog, int which)227     public void onClick(DialogInterface dialog, int which) {
228         switch (which) {
229             case DialogInterface.BUTTON_POSITIVE:
230                 onPositive();
231                 break;
232 
233             case DialogInterface.BUTTON_NEGATIVE:
234                 onNegative();
235                 break;
236             default:
237                 break;
238         }
239     }
240 
241     @Override
onDestroy()242     protected void onDestroy() {
243         super.onDestroy();
244         if (mReceiverRegistered) {
245             unregisterReceiver(mReceiver);
246             mReceiverRegistered = false;
247         }
248     }
249 
onPreferenceChange(Preference preference, Object newValue)250     public boolean onPreferenceChange(Preference preference, Object newValue) {
251         return true;
252     }
253 }
254