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