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