aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2015-04-08 17:32:28 -0700
committerEino-Ville Talvala <etalvala@google.com>2015-04-08 17:32:28 -0700
commit36dcae7c5cbc7ea8bef1e14d0be005c8c8c75ecf (patch)
treee093766a3eddb22d07fc768117ef0b963ab6405d
parent6a0fcc827ef8b03b5648b0d3b4c14f8bde82e551 (diff)
downloadpdk-36dcae7c5cbc7ea8bef1e14d0be005c8c8c75ecf.tar.gz
TestingCamera, TestingCamera2: Add runtime permission checking
The permission requests are placed largely where it is easiest to do, though some effort is made to not ask for a permission before it's actually needed. Change-Id: Ia484d6741da6a6c5ab812ecf2bbadc5d9ce81572
-rw-r--r--apps/TestingCamera/AndroidManifest.xml2
-rw-r--r--apps/TestingCamera/src/com/android/testingcamera/SnapshotDialogFragment.java21
-rw-r--r--apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java67
-rw-r--r--apps/TestingCamera2/AndroidManifest.xml2
-rw-r--r--apps/TestingCamera2/src/com/android/testingcamera2/CameraControlPane.java5
-rw-r--r--apps/TestingCamera2/src/com/android/testingcamera2/CameraOps2.java63
-rw-r--r--apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera21.java6
-rw-r--r--apps/TestingCamera2/src/com/android/testingcamera2/v1/TestingCamera2.java44
8 files changed, 193 insertions, 17 deletions
diff --git a/apps/TestingCamera/AndroidManifest.xml b/apps/TestingCamera/AndroidManifest.xml
index 36c21ca..415364c 100644
--- a/apps/TestingCamera/AndroidManifest.xml
+++ b/apps/TestingCamera/AndroidManifest.xml
@@ -22,7 +22,7 @@
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
- <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="17"/>
+ <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="10000"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
diff --git a/apps/TestingCamera/src/com/android/testingcamera/SnapshotDialogFragment.java b/apps/TestingCamera/src/com/android/testingcamera/SnapshotDialogFragment.java
index 6995320..3b1f19d 100644
--- a/apps/TestingCamera/src/com/android/testingcamera/SnapshotDialogFragment.java
+++ b/apps/TestingCamera/src/com/android/testingcamera/SnapshotDialogFragment.java
@@ -4,6 +4,8 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import android.Manifest;
+import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ExifInterface;
@@ -118,6 +120,17 @@ class SnapshotDialogFragment extends DialogFragment
mJpegImage = image;
}
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ TestingCamera parent = (TestingCamera) getActivity();
+ if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ parent.log("Storage write permission granted");
+ saveFile();
+ } else {
+ parent.log("Denied storage write permission; cannot save");
+ }
+ }
+
private String getAttrib(ExifInterface exif, String tag) {
String attribute = exif.getAttribute(tag);
return (attribute == null) ? "???" : attribute;
@@ -128,6 +141,14 @@ class SnapshotDialogFragment extends DialogFragment
TestingCamera parent = (TestingCamera) getActivity();
parent.log("Saving image");
+ if (parent.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ != PackageManager.PERMISSION_GRANTED) {
+ parent.log("Requesting storage write permission");
+ parent.requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ parent.PERMISSIONS_REQUEST_SNAPSHOT);
+ return;
+ }
+
File targetFile = parent.getOutputMediaFile(TestingCamera.MEDIA_TYPE_IMAGE);
if (targetFile == null) {
parent.logE("Unable to create file name");
diff --git a/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java b/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java
index e5ecd0c..8b9dd4f 100644
--- a/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java
+++ b/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java
@@ -16,9 +16,11 @@
package com.android.testingcamera;
+import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.FragmentManager;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.ImageFormat;
import android.hardware.Camera;
@@ -114,6 +116,8 @@ public class TestingCamera extends Activity
private TextView mLogView;
+ SnapshotDialogFragment mSnapshotDialog = null;
+
private Set<View> mOpenOnlyControls = new HashSet<View>();
private Set<View> mPreviewOnlyControls = new HashSet<View>();
@@ -172,7 +176,9 @@ public class TestingCamera extends Activity
/** Misc variables */
private static final String TAG = "TestingCamera";
-
+ private static final int PERMISSIONS_REQUEST_CAMERA = 1;
+ private static final int PERMISSIONS_REQUEST_RECORDING = 2;
+ static final int PERMISSIONS_REQUEST_SNAPSHOT = 3;
/** Activity lifecycle */
@@ -331,7 +337,6 @@ public class TestingCamera extends Activity
public void onResume() {
super.onResume();
log("onResume: Setting up");
- mPreviewHolder = null;
setUpCamera();
}
@@ -358,6 +363,36 @@ public class TestingCamera extends Activity
}
}
+ @Override
+ public void onRequestPermissionsResult (int requestCode, String[] permissions,
+ int[] grantResults) {
+ if (requestCode == PERMISSIONS_REQUEST_CAMERA) {
+ if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ log("Camera permission granted");
+ setUpCamera();
+ } else {
+ log("Camera permission denied, can't do anything");
+ finish();
+ }
+ } else if (requestCode == PERMISSIONS_REQUEST_RECORDING) {
+ mRecordToggle.setChecked(false);
+ for (int i = 0; i < grantResults.length; i++) {
+ if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
+ log("Recording permission " + permissions[i] + " denied");
+ return;
+ }
+ log("Recording permissions granted");
+ setUpCamera();
+ }
+ } else if (requestCode == PERMISSIONS_REQUEST_SNAPSHOT) {
+ if (mSnapshotDialog != null) {
+ mSnapshotDialog.onRequestPermissionsResult(requestCode, permissions,
+ grantResults);
+ }
+ }
+
+ }
+
/** SurfaceHolder.Callback methods */
@Override
public void surfaceChanged(SurfaceHolder holder,
@@ -860,10 +895,10 @@ public class TestingCamera extends Activity
public void onPictureTaken(byte[] data, Camera camera) {
log("JPEG picture callback received");
FragmentManager fm = getFragmentManager();
- SnapshotDialogFragment snapshotDialog = new SnapshotDialogFragment();
+ mSnapshotDialog = new SnapshotDialogFragment();
- snapshotDialog.updateImage(data);
- snapshotDialog.show(fm, "snapshot_dialog_fragment");
+ mSnapshotDialog.updateImage(data);
+ mSnapshotDialog.show(fm, "snapshot_dialog_fragment");
mPreviewToggle.setEnabled(true);
@@ -945,6 +980,15 @@ public class TestingCamera extends Activity
if (mState < CAMERA_OPEN) {
log("Opening camera " + mCameraId);
+ if (checkSelfPermission(Manifest.permission.CAMERA)
+ != PackageManager.PERMISSION_GRANTED) {
+ log("Requested camera permission");
+ requestPermissions(new String[] {Manifest.permission.CAMERA},
+ PERMISSIONS_REQUEST_CAMERA);
+ return;
+ }
+
+
try {
mCamera = Camera.open(mCameraId);
} catch (RuntimeException e) {
@@ -1523,6 +1567,19 @@ public class TestingCamera extends Activity
private void startRecording() {
log("Starting recording");
+
+ if ((checkSelfPermission(Manifest.permission.RECORD_AUDIO)
+ != PackageManager.PERMISSION_GRANTED)
+ || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ != PackageManager.PERMISSION_GRANTED)) {
+ log("Requesting recording permissions (audio, storage)");
+ requestPermissions(new String[] {
+ Manifest.permission.RECORD_AUDIO,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ PERMISSIONS_REQUEST_RECORDING);
+ return;
+ }
+
logIndent(1);
log("Configuring MediaRecoder");
diff --git a/apps/TestingCamera2/AndroidManifest.xml b/apps/TestingCamera2/AndroidManifest.xml
index 5127f0e..79c1b7f 100644
--- a/apps/TestingCamera2/AndroidManifest.xml
+++ b/apps/TestingCamera2/AndroidManifest.xml
@@ -30,7 +30,7 @@
<uses-sdk
android:minSdkVersion="21"
- android:targetSdkVersion="21" />
+ android:targetSdkVersion="10000" />
<uses-feature
android:name="android.hardware.camera.front"
diff --git a/apps/TestingCamera2/src/com/android/testingcamera2/CameraControlPane.java b/apps/TestingCamera2/src/com/android/testingcamera2/CameraControlPane.java
index 00f721e..b220328 100644
--- a/apps/TestingCamera2/src/com/android/testingcamera2/CameraControlPane.java
+++ b/apps/TestingCamera2/src/com/android/testingcamera2/CameraControlPane.java
@@ -376,8 +376,7 @@ public class CameraControlPane extends ControlPane {
if (isChecked) {
// Open camera
mCurrentCamera = null;
- boolean success = mCameraOps.openCamera(mCurrentCameraId, mCameraListener);
- buttonView.setChecked(success);
+ mCameraOps.openCamera(mCurrentCameraId, mCameraListener);
} else {
// Close camera
closeCurrentCamera();
@@ -520,6 +519,7 @@ public class CameraControlPane extends ControlPane {
@Override
public void onClosed(CameraDevice camera) {
// Don't change state on close, tracked by callers of close()
+ mOpenButton.setChecked(false);
}
@Override
@@ -558,7 +558,6 @@ public class CameraControlPane extends ControlPane {
mCurrentCamera.close();
mCurrentCamera = null;
setCameraState(CameraState.CLOSED);
- mOpenButton.setChecked(false);
}
}
diff --git a/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps2.java b/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps2.java
index dcb3cab..ddf0098 100644
--- a/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps2.java
+++ b/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps2.java
@@ -19,7 +19,9 @@ package com.android.testingcamera2;
import java.util.HashSet;
import java.util.Set;
-import android.content.Context;
+import android.Manifest;
+import android.app.Activity;
+import android.content.pm.PackageManager;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
@@ -32,11 +34,17 @@ import android.hardware.camera2.CameraAccessException;
public class CameraOps2 extends CameraManager.AvailabilityCallback {
private final CameraManager mCameraManager;
-
+ private final Activity mActivity;
private final Set<CameraDevice> mOpenCameras = new HashSet<CameraDevice>();
- public CameraOps2(Context context) {
- mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
+ // For persisting values for permission requests
+ private static final int PERMISSIONS_REQUEST_CAMERA = 1;
+ private String mDelayedOpenId = null;
+ private CameraDevice.StateCallback mDelayedOpenListener = null;
+
+ public CameraOps2(Activity activity) {
+ mActivity = activity;
+ mCameraManager = (CameraManager) activity.getSystemService(Activity.CAMERA_SERVICE);
if (mCameraManager == null) {
throw new AssertionError("Can't connect to camera manager!");
}
@@ -101,6 +109,26 @@ public class CameraOps2 extends CameraManager.AvailabilityCallback {
return false;
}
}
+ if ((mActivity.checkSelfPermission(Manifest.permission.CAMERA)
+ != PackageManager.PERMISSION_GRANTED)
+ || (mActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ != PackageManager.PERMISSION_GRANTED)) {
+ TLog.i("Requesting camera/storage permissions");
+
+ mDelayedOpenId = cameraId;
+ mDelayedOpenListener = listener;
+
+ mActivity.requestPermissions(new String[] {
+ Manifest.permission.CAMERA,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE },
+ PERMISSIONS_REQUEST_CAMERA);
+ return false;
+ }
+
+ return doOpenCamera(cameraId, listener);
+ }
+
+ private boolean doOpenCamera(String cameraId, CameraDevice.StateCallback listener) {
try {
DeviceStateCallback proxyListener = new DeviceStateCallback(listener);
mCameraManager.openCamera(cameraId, proxyListener, null);
@@ -112,6 +140,33 @@ public class CameraOps2 extends CameraManager.AvailabilityCallback {
return true;
}
+ public void onRequestPermissionsResult (int requestCode, String[] permissions,
+ int[] grantResults) {
+ if (requestCode == PERMISSIONS_REQUEST_CAMERA) {
+ if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ TLog.i("Camera permission granted");
+ if (mDelayedOpenId != null && mDelayedOpenListener != null) {
+ doOpenCamera(mDelayedOpenId, mDelayedOpenListener);
+ }
+ mDelayedOpenId = null;
+ mDelayedOpenListener = null;
+ } else {
+ TLog.i("Camera permission denied, not opening camera");
+ if (mDelayedOpenId != null && mDelayedOpenListener != null) {
+ mDelayedOpenListener.onError(null,
+ CameraDevice.StateCallback.ERROR_CAMERA_DISABLED);
+ mDelayedOpenId = null;
+ mDelayedOpenListener = null;
+ }
+ }
+ if (grantResults[1] == PackageManager.PERMISSION_GRANTED) {
+ TLog.i("Storage permission granted");
+ } else {
+ TLog.i("Storage permission not granted; saving will not work");
+ }
+ }
+ }
+
public CameraCharacteristics getCameraInfo(String cameraId) {
try {
return mCameraManager.getCameraCharacteristics(cameraId);
diff --git a/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera21.java b/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera21.java
index c78c401..c15a78c 100644
--- a/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera21.java
+++ b/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera21.java
@@ -184,6 +184,12 @@ public class TestingCamera21 extends Activity implements CameraControlPane.InfoD
return super.onOptionsItemSelected(item);
}
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ mCameraOps.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+
/**
* Get shared camera controls
*/
diff --git a/apps/TestingCamera2/src/com/android/testingcamera2/v1/TestingCamera2.java b/apps/TestingCamera2/src/com/android/testingcamera2/v1/TestingCamera2.java
index 64fa8a4..9bd3113 100644
--- a/apps/TestingCamera2/src/com/android/testingcamera2/v1/TestingCamera2.java
+++ b/apps/TestingCamera2/src/com/android/testingcamera2/v1/TestingCamera2.java
@@ -16,7 +16,9 @@
package com.android.testingcamera2.v1;
+import android.Manifest;
import android.app.Activity;
+import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -108,7 +110,7 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
private final Set<View> mManualControls = new HashSet<View>();
private final Set<View> mAutoControls = new HashSet<View>();
-
+ private static final int PERMISSIONS_REQUEST_CAMERA = 1;
Handler mMainHandler;
boolean mUseMediaCodec;
@@ -196,9 +198,45 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
@Override
public void onResume() {
super.onResume();
- try {
- if (VERBOSE) Log.v(TAG, String.format("onResume"));
+ if (VERBOSE) Log.v(TAG, String.format("onResume"));
+
+ if ((checkSelfPermission(Manifest.permission.CAMERA)
+ != PackageManager.PERMISSION_GRANTED )
+ || (checkSelfPermission(Manifest.permission.RECORD_AUDIO)
+ != PackageManager.PERMISSION_GRANTED)
+ || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ != PackageManager.PERMISSION_GRANTED)) {
+ Log.i(TAG, "Requested camera/video permissions");
+ requestPermissions(new String[] {
+ Manifest.permission.CAMERA,
+ Manifest.permission.RECORD_AUDIO,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ PERMISSIONS_REQUEST_CAMERA);
+ return;
+ }
+ setUpPreview();
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ if (requestCode == PERMISSIONS_REQUEST_CAMERA) {
+ for (int i = 0; i < grantResults.length; i++) {
+ if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
+ Log.i(TAG, "At least one permission denied, can't continue: " + permissions[i]);
+ finish();
+ return;
+ }
+ }
+
+ Log.i(TAG, "All permissions granted");
+ setUpPreview();
+ }
+ }
+
+ private void setUpPreview() {
+ try {
mCameraOps.minimalPreviewConfig(mPreviewView.getHolder());
mCurrentPreviewHolder = mPreviewView.getHolder();
} catch (ApiFailureException e) {