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