1b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds/*
2b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds * Copyright (C) 2018 The Android Open Source Project
3b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds *
4b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds * Licensed under the Apache License, Version 2.0 (the "License");
5b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds * you may not use this file except in compliance with the License.
6b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds * You may obtain a copy of the License at
7b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds *
8b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds *      http://www.apache.org/licenses/LICENSE-2.0
9b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds *
10b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds * Unless required by applicable law or agreed to in writing, software
11b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds * distributed under the License is distributed on an "AS IS" BASIS,
12b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds * See the License for the specific language governing permissions and
14b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds * limitations under the License
15b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds */
16b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
17b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldspackage com.android.systemui.statusbar;
18b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
19b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.app.AppOpsManager;
20b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.content.Context;
21b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.content.pm.ApplicationInfo;
22b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.content.pm.PackageInfo;
23b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.content.pm.PackageManager;
24b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.graphics.drawable.Drawable;
25b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.os.RemoteException;
26b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.service.notification.StatusBarNotification;
27b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.util.ArraySet;
28b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.util.AttributeSet;
29b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.view.View;
30b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.view.accessibility.AccessibilityEvent;
31b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.widget.ImageView;
32b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.widget.LinearLayout;
33b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport android.widget.TextView;
34b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
35b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport com.android.internal.logging.MetricsLogger;
36b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport com.android.internal.logging.nano.MetricsProto.MetricsEvent;
37b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldsimport com.android.systemui.R;
38b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
39b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds/**
40b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds * The guts of a notification revealed when performing a long press.
41b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds */
42b586745d86a7335901646da128ef296e80ba0a22Julia Reynoldspublic class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsContent {
43b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private static final String TAG = "AppOpsGuts";
44b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
45b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private PackageManager mPm;
46b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
47b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private String mPkg;
48b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private String mAppName;
49b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private int mAppUid;
50b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private StatusBarNotification mSbn;
51b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private ArraySet<Integer> mAppOps;
52b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private MetricsLogger mMetricsLogger;
53b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private OnSettingsClickListener mOnSettingsClickListener;
54b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private NotificationGuts mGutsContainer;
55b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
56b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private OnClickListener mOnOk = v -> {
57b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        closeControls(v);
58b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    };
59b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
60b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    public AppOpsInfo(Context context, AttributeSet attrs) {
61b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        super(context, attrs);
62b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
63b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
64b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    public interface OnSettingsClickListener {
65b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        void onClick(View v, String pkg, int uid, ArraySet<Integer> ops);
66b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
67b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
68b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    public void bindGuts(final PackageManager pm,
69b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            final OnSettingsClickListener onSettingsClick,
70b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            final StatusBarNotification sbn,
71b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            ArraySet<Integer> activeOps) {
72b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mPkg = sbn.getPackageName();
73b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mSbn = sbn;
74b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mPm = pm;
75b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mAppName = mPkg;
76b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mOnSettingsClickListener = onSettingsClick;
77b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mAppOps = activeOps;
78b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
79b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        bindHeader();
80b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        bindPrompt();
81b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        bindButtons();
82b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
83b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mMetricsLogger = new MetricsLogger();
84b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, true);
85b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
86b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
87b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private void bindHeader() {
88b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        // Package name
89b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        Drawable pkgicon = null;
90b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        ApplicationInfo info;
91b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        try {
92b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            info = mPm.getApplicationInfo(mPkg,
93b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                    PackageManager.MATCH_UNINSTALLED_PACKAGES
94b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                            | PackageManager.MATCH_DISABLED_COMPONENTS
95b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
96b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                            | PackageManager.MATCH_DIRECT_BOOT_AWARE);
97b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            if (info != null) {
98b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                mAppUid = mSbn.getUid();
99b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                mAppName = String.valueOf(mPm.getApplicationLabel(info));
100b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                pkgicon = mPm.getApplicationIcon(info);
101b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            }
102b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        } catch (PackageManager.NameNotFoundException e) {
103b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            // app is gone, just show package name and generic icon
104b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            pkgicon = mPm.getDefaultActivityIcon();
105b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        }
106b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
107b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
108b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
109b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
110b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private void bindPrompt() {
111b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        final TextView prompt = findViewById(R.id.prompt);
11215db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds        prompt.setText(getPrompt());
113b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
114b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
115b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private void bindButtons() {
116b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        View settings =  findViewById(R.id.settings);
117b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        settings.setOnClickListener((View view) -> {
118b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            mOnSettingsClickListener.onClick(view, mPkg, mAppUid, mAppOps);
119b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        });
120b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        TextView ok = findViewById(R.id.ok);
121b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        ok.setOnClickListener(mOnOk);
122b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
123b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
12415db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds    private String getPrompt() {
12515db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds        if (mAppOps == null || mAppOps.size() == 0) {
12615db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds            return "";
12715db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds        } else if (mAppOps.size() == 1) {
12815db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds            if (mAppOps.contains(AppOpsManager.OP_CAMERA)) {
12915db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds                return mContext.getString(R.string.appops_camera);
13015db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds            } else if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) {
13115db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds                return mContext.getString(R.string.appops_microphone);
132b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            } else {
13315db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds                return mContext.getString(R.string.appops_overlay);
13415db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds            }
13515db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds        } else if (mAppOps.size() == 2) {
13615db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds            if (mAppOps.contains(AppOpsManager.OP_CAMERA)) {
13715db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds                if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) {
13815db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds                    return mContext.getString(R.string.appops_camera_mic);
13915db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds                } else {
14015db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds                    return mContext.getString(R.string.appops_camera_overlay);
14115db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds                }
14215db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds            } else {
14315db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds                return mContext.getString(R.string.appops_mic_overlay);
144b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            }
145b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        } else {
14615db7cdf8d3afc30d754e924c21eece66bf0f0fdJulia Reynolds            return mContext.getString(R.string.appops_camera_mic_overlay);
147b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        }
148b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
149b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
150b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    @Override
151b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
152b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        super.onInitializeAccessibilityEvent(event);
153b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        if (mGutsContainer != null &&
154b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
155b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            if (mGutsContainer.isExposed()) {
156b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                event.getText().add(mContext.getString(
157b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                        R.string.notification_channel_controls_opened_accessibility, mAppName));
158b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            } else {
159b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                event.getText().add(mContext.getString(
160b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds                        R.string.notification_channel_controls_closed_accessibility, mAppName));
161b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds            }
162b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        }
163b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
164b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
165b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    private void closeControls(View v) {
166b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
167b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        int[] parentLoc = new int[2];
168b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        int[] targetLoc = new int[2];
169b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mGutsContainer.getLocationOnScreen(parentLoc);
170b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        v.getLocationOnScreen(targetLoc);
171b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        final int centerX = v.getWidth() / 2;
172b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        final int centerY = v.getHeight() / 2;
173b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        final int x = targetLoc[0] - parentLoc[0] + centerX;
174b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        final int y = targetLoc[1] - parentLoc[1] + centerY;
175b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mGutsContainer.closeControls(x, y, false, false);
176b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
177b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
178b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    @Override
179b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    public void setGutsParent(NotificationGuts guts) {
180b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        mGutsContainer = guts;
181b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
182b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
183b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    @Override
184b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    public boolean willBeRemoved() {
185b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        return false;
186b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
187b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
188b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    @Override
1899b08c01affb15468f0437418ff2f653335acf46cLucas Dupin    public boolean shouldBeSaved() {
1909b08c01affb15468f0437418ff2f653335acf46cLucas Dupin        return false;
1919b08c01affb15468f0437418ff2f653335acf46cLucas Dupin    }
1929b08c01affb15468f0437418ff2f653335acf46cLucas Dupin
1939b08c01affb15468f0437418ff2f653335acf46cLucas Dupin    @Override
194b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    public View getContentView() {
195b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        return this;
196b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
197b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
198b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    @Override
199b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    public boolean handleCloseControls(boolean save, boolean force) {
200b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        return false;
201b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
202b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds
203b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    @Override
204b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    public int getActualHeight() {
205b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds        return getHeight();
206b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds    }
207b586745d86a7335901646da128ef296e80ba0a22Julia Reynolds}
208