* 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
141 lines
5.0 KiB
Java
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);
|
|
}
|
|
} |