Slide 1

Slide 1 text

Do Your Users Love Android Runtime Permissions? Eric Cochran Oredev November 11, 2016

Slide 2

Slide 2 text

2 9 Permission groups • CALENDAR • READ_CALENDAR • WRITE_CALENDAR • CAMERA • CAMERA • CONTACTS • READ_CONTACTS • WRITE_CONTACTS • GET_ACCOUNTS • STORAGE • READ_EXTERNAL_STORAGE • WRITE_EXTERNAL_STORAGE • LOCATION • ACCESS_COARSE_LOCATION • ACCESS_FINE_LOCATION • SENSORS • BODY_SENSORS • MICROPHONE • RECORD_AUDIO • PHONE • READ_PHONE_STATE • CALL_PHONE • READ_CALL_LOG • WRITE_CALL_LOG • ADD_VOICEMAIL • USE_SIP • PROCESS_OUTGOING_CALLS • SMS • READ_SMS • SEND_SMS • RECEIVE_SMS • RECEIVE_MMS • RECEIVE_WAP_PUSH

Slide 3

Slide 3 text

3 • NORMAL — FREE! • DANGEROUS — ASK AT RUNTIME • SIGNATURE — /SYSTEM/PRIV-APP • PREINSTALLED — /SYSTEM/APP • PRE23 — FREE IF TARGET < 23 • DEVELOPMENT • PRIVILEGED (AKA SYSTEM) • SIGNATUREORSYSTEM • INSTALLER • VERIFIER Protection Level

Slide 4

Slide 4 text

4 Keep Up with Permissions • PLATFORM_FRAMEWORKS_BASE • CORE/RES/ANDROIDMANIFEST.XML https://android.googlesource.com/platform/frameworks/base.git/+/master/core/res/AndroidManifest.xml

Slide 5

Slide 5 text

5 What’s New for My App? • TARGETING < 23 • PERMISSIONS GRANTED BY DEFAULT • EMPTY DATA WHEN USERS EXPLICITLY DENY PERMISSIONS • PRE23 PROTECTION • WRITE_SETTINGS IS NO MORE • SYSTEM_ALERT_WINDOW IS GRANTABLE • 6.0: GET_ACCOUNTS NOT NEEDED FOR YOUR OWN ACCOUNT

Slide 6

Slide 6 text

6 if (!Settings.canDrawOverlays(this)) {
 Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
 Uri.parse("package:" + activity.getPackageName())); List handlers = context.getPackageManager().queryIntentActivities( appSettings, 0);
 if (handlers.isEmpty()) { // We can't go to Settings.
 return; }
 activity.startActivityForResult(intent, REQUEST_CODE_PERMISION_SYSTEM_ALERT_WINDOW);
 } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 if (requestCode == REQUEST_CODE_PERMISION_SYSTEM_ALERT_WINDOW) {
 if (Settings.canDrawOverlays(this)) {
 // Yay!
 } else {
 // Denied.
 }
 }
 }

Slide 7

Slide 7 text

7 if (notificationManager.getCurrentInterruptionFilter() != INTERRUPTION_FILTER_ALL) {
 Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); List handlers = context.getPackageManager().queryIntentActivities( appSettings, 0);
 if (handlers.isEmpty()) { // We can't go to Settings.
 return; }
 activity.startActivity(intent);
 }

Slide 8

Slide 8 text

8 Runtime Permissions String permission = READ_CALENDAR;
 Context checker; // PERMISSION_DENIED or PERMISSION_GRANTED
 int result = checker.checkSelfPermission(permission);

Slide 9

Slide 9 text

9 Runtime Permissions • USE SUPPORT ANNOTATIONS! @RequiresPermission(READ_CALENDAR) • USE SUPPORT V4! String permission = READ_CALENDAR;
 Context checker = …;
 int result = PermissionChecker.checkSelfPermission(checker, permission);

Slide 10

Slide 10 text

10 Rationale before request? Activity requester;
 boolean rationale = requester.shouldShowRequestPermissionRationale(permission);

Slide 11

Slide 11 text

11 Request String[] permissionsNeeded = { READ_CALENDAR };
 Activity requester;
 requester.requestPermissions(permissionsNeeded, requestCode); @Override public void onRequestPermissionsResult(int requestCode,
 @NonNull String[] permissions, @NonNull int[] grantResults) {
 // grantedResults full of PERMISSION_GRANTED and PERMISSION_DENIED.
 }

Slide 12

Slide 12 text

12 Denied: What Now? Intent appSettings = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + context.getPackageName()));
 List handlers = context.getPackageManager().queryIntentActivities( appSettings, 0);
 if (handlers.isEmpty()) {
 // We can't go to Settings.
 return;
 }
 context.startActivity(appSettings);

Slide 13

Slide 13 text

13 Test adb shell pm revoke

Slide 14

Slide 14 text

14 Manifest Tricks

Slide 15

Slide 15 text

15 @Eric_Cochran github.com/NightlyNexus nightlynexus.com