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