blob: e445c9d73bbbebe6c9c073da7e86d040159ac680 [file] [log] [blame]
Julia Reynoldsb5867452018-02-28 16:31:35 -05001/*
2 * Copyright (C) 2018 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
Rohan Shah20790b82018-07-02 17:21:04 -070017package com.android.systemui.statusbar.notification.row;
Julia Reynoldsb5867452018-02-28 16:31:35 -050018
19import android.app.AppOpsManager;
20import android.content.Context;
21import android.content.pm.ApplicationInfo;
Julia Reynoldsb5867452018-02-28 16:31:35 -050022import android.content.pm.PackageManager;
23import android.graphics.drawable.Drawable;
Julia Reynoldsb5867452018-02-28 16:31:35 -050024import android.service.notification.StatusBarNotification;
25import android.util.ArraySet;
26import android.util.AttributeSet;
27import android.view.View;
28import android.view.accessibility.AccessibilityEvent;
29import android.widget.ImageView;
30import android.widget.LinearLayout;
31import android.widget.TextView;
32
33import com.android.internal.logging.MetricsLogger;
34import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
35import com.android.systemui.R;
36
37/**
38 * The guts of a notification revealed when performing a long press.
39 */
40public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsContent {
41 private static final String TAG = "AppOpsGuts";
42
43 private PackageManager mPm;
44
45 private String mPkg;
46 private String mAppName;
47 private int mAppUid;
48 private StatusBarNotification mSbn;
49 private ArraySet<Integer> mAppOps;
50 private MetricsLogger mMetricsLogger;
51 private OnSettingsClickListener mOnSettingsClickListener;
52 private NotificationGuts mGutsContainer;
53
54 private OnClickListener mOnOk = v -> {
Dave Mankoffc97a0e62020-06-01 12:13:05 -040055 mGutsContainer.closeControls(v, false);
Julia Reynoldsb5867452018-02-28 16:31:35 -050056 };
57
58 public AppOpsInfo(Context context, AttributeSet attrs) {
59 super(context, attrs);
60 }
61
62 public interface OnSettingsClickListener {
63 void onClick(View v, String pkg, int uid, ArraySet<Integer> ops);
64 }
65
66 public void bindGuts(final PackageManager pm,
67 final OnSettingsClickListener onSettingsClick,
68 final StatusBarNotification sbn,
69 ArraySet<Integer> activeOps) {
70 mPkg = sbn.getPackageName();
71 mSbn = sbn;
72 mPm = pm;
73 mAppName = mPkg;
74 mOnSettingsClickListener = onSettingsClick;
75 mAppOps = activeOps;
76
77 bindHeader();
78 bindPrompt();
79 bindButtons();
80
81 mMetricsLogger = new MetricsLogger();
82 mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, true);
83 }
84
85 private void bindHeader() {
86 // Package name
87 Drawable pkgicon = null;
88 ApplicationInfo info;
89 try {
90 info = mPm.getApplicationInfo(mPkg,
91 PackageManager.MATCH_UNINSTALLED_PACKAGES
92 | PackageManager.MATCH_DISABLED_COMPONENTS
93 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
94 | PackageManager.MATCH_DIRECT_BOOT_AWARE);
95 if (info != null) {
96 mAppUid = mSbn.getUid();
97 mAppName = String.valueOf(mPm.getApplicationLabel(info));
98 pkgicon = mPm.getApplicationIcon(info);
99 }
100 } catch (PackageManager.NameNotFoundException e) {
101 // app is gone, just show package name and generic icon
102 pkgicon = mPm.getDefaultActivityIcon();
103 }
104 ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
105 ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
106 }
107
108 private void bindPrompt() {
109 final TextView prompt = findViewById(R.id.prompt);
Julia Reynolds15db7cd2018-05-07 09:42:38 -0400110 prompt.setText(getPrompt());
Julia Reynoldsb5867452018-02-28 16:31:35 -0500111 }
112
113 private void bindButtons() {
114 View settings = findViewById(R.id.settings);
115 settings.setOnClickListener((View view) -> {
116 mOnSettingsClickListener.onClick(view, mPkg, mAppUid, mAppOps);
117 });
118 TextView ok = findViewById(R.id.ok);
119 ok.setOnClickListener(mOnOk);
Dave Mankoffc97a0e62020-06-01 12:13:05 -0400120 ok.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
Julia Reynoldsb5867452018-02-28 16:31:35 -0500121 }
122
Julia Reynolds15db7cd2018-05-07 09:42:38 -0400123 private String getPrompt() {
124 if (mAppOps == null || mAppOps.size() == 0) {
125 return "";
126 } else if (mAppOps.size() == 1) {
127 if (mAppOps.contains(AppOpsManager.OP_CAMERA)) {
128 return mContext.getString(R.string.appops_camera);
129 } else if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) {
130 return mContext.getString(R.string.appops_microphone);
Julia Reynoldsb5867452018-02-28 16:31:35 -0500131 } else {
Julia Reynolds15db7cd2018-05-07 09:42:38 -0400132 return mContext.getString(R.string.appops_overlay);
133 }
134 } else if (mAppOps.size() == 2) {
135 if (mAppOps.contains(AppOpsManager.OP_CAMERA)) {
136 if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) {
137 return mContext.getString(R.string.appops_camera_mic);
138 } else {
139 return mContext.getString(R.string.appops_camera_overlay);
140 }
141 } else {
142 return mContext.getString(R.string.appops_mic_overlay);
Julia Reynoldsb5867452018-02-28 16:31:35 -0500143 }
144 } else {
Julia Reynolds15db7cd2018-05-07 09:42:38 -0400145 return mContext.getString(R.string.appops_camera_mic_overlay);
Julia Reynoldsb5867452018-02-28 16:31:35 -0500146 }
Julia Reynoldsb5867452018-02-28 16:31:35 -0500147 }
148
149 @Override
150 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
151 super.onInitializeAccessibilityEvent(event);
152 if (mGutsContainer != null &&
153 event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
154 if (mGutsContainer.isExposed()) {
155 event.getText().add(mContext.getString(
156 R.string.notification_channel_controls_opened_accessibility, mAppName));
157 } else {
158 event.getText().add(mContext.getString(
159 R.string.notification_channel_controls_closed_accessibility, mAppName));
160 }
161 }
162 }
163
Julia Reynoldsb5867452018-02-28 16:31:35 -0500164 @Override
165 public void setGutsParent(NotificationGuts guts) {
166 mGutsContainer = guts;
167 }
168
169 @Override
170 public boolean willBeRemoved() {
171 return false;
172 }
173
174 @Override
Lucas Dupin9b08c012018-05-16 19:53:32 -0700175 public boolean shouldBeSaved() {
176 return false;
177 }
178
179 @Override
Julia Reynoldsbe371072020-05-28 11:32:01 -0400180 public boolean needsFalsingProtection() {
181 return false;
182 }
183
184 @Override
Julia Reynoldsb5867452018-02-28 16:31:35 -0500185 public View getContentView() {
186 return this;
187 }
188
189 @Override
190 public boolean handleCloseControls(boolean save, boolean force) {
Dave Mankoffc125b412020-06-08 13:27:59 -0400191 if (mMetricsLogger != null) {
192 mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
193 }
Julia Reynoldsb5867452018-02-28 16:31:35 -0500194 return false;
195 }
196
197 @Override
198 public int getActualHeight() {
199 return getHeight();
200 }
201}