1 /* 2 * Copyright (C) 2021 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.car.settings.notifications; 19 20 21 import static com.android.internal.notification.NotificationAccessConfirmationActivityContract.EXTRA_COMPONENT_NAME; 22 import static com.android.internal.notification.NotificationAccessConfirmationActivityContract.EXTRA_PACKAGE_TITLE; 23 24 import android.Manifest; 25 import android.annotation.Nullable; 26 import android.app.NotificationManager; 27 import android.content.ComponentName; 28 import android.content.pm.PackageManager; 29 import android.content.pm.ServiceInfo; 30 import android.os.Bundle; 31 import android.text.TextUtils; 32 import android.view.accessibility.AccessibilityEvent; 33 34 import androidx.fragment.app.Fragment; 35 import androidx.fragment.app.FragmentActivity; 36 37 import com.android.car.settings.R; 38 import com.android.car.settings.common.ConfirmationDialogFragment; 39 import com.android.car.settings.common.Logger; 40 import com.android.internal.app.AlertActivity; 41 import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin; 42 43 /** 44 * This activity is a copy of 45 * {@link com.android.settings.notification.NotificationAccessConfirmationActivity}. 46 */ 47 public class NotificationAccessConfirmationActivity extends FragmentActivity { 48 private static final Logger LOG = new Logger(NotificationAccessConfirmationActivity.class); 49 private static final String REQUIRED_PERMISSION = 50 Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE; 51 52 private ComponentName mComponentName; 53 54 private final ConfirmationDialogFragment.ConfirmListener mConfirmListener = 55 arguments -> onAllow(); 56 57 private final ConfirmationDialogFragment.RejectListener mRejectListener = 58 arguments -> cancel(); 59 60 @Override onCreate(@ullable Bundle savedInstanceState)61 protected void onCreate(@Nullable Bundle savedInstanceState) { 62 super.onCreate(savedInstanceState); 63 getLifecycle().addObserver(new HideNonSystemOverlayMixin(this)); 64 ConfirmationDialogFragment.resetListeners(findConfirmationDialogFragment(), 65 mConfirmListener, 66 mRejectListener, 67 /* neutralListener= */ null); 68 69 70 mComponentName = getIntent().getParcelableExtra(EXTRA_COMPONENT_NAME); 71 String pkgTitle = getIntent().getStringExtra(EXTRA_PACKAGE_TITLE); 72 if (TextUtils.isEmpty(pkgTitle)) { 73 LOG.e(EXTRA_PACKAGE_TITLE + " is empty"); 74 finish(); 75 } 76 77 ConfirmationDialogFragment confirmationDialogFragment = 78 new ConfirmationDialogFragment.Builder(this) 79 .setTitle(getString(R.string.notification_listener_security_warning_title, 80 pkgTitle)) 81 .setMessage( 82 getString(R.string.notification_listener_security_warning_summary, 83 pkgTitle)) 84 .setPositiveButton(R.string.allow, mConfirmListener) 85 .setNegativeButton(R.string.deny, mRejectListener) 86 .build(); 87 88 // Consistent with the permission dialog 89 confirmationDialogFragment.setCancelable(false); 90 confirmationDialogFragment 91 .show(getSupportFragmentManager(), ConfirmationDialogFragment.TAG); 92 } 93 94 @Nullable findConfirmationDialogFragment()95 private ConfirmationDialogFragment findConfirmationDialogFragment() { 96 Fragment fragment = getSupportFragmentManager().findFragmentByTag( 97 ConfirmationDialogFragment.TAG); 98 if (fragment != null) { 99 return (ConfirmationDialogFragment) fragment; 100 } 101 return null; 102 } 103 onAllow()104 private void onAllow() { 105 try { 106 ServiceInfo serviceInfo = getPackageManager().getServiceInfo(mComponentName, 0); 107 if (!REQUIRED_PERMISSION.equals(serviceInfo.permission)) { 108 LOG.e("Service " + mComponentName + " lacks permission " + REQUIRED_PERMISSION); 109 finish(); 110 return; 111 } 112 } catch (PackageManager.NameNotFoundException e) { 113 LOG.e("Failed to get service info for " + mComponentName, e); 114 finish(); 115 return; 116 } 117 118 getSystemService(NotificationManager.class) 119 .setNotificationListenerAccessGranted(mComponentName, true); 120 finish(); 121 } 122 123 @Override dispatchPopulateAccessibilityEvent(AccessibilityEvent event)124 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 125 return AlertActivity.dispatchPopulateAccessibilityEvent(this, event); 126 } 127 128 @Override onBackPressed()129 public void onBackPressed() { 130 // Suppress finishing the activity on back button press, 131 // consistently with the permission dialog behavior 132 } 133 cancel()134 private void cancel() { 135 finish(); 136 } 137 } 138