diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2016-06-10 23:15:54 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-06-10 23:15:54 -0700 |
commit | 2efa365cdd2a1f045ab03acd432b8e9e9a8ffe7b (patch) | |
tree | 8f9a00a677361f926035f9b3546202a6d7c9610f | |
parent | 69b71ffdc38b7261c9eabb3a22259da13ed11b02 (diff) | |
parent | f6ced59d086a755d6f720600181c023c29d202ca (diff) | |
download | android_packages_apps_Snap-2efa365cdd2a1f045ab03acd432b8e9e9a8ffe7b.tar.gz android_packages_apps_Snap-2efa365cdd2a1f045ab03acd432b8e9e9a8ffe7b.tar.bz2 android_packages_apps_Snap-2efa365cdd2a1f045ab03acd432b8e9e9a8ffe7b.zip |
Merge "Minimum viable Android M runtime permissions handling for H." into camera.lnx.1.0-dev.1.0
-rw-r--r-- | AndroidManifest.xml | 10 | ||||
-rw-r--r-- | res/values/strings.xml | 6 | ||||
-rw-r--r-- | src/com/android/camera/CameraActivity.java | 41 | ||||
-rw-r--r-- | src/com/android/camera/PermissionsActivity.java | 167 |
4 files changed, 223 insertions, 1 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ac727e2a2..12a86bb9b 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -20,7 +20,6 @@ <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> <uses-permission android:name="android.permission.NFC" /> - <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> @@ -83,6 +82,15 @@ android:resource="@layout/keyguard_widget" /> </activity> + <activity + android:name="com.android.camera.PermissionsActivity" + android:label="@string/app_name" + android:parentActivityName="com.android.camera.CameraActivity" > + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value="com.android.camera.CameraActivity" /> + </activity> + <activity-alias android:name="com.android.camera.CameraLauncher" android:icon="@mipmap/ic_launcher_camera" diff --git a/res/values/strings.xml b/res/values/strings.xml index 2b06e257f..898329a7f 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -171,6 +171,12 @@ <!-- message for the dialog showing the camera is disabled because of security policies. Camera cannot be used. --> <string name="camera_disabled">Camera has been disabled because of security policies.</string> + <!-- message for the dialog showing that the app does not have sufficient permissions [CHAR LIMIT=NONE] --> + <string name="error_permissions">The app does not have critical permissions needed to run. Please check your permissions settings.</string> + + <!-- Dialog "Dismiss" button. Closes the dialog [CHAR LIMIT=12]--> + <string name="dialog_dismiss">Dismiss</string> + <!-- alert to the user to wait for some operation to complete --> <string name="wait">Please wait\u2026</string> diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java index a93e7ccc0..e1abd93db 100644 --- a/src/com/android/camera/CameraActivity.java +++ b/src/com/android/camera/CameraActivity.java @@ -18,6 +18,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; @@ -32,6 +33,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; @@ -144,6 +146,9 @@ public class CameraActivity extends Activity // This string is used for judge start activity from screenoff or not public static final String GESTURE_CAMERA_NAME = "com.android.camera.CameraGestureActivity"; + private static final int PERMISSIONS_ACTIVITY_REQUEST_CODE = 1; + private static final int PERMISSIONS_RESULT_CODE_OK = 0; + private static final int PERMISSIONS_RESULT_CODE_FAILED = 1; /** * Request code from an activity we started that indicated that we do not @@ -218,6 +223,7 @@ public class CameraActivity extends Activity private View mPreviewCover; private FrameLayout mPreviewContentLayout; private boolean mPaused = true; + private boolean mHasCriticalPermissions; private Uri[] mNfcPushUris = new Uri[1]; @@ -1377,6 +1383,7 @@ public class CameraActivity extends Activity @Override public void onCreate(Bundle state) { super.onCreate(state); + checkPermissions(); // Check if this is in the secure camera mode. Intent intent = getIntent(); String action = intent.getAction(); @@ -1615,6 +1622,10 @@ public class CameraActivity extends Activity mIsEditActivityInProgress = false; } else { super.onActivityResult(requestCode, resultCode, data); + // Close the app if critical permissions are missing. + if (requestCode == PERMISSIONS_ACTIVITY_REQUEST_CODE && resultCode == PERMISSIONS_RESULT_CODE_FAILED) { + finish(); + } } } @@ -1625,8 +1636,38 @@ 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) The permissions dialogs have not run yet. We will ask for permission only once. + * b) If the missing permissions are critical to the app running, we will display a fatal error dialog. + * Critical permissions are: camera, microphone and storage. The app cannot run without them. + * Non-critical permission is location. + */ + private void checkPermissions() { + + 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) { + Intent intent = new Intent(this, PermissionsActivity.class); + startActivityForResult(intent, PERMISSIONS_ACTIVITY_REQUEST_CODE); + } + } + @Override public void onResume() { + if (!mHasCriticalPermissions) { + super.onResume(); + Log.v(TAG, "Missing critical permissions."); + return; + } // Hide action bar first since we are in full screen mode first, and // switch the system UI to lights-out mode. this.setSystemBarsVisibility(false); diff --git a/src/com/android/camera/PermissionsActivity.java b/src/com/android/camera/PermissionsActivity.java new file mode 100644 index 000000000..f2d907c68 --- /dev/null +++ b/src/com/android/camera/PermissionsActivity.java @@ -0,0 +1,167 @@ +package com.android.camera; + +import android.Manifest; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.pm.PackageManager; +import android.os.Bundle; +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 static int RESULT_CODE_OK = 0; + private static int RESULT_CODE_FAILED = 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; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + protected void onResume() { + super.onResume(); + mNumPermissionsToRequest = 0; + checkPermissions(); + } + + 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 { + handlePermissionsFailure(); + } + } + if (mShouldRequestMicrophonePermission) { + if (grantResults[mIndexPermissionRequestMicrophone] == PackageManager.PERMISSION_GRANTED) { + mFlagHasMicrophonePermission = true; + } else { + handlePermissionsFailure(); + } + } + if (mShouldRequestStoragePermission) { + if (grantResults[mIndexPermissionRequestStorage] == PackageManager.PERMISSION_GRANTED) { + mFlagHasStoragePermission = true; + } else { + handlePermissionsFailure(); + } + } + + if (mShouldRequestLocationPermission) { + if (grantResults[mIndexPermissionRequestLocation] == PackageManager.PERMISSION_GRANTED) { + // Do nothing + } else { + // Do nothing + } + } + + if (mFlagHasCameraPermission && mFlagHasMicrophonePermission && mFlagHasStoragePermission) { + handlePermissionsSuccess(); + } + } + + private void handlePermissionsSuccess() { + setResult(RESULT_CODE_OK, null); + finish(); + } + + private void handlePermissionsFailure() { + new AlertDialog.Builder(this).setTitle(getResources().getString(R.string.camera_error_title)) + .setMessage(getResources().getString(R.string.error_permissions)) + .setPositiveButton(getResources().getString(R.string.dialog_dismiss), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + setResult(RESULT_CODE_FAILED, null); + finish(); + } + }) + .show(); + } +} |