1 package com.android.camera;
2 
3 import android.Manifest;
4 import android.app.Activity;
5 import android.app.Dialog;
6 import android.app.AlertDialog;
7 import android.app.KeyguardManager;
8 import android.content.BroadcastReceiver;
9 import android.content.Context;
10 import android.content.DialogInterface;
11 import android.content.Intent;
12 import android.content.IntentFilter;
13 import android.content.pm.PackageManager;
14 import android.os.Bundle;
15 import android.view.KeyEvent;
16 import android.view.Window;
17 import android.view.WindowManager;
18 import com.android.camera.app.CameraServicesImpl;
19 import com.android.camera.debug.Log;
20 import com.android.camera.settings.Keys;
21 import com.android.camera.settings.SettingsManager;
22 import com.android.camera.util.QuickActivity;
23 import com.android.camera2.R;
24 
25 /**
26  * Activity that shows permissions request dialogs and handles lack of critical permissions.
27  * TODO: Convert PermissionsActivity into a dialog to be emitted from
28  * CameraActivity as not to have to restart CameraActivity from
29  * scratch.
30  */
31 public class PermissionsActivity extends QuickActivity {
32     private static final Log.Tag TAG = new Log.Tag("PermissionsActivity");
33 
34     private static int PERMISSION_REQUEST_CODE = 1;
35     private static int RESULT_CODE_OK = 1;
36     private static int RESULT_CODE_FAILED = 2;
37 
38     private int mIndexPermissionRequestCamera;
39     private int mIndexPermissionRequestMicrophone;
40     private int mIndexPermissionRequestLocation;
41     private int mIndexPermissionRequestStorage;
42     private int mIndexPermissionRequestWriteStorage;
43     private boolean mShouldRequestCameraPermission;
44     private boolean mShouldRequestMicrophonePermission;
45     private boolean mShouldRequestLocationPermission;
46     private boolean mShouldRequestStoragePermission;
47     private boolean mShouldRequestWriteStoragePermission;
48     private int mNumPermissionsToRequest;
49     private boolean mFlagHasCameraPermission;
50     private boolean mFlagHasMicrophonePermission;
51     private boolean mFlagHasStoragePermission;
52     private boolean mFlagHasWriteStoragePermission;
53     private SettingsManager mSettingsManager;
54 
55     /**
56      * Close activity when secure app passes lock screen or screen turns
57      * off.
58      */
59     private final BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
60         @Override
61         public void onReceive(Context context, Intent intent) {
62           Log.v(TAG, "received intent, finishing: " + intent.getAction());
63           finish();
64         }
65     };
66 
67     @Override
onCreateTasks(Bundle savedInstanceState)68     protected void onCreateTasks(Bundle savedInstanceState) {
69         setContentView(R.layout.permissions);
70         mSettingsManager = CameraServicesImpl.instance().getSettingsManager();
71 
72         // Filter for screen off so that we can finish permissions activity
73         // when screen is off.
74         IntentFilter filter_screen_off = new IntentFilter(Intent.ACTION_SCREEN_OFF);
75         registerReceiver(mShutdownReceiver, filter_screen_off);
76 
77         // Filter for phone unlock so that we can finish permissions activity
78         // via this UI path:
79         //    1. from secure lock screen, user starts secure camera
80         //    2. user presses home button
81         //    3. user unlocks phone
82         IntentFilter filter_user_unlock = new IntentFilter(Intent.ACTION_USER_PRESENT);
83         registerReceiver(mShutdownReceiver, filter_user_unlock);
84 
85         Window win = getWindow();
86         if (isKeyguardLocked()) {
87             win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
88         } else {
89             win.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
90         }
91     }
92 
93     @Override
onResumeTasks()94     protected void onResumeTasks() {
95         mNumPermissionsToRequest = 0;
96         checkPermissions();
97     }
98 
99     @Override
onDestroyTasks()100     protected void onDestroyTasks() {
101         Log.v(TAG, "onDestroy: unregistering receivers");
102         unregisterReceiver(mShutdownReceiver);
103     }
104 
checkPermissions()105     private void checkPermissions() {
106         if (checkSelfPermission(Manifest.permission.CAMERA)
107                 != PackageManager.PERMISSION_GRANTED) {
108             mNumPermissionsToRequest++;
109             mShouldRequestCameraPermission = true;
110         } else {
111             mFlagHasCameraPermission = true;
112         }
113 
114         if (checkSelfPermission(Manifest.permission.RECORD_AUDIO)
115                 != PackageManager.PERMISSION_GRANTED) {
116             mNumPermissionsToRequest++;
117             mShouldRequestMicrophonePermission = true;
118         } else {
119             mFlagHasMicrophonePermission = true;
120         }
121 
122         if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
123                 != PackageManager.PERMISSION_GRANTED) {
124             mNumPermissionsToRequest++;
125             mShouldRequestStoragePermission = true;
126         } else {
127             mFlagHasStoragePermission = true;
128         }
129 
130         if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
131                 != PackageManager.PERMISSION_GRANTED) {
132             mNumPermissionsToRequest++;
133             mShouldRequestWriteStoragePermission = true;
134         } else {
135             mFlagHasWriteStoragePermission = true;
136         }
137 
138         if (mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL,
139             Keys.KEY_RECORD_LOCATION)
140                 && (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
141                 != PackageManager.PERMISSION_GRANTED)) {
142             mNumPermissionsToRequest++;
143             mShouldRequestLocationPermission = true;
144         }
145 
146         if (mNumPermissionsToRequest != 0) {
147             if (!isKeyguardLocked() && !mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL,
148                     Keys.KEY_HAS_SEEN_PERMISSIONS_DIALOGS)) {
149                 buildPermissionsRequest();
150             } else {
151                 // Permissions dialog has already been shown, or we're on
152                 // lockscreen, and we're still missing permissions.
153                 handlePermissionsFailure();
154             }
155         } else {
156             handlePermissionsSuccess();
157         }
158     }
159 
buildPermissionsRequest()160     private void buildPermissionsRequest() {
161         String[] permissionsToRequest = new String[mNumPermissionsToRequest];
162         int permissionsRequestIndex = 0;
163 
164         if (mShouldRequestCameraPermission) {
165             permissionsToRequest[permissionsRequestIndex] = Manifest.permission.CAMERA;
166             mIndexPermissionRequestCamera = permissionsRequestIndex;
167             permissionsRequestIndex++;
168         }
169         if (mShouldRequestMicrophonePermission) {
170             permissionsToRequest[permissionsRequestIndex] = Manifest.permission.RECORD_AUDIO;
171             mIndexPermissionRequestMicrophone = permissionsRequestIndex;
172             permissionsRequestIndex++;
173         }
174         if (mShouldRequestStoragePermission) {
175             permissionsToRequest[permissionsRequestIndex] = Manifest.permission.READ_EXTERNAL_STORAGE;
176             mIndexPermissionRequestStorage = permissionsRequestIndex;
177             permissionsRequestIndex++;
178         }
179         if (mShouldRequestWriteStoragePermission) {
180             permissionsToRequest[permissionsRequestIndex] = Manifest.permission.WRITE_EXTERNAL_STORAGE;
181             mIndexPermissionRequestWriteStorage = permissionsRequestIndex;
182             permissionsRequestIndex++;
183         }
184         if (mShouldRequestLocationPermission) {
185             permissionsToRequest[permissionsRequestIndex] = Manifest.permission.ACCESS_COARSE_LOCATION;
186             mIndexPermissionRequestLocation = permissionsRequestIndex;
187         }
188 
189         Log.v(TAG, "requestPermissions count: " + permissionsToRequest.length);
190         requestPermissions(permissionsToRequest, PERMISSION_REQUEST_CODE);
191     }
192 
193     @Override
onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)194     public void onRequestPermissionsResult(int requestCode,
195                                            String permissions[], int[] grantResults) {
196         Log.v(TAG, "onPermissionsResult counts: " + permissions.length + ":" + grantResults.length);
197         mSettingsManager.set(
198                 SettingsManager.SCOPE_GLOBAL,
199                 Keys.KEY_HAS_SEEN_PERMISSIONS_DIALOGS,
200                 true);
201 
202         if (mShouldRequestCameraPermission) {
203             if (grantResults.length > 0 && grantResults[mIndexPermissionRequestCamera] ==
204                     PackageManager.PERMISSION_GRANTED) {
205                 mFlagHasCameraPermission = true;
206             } else {
207                 handlePermissionsFailure();
208             }
209         }
210         if (mShouldRequestMicrophonePermission) {
211             if (grantResults.length > 0 && grantResults[mIndexPermissionRequestMicrophone] ==
212                     PackageManager.PERMISSION_GRANTED) {
213                 mFlagHasMicrophonePermission = true;
214             } else {
215                 handlePermissionsFailure();
216             }
217         }
218         if (mShouldRequestStoragePermission) {
219             if (grantResults.length > 0 && grantResults[mIndexPermissionRequestStorage] ==
220                     PackageManager.PERMISSION_GRANTED) {
221                 mFlagHasStoragePermission = true;
222             } else {
223                 handlePermissionsFailure();
224             }
225         }
226         if (mShouldRequestWriteStoragePermission) {
227             if (grantResults.length > 0 && grantResults[mIndexPermissionRequestWriteStorage] ==
228                     PackageManager.PERMISSION_GRANTED) {
229                 mFlagHasWriteStoragePermission = true;
230             } else {
231                 handlePermissionsFailure();
232             }
233         }
234 
235         if (mShouldRequestLocationPermission) {
236             if (grantResults.length > 0 && grantResults[mIndexPermissionRequestLocation] ==
237                     PackageManager.PERMISSION_GRANTED) {
238                 // Do nothing
239             } else {
240                 // Do nothing
241             }
242         }
243 
244         if (mFlagHasCameraPermission && mFlagHasMicrophonePermission &&
245                 mFlagHasStoragePermission && mFlagHasWriteStoragePermission) {
246             handlePermissionsSuccess();
247         }
248     }
249 
handlePermissionsSuccess()250     private void handlePermissionsSuccess() {
251         Intent intent = new Intent(this, CameraActivity.class);
252         startActivity(intent);
253         finish();
254     }
255 
handlePermissionsFailure()256     private void handlePermissionsFailure() {
257         new AlertDialog.Builder(this).setTitle(getResources().getString(R.string.camera_error_title))
258                 .setMessage(getResources().getString(R.string.error_permissions))
259                 .setCancelable(false)
260                 .setOnKeyListener(new Dialog.OnKeyListener() {
261                     @Override
262                     public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
263                         if (keyCode == KeyEvent.KEYCODE_BACK) {
264                             finish();
265                         }
266                         return true;
267                     }
268                 })
269                 .setPositiveButton(getResources().getString(R.string.dialog_dismiss),
270                         new DialogInterface.OnClickListener() {
271                     @Override
272                     public void onClick(DialogInterface dialog, int which) {
273                         finish();
274                     }
275                 })
276                 .show();
277     }
278 }
279