package com.android.camera; import android.Manifest; import android.app.Activity; import android.app.Dialog; import android.app.AlertDialog; import android.app.KeyguardManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Bundle; import android.view.KeyEvent; import android.view.Window; import android.view.WindowManager; import com.android.camera.app.CameraServicesImpl; import com.android.camera.debug.Log; import com.android.camera.settings.Keys; import com.android.camera.settings.SettingsManager; import com.android.camera.util.QuickActivity; import com.android.camera2.R; /** * Activity that shows permissions request dialogs and handles lack of critical permissions. * TODO: Convert PermissionsActivity into a dialog to be emitted from * CameraActivity as not to have to restart CameraActivity from * scratch. */ public class PermissionsActivity extends QuickActivity { private static final Log.Tag TAG = new Log.Tag("PermissionsActivity"); private static int PERMISSION_REQUEST_CODE = 1; private static int RESULT_CODE_OK = 1; private static int RESULT_CODE_FAILED = 2; private int mIndexPermissionRequestCamera; private int mIndexPermissionRequestMicrophone; private int mIndexPermissionRequestLocation; private int mIndexPermissionRequestStorage; private int mIndexPermissionRequestWriteStorage; private boolean mShouldRequestCameraPermission; private boolean mShouldRequestMicrophonePermission; private boolean mShouldRequestLocationPermission; private boolean mShouldRequestStoragePermission; private boolean mShouldRequestWriteStoragePermission; private int mNumPermissionsToRequest; private boolean mFlagHasCameraPermission; private boolean mFlagHasMicrophonePermission; private boolean mFlagHasStoragePermission; private boolean mFlagHasWriteStoragePermission; private SettingsManager mSettingsManager; /** * Close activity when secure app passes lock screen or screen turns * off. */ private final BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.v(TAG, "received intent, finishing: " + intent.getAction()); finish(); } }; @Override protected void onCreateTasks(Bundle savedInstanceState) { setContentView(R.layout.permissions); mSettingsManager = CameraServicesImpl.instance().getSettingsManager(); // Filter for screen off so that we can finish permissions activity // when screen is off. IntentFilter filter_screen_off = new IntentFilter(Intent.ACTION_SCREEN_OFF); registerReceiver(mShutdownReceiver, filter_screen_off); // Filter for phone unlock so that we can finish permissions activity // via this UI path: // 1. from secure lock screen, user starts secure camera // 2. user presses home button // 3. user unlocks phone IntentFilter filter_user_unlock = new IntentFilter(Intent.ACTION_USER_PRESENT); registerReceiver(mShutdownReceiver, filter_user_unlock); Window win = getWindow(); if (isKeyguardLocked()) { win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); } else { win.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); } } @Override protected void onResumeTasks() { mNumPermissionsToRequest = 0; checkPermissions(); } @Override protected void onDestroyTasks() { Log.v(TAG, "onDestroy: unregistering receivers"); unregisterReceiver(mShutdownReceiver); } private void checkPermissions() { if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { mNumPermissionsToRequest++; mShouldRequestCameraPermission = true; } else { mFlagHasCameraPermission = true; } if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { mNumPermissionsToRequest++; mShouldRequestMicrophonePermission = true; } else { mFlagHasMicrophonePermission = true; } if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { mNumPermissionsToRequest++; mShouldRequestStoragePermission = true; } else { mFlagHasStoragePermission = true; } if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { mNumPermissionsToRequest++; mShouldRequestWriteStoragePermission = true; } else { mFlagHasWriteStoragePermission = true; } if (mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL, Keys.KEY_RECORD_LOCATION) && (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) { mNumPermissionsToRequest++; mShouldRequestLocationPermission = true; } if (mNumPermissionsToRequest != 0) { if (!isKeyguardLocked() && !mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL, Keys.KEY_HAS_SEEN_PERMISSIONS_DIALOGS)) { buildPermissionsRequest(); } else { // Permissions dialog has already been shown, or we're on // lockscreen, and we're still missing permissions. handlePermissionsFailure(); } } else { handlePermissionsSuccess(); } } private void buildPermissionsRequest() { String[] permissionsToRequest = new String[mNumPermissionsToRequest]; int permissionsRequestIndex = 0; if (mShouldRequestCameraPermission) { permissionsToRequest[permissionsRequestIndex] = Manifest.permission.CAMERA; mIndexPermissionRequestCamera = permissionsRequestIndex; permissionsRequestIndex++; } if (mShouldRequestMicrophonePermission) { permissionsToRequest[permissionsRequestIndex] = Manifest.permission.RECORD_AUDIO; mIndexPermissionRequestMicrophone = permissionsRequestIndex; permissionsRequestIndex++; } if (mShouldRequestStoragePermission) { permissionsToRequest[permissionsRequestIndex] = Manifest.permission.READ_EXTERNAL_STORAGE; mIndexPermissionRequestStorage = permissionsRequestIndex; permissionsRequestIndex++; } if (mShouldRequestWriteStoragePermission) { permissionsToRequest[permissionsRequestIndex] = Manifest.permission.WRITE_EXTERNAL_STORAGE; mIndexPermissionRequestWriteStorage = permissionsRequestIndex; permissionsRequestIndex++; } if (mShouldRequestLocationPermission) { permissionsToRequest[permissionsRequestIndex] = Manifest.permission.ACCESS_FINE_LOCATION; mIndexPermissionRequestLocation = permissionsRequestIndex; } Log.v(TAG, "requestPermissions count: " + permissionsToRequest.length); requestPermissions(permissionsToRequest, PERMISSION_REQUEST_CODE); } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { Log.v(TAG, "onPermissionsResult counts: " + permissions.length + ":" + grantResults.length); mSettingsManager.set( SettingsManager.SCOPE_GLOBAL, Keys.KEY_HAS_SEEN_PERMISSIONS_DIALOGS, true); if (mShouldRequestCameraPermission) { if (grantResults.length > 0 && grantResults[mIndexPermissionRequestCamera] == PackageManager.PERMISSION_GRANTED) { mFlagHasCameraPermission = true; } else { handlePermissionsFailure(); } } if (mShouldRequestMicrophonePermission) { if (grantResults.length > 0 && grantResults[mIndexPermissionRequestMicrophone] == PackageManager.PERMISSION_GRANTED) { mFlagHasMicrophonePermission = true; } else { handlePermissionsFailure(); } } if (mShouldRequestStoragePermission) { if (grantResults.length > 0 && grantResults[mIndexPermissionRequestStorage] == PackageManager.PERMISSION_GRANTED) { mFlagHasStoragePermission = true; } else { handlePermissionsFailure(); } } if (mShouldRequestWriteStoragePermission) { if (grantResults.length > 0 && grantResults[mIndexPermissionRequestWriteStorage] == PackageManager.PERMISSION_GRANTED) { mFlagHasWriteStoragePermission = true; } else { handlePermissionsFailure(); } } if (mShouldRequestLocationPermission) { if (grantResults.length > 0 && grantResults[mIndexPermissionRequestLocation] == PackageManager.PERMISSION_GRANTED) { // Do nothing } else { // Do nothing } } if (mFlagHasCameraPermission && mFlagHasMicrophonePermission && mFlagHasStoragePermission && mFlagHasWriteStoragePermission) { handlePermissionsSuccess(); } } private void handlePermissionsSuccess() { Intent intent = new Intent(this, CameraActivity.class); startActivity(intent); finish(); } private void handlePermissionsFailure() { new AlertDialog.Builder(this).setTitle(getResources().getString(R.string.camera_error_title)) .setMessage(getResources().getString(R.string.error_permissions)) .setCancelable(false) .setOnKeyListener(new Dialog.OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { finish(); } return true; } }) .setPositiveButton(getResources().getString(R.string.dialog_dismiss), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }) .show(); } }