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