1 /* 2 * Copyright (C) 2017 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 17 18 package com.android.settings.notification; 19 20 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 21 22 import static com.android.internal.notification.NotificationAccessConfirmationActivityContract.EXTRA_COMPONENT_NAME; 23 import static com.android.internal.notification.NotificationAccessConfirmationActivityContract.EXTRA_PACKAGE_TITLE; 24 import static com.android.internal.notification.NotificationAccessConfirmationActivityContract.EXTRA_USER_ID; 25 26 import android.Manifest; 27 import android.annotation.Nullable; 28 import android.app.Activity; 29 import android.app.NotificationManager; 30 import android.content.ComponentName; 31 import android.content.Context; 32 import android.content.DialogInterface; 33 import android.content.pm.PackageManager; 34 import android.content.pm.ServiceInfo; 35 import android.os.Bundle; 36 import android.os.UserHandle; 37 import android.util.Slog; 38 import android.view.WindowManager; 39 import android.view.accessibility.AccessibilityEvent; 40 41 import com.android.internal.app.AlertActivity; 42 import com.android.internal.app.AlertController; 43 import com.android.settings.R; 44 45 /** @hide */ 46 public class NotificationAccessConfirmationActivity extends Activity 47 implements DialogInterface { 48 49 private static final boolean DEBUG = false; 50 private static final String LOG_TAG = "NotificationAccessConfirmationActivity"; 51 52 private int mUserId; 53 private ComponentName mComponentName; 54 private NotificationManager mNm; 55 56 @Override onCreate(@ullable Bundle savedInstanceState)57 protected void onCreate(@Nullable Bundle savedInstanceState) { 58 super.onCreate(savedInstanceState); 59 60 getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 61 62 mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 63 64 mComponentName = getIntent().getParcelableExtra(EXTRA_COMPONENT_NAME); 65 mUserId = getIntent().getIntExtra(EXTRA_USER_ID, UserHandle.USER_NULL); 66 String pkgTitle = getIntent().getStringExtra(EXTRA_PACKAGE_TITLE); 67 68 AlertController.AlertParams p = new AlertController.AlertParams(this); 69 p.mTitle = getString( 70 R.string.notification_listener_security_warning_title, 71 pkgTitle); 72 p.mMessage = getString( 73 R.string.notification_listener_security_warning_summary, 74 pkgTitle); 75 p.mPositiveButtonText = getString(R.string.allow); 76 p.mPositiveButtonListener = (a, b) -> onAllow(); 77 p.mNegativeButtonText = getString(R.string.deny); 78 p.mNegativeButtonListener = (a, b) -> cancel(); 79 AlertController 80 .create(this, this, getWindow()) 81 .installContent(p); 82 // Consistent with the permission dialog 83 // Used instead of p.mCancelable as that is only honored for AlertDialog 84 getWindow().setCloseOnTouchOutside(false); 85 } 86 87 @Override onResume()88 public void onResume() { 89 super.onResume(); 90 getWindow().addFlags( 91 WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 92 } 93 94 @Override onPause()95 public void onPause() { 96 getWindow().clearFlags( 97 WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 98 super.onPause(); 99 } 100 onAllow()101 private void onAllow() { 102 String requiredPermission = Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE; 103 try { 104 ServiceInfo serviceInfo = getPackageManager().getServiceInfo(mComponentName, 0); 105 if (!requiredPermission.equals(serviceInfo.permission)) { 106 Slog.e(LOG_TAG, 107 "Service " + mComponentName + " lacks permission " + requiredPermission); 108 return; 109 } 110 } catch (PackageManager.NameNotFoundException e) { 111 Slog.e(LOG_TAG, "Failed to get service info for " + mComponentName, e); 112 return; 113 } 114 115 mNm.setNotificationListenerAccessGranted(mComponentName, true); 116 117 finish(); 118 } 119 120 @Override dispatchPopulateAccessibilityEvent(AccessibilityEvent event)121 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 122 return AlertActivity.dispatchPopulateAccessibilityEvent(this, event); 123 } 124 125 @Override onBackPressed()126 public void onBackPressed() { 127 // Suppress finishing the activity on back button press, 128 // consistently with the permission dialog behavior 129 } 130 131 @Override cancel()132 public void cancel() { 133 finish(); 134 } 135 136 @Override dismiss()137 public void dismiss() { 138 // This is called after the click, since we finish when handling the 139 // click, don't do that again here. 140 if (!isFinishing()) { 141 finish(); 142 } 143 } 144 } 145