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 import java.util.ArrayList; 26 import java.util.List; 27 28 /** 29 * Activity that shows permissions request dialogs and handles lack of critical permissions. 30 * TODO: Convert PermissionsActivity into a dialog to be emitted from 31 * CameraActivity as not to have to restart CameraActivity from 32 * scratch. 33 */ 34 public class PermissionsActivity extends QuickActivity { 35 private static final Log.Tag TAG = new Log.Tag("PermissionsActivity"); 36 37 private static final int PERMISSION_REQUEST_CODE = 1; 38 39 private SettingsManager mSettingsManager; 40 41 /** 42 * Close activity when secure app passes lock screen or screen turns 43 * off. 44 */ 45 private final BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() { 46 @Override 47 public void onReceive(Context context, Intent intent) { 48 Log.v(TAG, "received intent, finishing: " + intent.getAction()); 49 finish(); 50 } 51 }; 52 53 @Override onCreateTasks(Bundle savedInstanceState)54 protected void onCreateTasks(Bundle savedInstanceState) { 55 setContentView(R.layout.permissions); 56 mSettingsManager = CameraServicesImpl.instance().getSettingsManager(); 57 58 // Filter for screen off so that we can finish permissions activity 59 // when screen is off. 60 IntentFilter filter_screen_off = new IntentFilter(Intent.ACTION_SCREEN_OFF); 61 registerReceiver(mShutdownReceiver, filter_screen_off); 62 63 // Filter for phone unlock so that we can finish permissions activity 64 // via this UI path: 65 // 1. from secure lock screen, user starts secure camera 66 // 2. user presses home button 67 // 3. user unlocks phone 68 IntentFilter filter_user_unlock = new IntentFilter(Intent.ACTION_USER_PRESENT); 69 registerReceiver(mShutdownReceiver, filter_user_unlock); 70 71 Window win = getWindow(); 72 if (isKeyguardLocked()) { 73 win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); 74 } else { 75 win.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); 76 } 77 } 78 79 @Override onResumeTasks()80 protected void onResumeTasks() { 81 checkPermissions(); 82 } 83 84 @Override onDestroyTasks()85 protected void onDestroyTasks() { 86 Log.v(TAG, "onDestroy: unregistering receivers"); 87 unregisterReceiver(mShutdownReceiver); 88 } 89 checkPermissions()90 private void checkPermissions() { 91 List<String> permissions = new ArrayList<>(); 92 93 if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { 94 permissions.add(Manifest.permission.CAMERA); 95 } 96 97 if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) 98 != PackageManager.PERMISSION_GRANTED) { 99 permissions.add(Manifest.permission.RECORD_AUDIO); 100 } 101 102 if (mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL, Keys.KEY_RECORD_LOCATION) 103 && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) 104 != PackageManager.PERMISSION_GRANTED 105 && checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) 106 != PackageManager.PERMISSION_GRANTED) { 107 permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION); 108 permissions.add(Manifest.permission.ACCESS_FINE_LOCATION); 109 } 110 111 if (!permissions.isEmpty()) { 112 if (!isKeyguardLocked() && !mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL, 113 Keys.KEY_HAS_SEEN_PERMISSIONS_DIALOGS)) { 114 Log.v(TAG, "requestPermissions count: " + permissions.size()); 115 requestPermissions(permissions.toArray(new String[0]), PERMISSION_REQUEST_CODE); 116 } else { 117 // Permissions dialog has already been shown, or we're on 118 // lockscreen, and we're still missing permissions. 119 handlePermissionsFailure(); 120 } 121 } else { 122 handlePermissionsSuccess(); 123 } 124 } 125 126 @Override onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)127 public void onRequestPermissionsResult(int requestCode, 128 String[] permissions, int[] grantResults) { 129 Log.v(TAG, "onPermissionsResult counts: " + permissions.length + ":" + grantResults.length); 130 mSettingsManager.set( 131 SettingsManager.SCOPE_GLOBAL, 132 Keys.KEY_HAS_SEEN_PERMISSIONS_DIALOGS, 133 true); 134 135 boolean missingCriticalPermissions = false; 136 for (int i = 0; i < permissions.length; i++) { 137 String permission = permissions[i]; 138 int result = grantResults[i]; 139 // Show fail dialog if critical permissions are not granted 140 if (Manifest.permission.CAMERA.equals(permission) 141 && result == PackageManager.PERMISSION_DENIED) { 142 handlePermissionsFailure(); 143 missingCriticalPermissions = true; 144 } else if (Manifest.permission.RECORD_AUDIO.equals(permission) 145 && result == PackageManager.PERMISSION_DENIED) { 146 handlePermissionsFailure(); 147 missingCriticalPermissions = true; 148 } 149 } 150 if (!missingCriticalPermissions) { 151 handlePermissionsSuccess(); 152 } 153 } 154 handlePermissionsSuccess()155 private void handlePermissionsSuccess() { 156 Intent intent = new Intent(this, CameraActivity.class); 157 startActivity(intent); 158 finish(); 159 } 160 handlePermissionsFailure()161 private void handlePermissionsFailure() { 162 new AlertDialog.Builder(this).setTitle(getResources().getString(R.string.camera_error_title)) 163 .setMessage(getResources().getString(R.string.error_permissions)) 164 .setCancelable(false) 165 .setOnKeyListener(new Dialog.OnKeyListener() { 166 @Override 167 public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { 168 if (keyCode == KeyEvent.KEYCODE_BACK) { 169 finish(); 170 } 171 return true; 172 } 173 }) 174 .setPositiveButton(getResources().getString(R.string.dialog_dismiss), 175 new DialogInterface.OnClickListener() { 176 @Override 177 public void onClick(DialogInterface dialog, int which) { 178 finish(); 179 } 180 }) 181 .show(); 182 } 183 } 184