Files
app_Settings/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
Matías Hernández 027f0a46ae Settings: don't try to allow NLSes with too-long component names
* NotificationAccessConfirmationActivity (triggered through CompanionDeviceManager) -> Don't show the dialog, bail out early similarly to other invalid inputs.
* NotificationAccessSettings (from Special App Access) -> No changes, but use the canonical constant now.
* ApprovalPreferenceController (used in NotificationAccessDetails) -> Disable the toggle, unless the NLS was previously approved (in which case it can still be removed).

Fixes: 260570119
Fixes: 286043036
Test: atest + manually
Change-Id: Ifc048311746c027e3683cdcf65f1079d04cf7c56
2023-06-21 17:02:32 +02:00

141 lines
5.0 KiB
Java

/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.specialaccess.notificationaccess;
import android.app.NotificationManager;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedSwitchPreference;
public class ApprovalPreferenceController extends BasePreferenceController {
private static final String TAG = "ApprovalPrefController";
private PackageInfo mPkgInfo;
private ComponentName mCn;
private PreferenceFragmentCompat mParent;
private NotificationManager mNm;
private PackageManager mPm;
public ApprovalPreferenceController(Context context, String key) {
super(context, key);
}
public ApprovalPreferenceController setPkgInfo(PackageInfo pkgInfo) {
mPkgInfo = pkgInfo;
return this;
}
public ApprovalPreferenceController setCn(ComponentName cn) {
mCn = cn;
return this;
}
public ApprovalPreferenceController setParent(PreferenceFragmentCompat parent) {
mParent = parent;
return this;
}
public ApprovalPreferenceController setNm(NotificationManager nm) {
mNm = nm;
return this;
}
public ApprovalPreferenceController setPm(PackageManager pm) {
mPm = pm;
return this;
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public void updateState(Preference pref) {
final RestrictedSwitchPreference preference =
(RestrictedSwitchPreference) pref;
final CharSequence label = mPkgInfo.applicationInfo.loadLabel(mPm);
final boolean isAllowedCn = mCn.flattenToShortString().length()
<= NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH;
final boolean isEnabled = isServiceEnabled(mCn);
preference.setChecked(isEnabled);
preference.setOnPreferenceChangeListener((p, newValue) -> {
final boolean access = (Boolean) newValue;
if (!access) {
if (!isServiceEnabled(mCn)) {
return true; // already disabled
}
// show a friendly dialog
new FriendlyWarningDialogFragment()
.setServiceInfo(mCn, label, mParent)
.show(mParent.getFragmentManager(), "friendlydialog");
return false;
} else {
if (isServiceEnabled(mCn)) {
return true; // already enabled
}
// show a scary dialog
new ScaryWarningDialogFragment()
.setServiceInfo(mCn, label, mParent)
.show(mParent.getFragmentManager(), "dialog");
return false;
}
});
preference.updateState(
mCn.getPackageName(), mPkgInfo.applicationInfo.uid, isAllowedCn, isEnabled);
}
public void disable(final ComponentName cn) {
logSpecialPermissionChange(true, cn.getPackageName());
mNm.setNotificationListenerAccessGranted(cn, false);
AsyncTask.execute(() -> {
if (!mNm.isNotificationPolicyAccessGrantedForPackage(
cn.getPackageName())) {
mNm.removeAutomaticZenRules(cn.getPackageName());
}
});
}
protected void enable(ComponentName cn) {
logSpecialPermissionChange(true, cn.getPackageName());
mNm.setNotificationListenerAccessGranted(cn, true);
}
protected boolean isServiceEnabled(ComponentName cn) {
return mNm.isNotificationListenerAccessGranted(cn);
}
@VisibleForTesting
void logSpecialPermissionChange(boolean enable, String packageName) {
final int logCategory = enable ? SettingsEnums.APP_SPECIAL_PERMISSION_NOTIVIEW_ALLOW
: SettingsEnums.APP_SPECIAL_PERMISSION_NOTIVIEW_DENY;
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider().action(mContext,
logCategory, packageName);
}
}