summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorzafir <zafir@google.com>2015-06-29 00:08:22 -0500
committerSteve Kondik <steve@cyngn.com>2016-08-18 15:07:20 -0700
commit219fbf4d3d7c47039c79822af26bace2849375e4 (patch)
tree34fcb84361c5e1b2f8da734aa74b47796f5c7aaa /src
parentdb4f5342e80662985c8bcb208e4fabf5c8db8a1a (diff)
downloadandroid_packages_apps_Snap-219fbf4d3d7c47039c79822af26bace2849375e4.tar.gz
android_packages_apps_Snap-219fbf4d3d7c47039c79822af26bace2849375e4.tar.bz2
android_packages_apps_Snap-219fbf4d3d7c47039c79822af26bace2849375e4.zip
Minimum viable Android M runtime permissions handling for H.
Creates new activity for permissions handling: both checking for permissions and handling error condition when critical permissions are not present. The reason for creating a new activity is so the app does not attempt to continue executing OnCreate, OnResume etc, which opens the camera while the dialogs are showing. This should not slow the app down because the permissions activity will only run when a) the first time the app has insufficient permissions and b) when a critical permission is missing and the app needs to shut down. Bug: 21273463 CRs-Fixed: 1019847 Change-Id: I603acfb3057ba26b9cfa7935eb4cb24b5d547cb5 (cherry picked from commit ad44cda82fe6ec5ee090115129223c6314f9e1bb) Fixes to M permissions. Previously, we called PermissionsActivity with startActivityForResult(). However, this creates race conditions as we check for permissions and the CameraActivity continues to operate. Now, we end CameraActivity and launch a new instance upon successful permissions resolution. We can also put the preload filmstrip logic back in its original place in onCreate. The checks for permissions happen in both onCreate and onResume. Bug: 22442745, 22478144, 22497152 CRs-Fixed: 1019847 Change-Id: I82e9125a46581db44aa61d4ee94aec5a820e9df0 (cherry picked from commit ac0e2425e77a9b69e76d2f31876798825ea44584) SnapdragonCamera: Fixed M permission issue - Resolved NPE while sending permission request - Made change to request non-critical permissions once only, but the critical permssions all th time. - Removed unused contant defines CRs-Fixed: 1019847 Change-Id: Ib997244cbcc041d86c094c7ee7a902bff56e92ad snap: Remove platform signature * We are using runtime permissions now. Change-Id: I3386214dbbc0915251941ef490e7cbaf27e6ed45
Diffstat (limited to 'src')
-rw-r--r--src/com/android/camera/CameraActivity.java63
-rw-r--r--src/com/android/camera/CameraSettings.java2
-rw-r--r--src/com/android/camera/PermissionsActivity.java191
3 files changed, 253 insertions, 3 deletions
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index bdb03bb0a..a22a7ae41 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -19,6 +19,7 @@ package com.android.camera;
import android.view.Display;
import android.graphics.Point;
+import android.Manifest;
import android.animation.Animator;
import android.annotation.TargetApi;
import android.app.ActionBar;
@@ -33,6 +34,7 @@ import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
@@ -227,6 +229,7 @@ public class CameraActivity extends Activity
private boolean mPaused = true;
private View mPreviewCover;
private FrameLayout mPreviewContentLayout;
+ private boolean mHasCriticalPermissions;
private Uri[] mNfcPushUris = new Uri[1];
@@ -1428,6 +1431,11 @@ public class CameraActivity extends Activity
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
+ if (checkPermissions() || !mHasCriticalPermissions) {
+ Log.v(TAG, "onCreate: Missing critical permissions.");
+ finish();
+ return;
+ }
// Check if this is in the secure camera mode.
Intent intent = getIntent();
String action = intent.getAction();
@@ -1637,7 +1645,9 @@ public class CameraActivity extends Activity
@Override
public void onUserInteraction() {
super.onUserInteraction();
- mCurrentModule.onUserInteraction();
+ if (mCurrentModule != null) {
+ mCurrentModule.onUserInteraction();
+ }
}
@Override
@@ -1691,8 +1701,53 @@ public class CameraActivity extends Activity
if (focus) this.setSystemBarsVisibility(false);
}
+ /**
+ * Checks if any of the needed Android runtime permissions are missing.
+ * If they are, then launch the permissions activity under one of the following conditions:
+ * a) If critical permissions are missing, display permission request again
+ * b) If non-critical permissions are missing, just display permission request once.
+ * Critical permissions are: camera, microphone and storage. The app cannot run without them.
+ * Non-critical permission is location.
+ */
+ private boolean checkPermissions() {
+ boolean requestPermission = false;
+
+ if (checkSelfPermission(Manifest.permission.CAMERA) ==
+ PackageManager.PERMISSION_GRANTED &&
+ checkSelfPermission(Manifest.permission.RECORD_AUDIO) ==
+ PackageManager.PERMISSION_GRANTED &&
+ checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) ==
+ PackageManager.PERMISSION_GRANTED) {
+ mHasCriticalPermissions = true;
+ } else {
+ mHasCriticalPermissions = false;
+ }
+
+ if ((checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) !=
+ PackageManager.PERMISSION_GRANTED) || !mHasCriticalPermissions) {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean isRequestShown = prefs.getBoolean(CameraSettings.KEY_REQUEST_PERMISSION, false);
+ if(!isRequestShown || !mHasCriticalPermissions) {
+ Log.v(TAG, "Request permission");
+ Intent intent = new Intent(this, PermissionsActivity.class);
+ startActivity(intent);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(CameraSettings.KEY_REQUEST_PERMISSION, true);
+ editor.apply();
+ requestPermission = true;
+ }
+ }
+ return requestPermission;
+ }
+
@Override
public void onResume() {
+ if (checkPermissions() || !mHasCriticalPermissions) {
+ super.onResume();
+ Log.v(TAG, "onResume: Missing critical permissions.");
+ finish();
+ return;
+ }
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_FOREGROUNDED, this.getClass().getSimpleName());
@@ -1761,8 +1816,10 @@ public class CameraActivity extends Activity
getContentResolver().unregisterContentObserver(mLocalVideosObserver);
unregisterReceiver(mSDcardMountedReceiver);
- mCursor.close();
- mCursor=null;
+ if (mCursor != null) {
+ mCursor.close();
+ mCursor=null;
+ }
super.onDestroy();
}
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index bf6dfc080..86d84ac6c 100644
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -241,6 +241,8 @@ public class CameraSettings {
public static final String KEY_QC_SUPPORTED_MANUAL_EXPOSURE_MODES = "manual-exposure-modes";
public static final String KEY_QC_SUPPORTED_MANUAL_WB_MODES = "manual-wb-modes";
+ public static final String KEY_REQUEST_PERMISSION = "request_permission";
+
public static final String KEY_SELFIE_FLASH = "pref_selfie_flash_key";
public static final String EXPOSURE_DEFAULT_VALUE = "0";
diff --git a/src/com/android/camera/PermissionsActivity.java b/src/com/android/camera/PermissionsActivity.java
new file mode 100644
index 000000000..27a3c3692
--- /dev/null
+++ b/src/com/android/camera/PermissionsActivity.java
@@ -0,0 +1,191 @@
+package com.android.camera;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import org.codeaurora.snapcam.R;
+
+/**
+ * Activity that shows permissions request dialogs and handles lack of critical permissions.
+ */
+public class PermissionsActivity extends Activity {
+ private static final String TAG = "PermissionsActivity";
+
+ private static int PERMISSION_REQUEST_CODE = 1;
+
+ private int mIndexPermissionRequestCamera;
+ private int mIndexPermissionRequestMicrophone;
+ private int mIndexPermissionRequestLocation;
+ private int mIndexPermissionRequestStorage;
+ private boolean mShouldRequestCameraPermission;
+ private boolean mShouldRequestMicrophonePermission;
+ private boolean mShouldRequestLocationPermission;
+ private boolean mShouldRequestStoragePermission;
+ private int mNumPermissionsToRequest;
+ private boolean mFlagHasCameraPermission;
+ private boolean mFlagHasMicrophonePermission;
+ private boolean mFlagHasStoragePermission;
+ private boolean mCriticalPermissionDenied;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (!mCriticalPermissionDenied) {
+ mNumPermissionsToRequest = 0;
+ checkPermissions();
+ } else {
+ mCriticalPermissionDenied = false;
+ }
+ }
+
+ 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.ACCESS_COARSE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED) {
+ mNumPermissionsToRequest++;
+ mShouldRequestLocationPermission = true;
+ }
+
+ if (mNumPermissionsToRequest != 0) {
+ buildPermissionsRequest();
+ } 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 (mShouldRequestLocationPermission) {
+ permissionsToRequest[permissionsRequestIndex] = Manifest.permission.ACCESS_COARSE_LOCATION;
+ mIndexPermissionRequestLocation = permissionsRequestIndex;
+ }
+ requestPermissions(permissionsToRequest, PERMISSION_REQUEST_CODE);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode,
+ String permissions[], int[] grantResults) {
+
+ if (mShouldRequestCameraPermission) {
+ if (grantResults[mIndexPermissionRequestCamera] ==
+ PackageManager.PERMISSION_GRANTED) {
+ mFlagHasCameraPermission = true;
+ } else {
+ mCriticalPermissionDenied = true;
+ }
+ }
+ if (mShouldRequestMicrophonePermission) {
+ if (grantResults[mIndexPermissionRequestMicrophone] ==
+ PackageManager.PERMISSION_GRANTED) {
+ mFlagHasMicrophonePermission = true;
+ } else {
+ mCriticalPermissionDenied = true;
+ }
+ }
+ if (mShouldRequestStoragePermission) {
+ if (grantResults[mIndexPermissionRequestStorage] ==
+ PackageManager.PERMISSION_GRANTED) {
+ mFlagHasStoragePermission = true;
+ } else {
+ mCriticalPermissionDenied = true;
+ }
+ }
+
+ if (mShouldRequestLocationPermission) {
+ if (grantResults[mIndexPermissionRequestLocation] ==
+ PackageManager.PERMISSION_GRANTED) {
+ // Do nothing
+ } else {
+ // Do nothing
+ }
+ }
+
+ if (mFlagHasCameraPermission && mFlagHasMicrophonePermission && mFlagHasStoragePermission) {
+ handlePermissionsSuccess();
+ } else if (mCriticalPermissionDenied) {
+ handlePermissionsFailure();
+ }
+ }
+
+ 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();
+ }
+}