1 /* 2 * Copyright (c) 2016, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.car.stream; 17 18 import android.app.Activity; 19 import android.app.AlertDialog; 20 import android.content.ComponentName; 21 import android.content.DialogInterface; 22 import android.content.Intent; 23 import android.content.pm.PackageManager; 24 import android.content.res.Resources; 25 import android.os.Bundle; 26 import android.provider.Settings; 27 import android.util.Log; 28 import com.android.car.stream.notifications.StreamNotificationListenerService; 29 30 import java.util.ArrayList; 31 import java.util.List; 32 33 /** 34 * A trampoline activity that checks if all permissions necessary are granted. 35 */ 36 public class PermissionsActivity extends Activity { 37 private static final String TAG = "PermissionsActivity"; 38 private static final String NOTIFICATION_LISTENER_ENABLED = "enabled_notification_listeners"; 39 40 public static final int CAR_PERMISSION_REQUEST_CODE = 1013; // choose a unique number 41 42 private static final String[] PERMISSIONS = new String[]{ 43 android.Manifest.permission.READ_PHONE_STATE, 44 android.Manifest.permission.CALL_PHONE, 45 android.Manifest.permission.READ_CALL_LOG, 46 android.Manifest.permission.READ_CONTACTS, 47 android.Manifest.permission.ACCESS_FINE_LOCATION, 48 android.Manifest.permission.RECEIVE_SMS, 49 android.Manifest.permission.READ_EXTERNAL_STORAGE 50 }; 51 52 @Override 53 protected void onCreate(Bundle savedInstanceState) { 54 super.onCreate(savedInstanceState); 55 56 boolean permissionsCheckOnly = getIntent().getExtras() 57 .getBoolean(StreamConstants.STREAM_PERMISSION_CHECK_PERMISSIONS_ONLY); 58 59 if (permissionsCheckOnly) { 60 boolean allPermissionsGranted = hasNotificationListenerPermission() 61 && arePermissionGranted(PERMISSIONS); 62 setResult(allPermissionsGranted ? RESULT_OK : RESULT_CANCELED); 63 finish(); 64 return; 65 } 66 67 if (!hasNotificationListenerPermission()) { 68 showNotificationListenerSettings(); 69 } else { 70 maybeRequestPermissions(); 71 } 72 } 73 74 private void maybeRequestPermissions() { 75 boolean permissionGranted = arePermissionGranted(PERMISSIONS); 76 if (!permissionGranted) { 77 requestPermissions(PERMISSIONS, CAR_PERMISSION_REQUEST_CODE); 78 } else { 79 startService(new Intent(this, StreamService.class)); 80 finish(); 81 } 82 } 83 84 @Override 85 public void onRequestPermissionsResult(int requestCode, String[] permissions, 86 int[] grantResults) { 87 super.onRequestPermissionsResult(requestCode, permissions, grantResults); 88 89 if (requestCode == CAR_PERMISSION_REQUEST_CODE) { 90 List<String> granted = new ArrayList<>(); 91 List<String> notGranted = new ArrayList<>(); 92 for (int i = 0; i < permissions.length; i++) { 93 String permission = permissions[i]; 94 int grantResult = grantResults[i]; 95 if (grantResult == PackageManager.PERMISSION_GRANTED) { 96 granted.add(permission); 97 } else { 98 notGranted.add(permission); 99 } 100 } 101 102 if (notGranted.size() > 0) { 103 StringBuilder stb = new StringBuilder(); 104 for (String s : notGranted) { 105 stb.append(" ").append(s); 106 } 107 showDialog(getString(R.string.permission_not_granted, stb.toString())); 108 } else { 109 showDialog(getString(R.string.all_permission_granted)); 110 startService(new Intent(this, StreamService.class)); 111 } 112 113 if (arePermissionGranted(PERMISSIONS)) { 114 setResult(Activity.RESULT_OK); 115 } 116 finish(); 117 } 118 } 119 120 private void showDialog(String message) { 121 new AlertDialog.Builder(this /* context */) 122 .setTitle(getString(R.string.permission_dialog_title)) 123 .setMessage(message) 124 .setIcon(android.R.drawable.ic_dialog_alert) 125 .setPositiveButton( 126 getString(R.string.permission_dialog_positive_button_text), 127 new DialogInterface.OnClickListener() { 128 public void onClick(DialogInterface dialog, int id) { 129 dialog.cancel(); 130 } 131 }) 132 .show(); 133 } 134 135 private boolean arePermissionGranted(String[] permissions) { 136 for (String permission : permissions) { 137 if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { 138 Log.e(TAG, "Permission is not granted: " + permission); 139 return false; 140 } 141 } 142 return true; 143 } 144 145 private boolean hasNotificationListenerPermission() { 146 ComponentName notificationListener = new ComponentName(this, 147 StreamNotificationListenerService.class); 148 String listeners = Settings.Secure.getString(getContentResolver(), 149 NOTIFICATION_LISTENER_ENABLED); 150 return listeners != null && listeners.contains(notificationListener.flattenToString()); 151 } 152 153 private void showNotificationListenerSettings() { 154 AlertDialog dialog = new AlertDialog.Builder(this) 155 .setTitle(getString(R.string.car_notification_permission_dialog_title)) 156 .setMessage(getString(R.string.car_notification_permission_dialog_text)) 157 .setCancelable(false) 158 .setNeutralButton(getString(android.R.string.ok), 159 new DialogInterface.OnClickListener() { 160 @Override 161 public void onClick(DialogInterface dialog, int id) { 162 dialog.cancel(); 163 Intent settingsIntent = 164 new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS); 165 startActivity(settingsIntent); 166 } 167 }) 168 .create(); 169 dialog.show(); 170 } 171 } 172