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 int mNumPermissionsToRequest; 47 private boolean mFlagHasCameraPermission; 48 private boolean mFlagHasMicrophonePermission; 49 private SettingsManager mSettingsManager; 50 51 /** 52 * Close activity when secure app passes lock screen or screen turns 53 * off. 54 */ 55 private final BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() { 56 @Override 57 public void onReceive(Context context, Intent intent) { 58 Log.v(TAG, "received intent, finishing: " + intent.getAction()); 59 finish(); 60 } 61 }; 62 63 @Override onCreateTasks(Bundle savedInstanceState)64 protected void onCreateTasks(Bundle savedInstanceState) { 65 setContentView(R.layout.permissions); 66 mSettingsManager = CameraServicesImpl.instance().getSettingsManager(); 67 68 // Filter for screen off so that we can finish permissions activity 69 // when screen is off. 70 IntentFilter filter_screen_off = new IntentFilter(Intent.ACTION_SCREEN_OFF); 71 registerReceiver(mShutdownReceiver, filter_screen_off); 72 73 // Filter for phone unlock so that we can finish permissions activity 74 // via this UI path: 75 // 1. from secure lock screen, user starts secure camera 76 // 2. user presses home button 77 // 3. user unlocks phone 78 IntentFilter filter_user_unlock = new IntentFilter(Intent.ACTION_USER_PRESENT); 79 registerReceiver(mShutdownReceiver, filter_user_unlock); 80 81 Window win = getWindow(); 82 if (isKeyguardLocked()) { 83 win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); 84 } else { 85 win.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); 86 } 87 } 88 89 @Override onResumeTasks()90 protected void onResumeTasks() { 91 mNumPermissionsToRequest = 0; 92 checkPermissions(); 93 } 94 95 @Override onDestroyTasks()96 protected void onDestroyTasks() { 97 Log.v(TAG, "onDestroy: unregistering receivers"); 98 unregisterReceiver(mShutdownReceiver); 99 } 100 checkPermissions()101 private void checkPermissions() { 102 if (checkSelfPermission(Manifest.permission.CAMERA) 103 != PackageManager.PERMISSION_GRANTED) { 104 mNumPermissionsToRequest++; 105 mShouldRequestCameraPermission = true; 106 } else { 107 mFlagHasCameraPermission = true; 108 } 109 110 if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) 111 != PackageManager.PERMISSION_GRANTED) { 112 mNumPermissionsToRequest++; 113 mShouldRequestMicrophonePermission = true; 114 } else { 115 mFlagHasMicrophonePermission = true; 116 } 117 118 if (mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL, 119 Keys.KEY_RECORD_LOCATION) 120 && (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) 121 != PackageManager.PERMISSION_GRANTED)) { 122 mNumPermissionsToRequest++; 123 mShouldRequestLocationPermission = true; 124 } 125 126 if (mNumPermissionsToRequest != 0) { 127 if (!isKeyguardLocked() && !mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL, 128 Keys.KEY_HAS_SEEN_PERMISSIONS_DIALOGS)) { 129 buildPermissionsRequest(); 130 } else { 131 // Permissions dialog has already been shown, or we're on 132 // lockscreen, and we're still missing permissions. 133 handlePermissionsFailure(); 134 } 135 } else { 136 handlePermissionsSuccess(); 137 } 138 } 139 buildPermissionsRequest()140 private void buildPermissionsRequest() { 141 String[] permissionsToRequest = new String[mNumPermissionsToRequest]; 142 int permissionsRequestIndex = 0; 143 144 if (mShouldRequestCameraPermission) { 145 permissionsToRequest[permissionsRequestIndex] = Manifest.permission.CAMERA; 146 mIndexPermissionRequestCamera = permissionsRequestIndex; 147 permissionsRequestIndex++; 148 } 149 if (mShouldRequestMicrophonePermission) { 150 permissionsToRequest[permissionsRequestIndex] = Manifest.permission.RECORD_AUDIO; 151 mIndexPermissionRequestMicrophone = permissionsRequestIndex; 152 permissionsRequestIndex++; 153 } 154 if (mShouldRequestLocationPermission) { 155 permissionsToRequest[permissionsRequestIndex] = Manifest.permission.ACCESS_COARSE_LOCATION; 156 mIndexPermissionRequestLocation = permissionsRequestIndex; 157 } 158 159 Log.v(TAG, "requestPermissions count: " + permissionsToRequest.length); 160 requestPermissions(permissionsToRequest, PERMISSION_REQUEST_CODE); 161 } 162 163 @Override onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)164 public void onRequestPermissionsResult(int requestCode, 165 String permissions[], int[] grantResults) { 166 Log.v(TAG, "onPermissionsResult counts: " + permissions.length + ":" + grantResults.length); 167 mSettingsManager.set( 168 SettingsManager.SCOPE_GLOBAL, 169 Keys.KEY_HAS_SEEN_PERMISSIONS_DIALOGS, 170 true); 171 172 if (mShouldRequestCameraPermission) { 173 if (grantResults.length > 0 && grantResults[mIndexPermissionRequestCamera] == 174 PackageManager.PERMISSION_GRANTED) { 175 mFlagHasCameraPermission = true; 176 } else { 177 handlePermissionsFailure(); 178 } 179 } 180 if (mShouldRequestMicrophonePermission) { 181 if (grantResults.length > 0 && grantResults[mIndexPermissionRequestMicrophone] == 182 PackageManager.PERMISSION_GRANTED) { 183 mFlagHasMicrophonePermission = true; 184 } else { 185 handlePermissionsFailure(); 186 } 187 } 188 if (mShouldRequestLocationPermission) { 189 if (grantResults.length > 0 && grantResults[mIndexPermissionRequestLocation] == 190 PackageManager.PERMISSION_GRANTED) { 191 // Do nothing 192 } else { 193 // Do nothing 194 } 195 } 196 197 if (mFlagHasCameraPermission && mFlagHasMicrophonePermission) { 198 handlePermissionsSuccess(); 199 } 200 } 201 handlePermissionsSuccess()202 private void handlePermissionsSuccess() { 203 Intent intent = new Intent(this, CameraActivity.class); 204 startActivity(intent); 205 finish(); 206 } 207 handlePermissionsFailure()208 private void handlePermissionsFailure() { 209 new AlertDialog.Builder(this).setTitle(getResources().getString(R.string.camera_error_title)) 210 .setMessage(getResources().getString(R.string.error_permissions)) 211 .setCancelable(false) 212 .setOnKeyListener(new Dialog.OnKeyListener() { 213 @Override 214 public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { 215 if (keyCode == KeyEvent.KEYCODE_BACK) { 216 finish(); 217 } 218 return true; 219 } 220 }) 221 .setPositiveButton(getResources().getString(R.string.dialog_dismiss), 222 new DialogInterface.OnClickListener() { 223 @Override 224 public void onClick(DialogInterface dialog, int which) { 225 finish(); 226 } 227 }) 228 .show(); 229 } 230 } 231