1package com.android.camera;
2
3import android.Manifest;
4import android.app.Activity;
5import android.app.Dialog;
6import android.app.AlertDialog;
7import android.app.KeyguardManager;
8import android.content.BroadcastReceiver;
9import android.content.Context;
10import android.content.DialogInterface;
11import android.content.Intent;
12import android.content.IntentFilter;
13import android.content.pm.PackageManager;
14import android.os.Bundle;
15import android.view.KeyEvent;
16import android.view.Window;
17import android.view.WindowManager;
18import com.android.camera.app.CameraServicesImpl;
19import com.android.camera.debug.Log;
20import com.android.camera.settings.Keys;
21import com.android.camera.settings.SettingsManager;
22import com.android.camera.util.QuickActivity;
23import com.android.camera2.R;
24
25/**
26 * Activity that shows permissions request dialogs and handles lack of critical permissions.
27 */
28public 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
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
88    protected void onResumeTasks() {
89        mNumPermissionsToRequest = 0;
90        checkPermissions();
91    }
92
93    @Override
94    protected void onDestroyTasks() {
95        Log.v(TAG, "onDestroy: unregistering receivers");
96        unregisterReceiver(mShutdownReceiver);
97    }
98
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
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
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
220    private void handlePermissionsSuccess() {
221        Intent intent = new Intent(this, CameraActivity.class);
222        startActivity(intent);
223        finish();
224    }
225
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