Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01bb0f9b authored by Fan Zhang's avatar Fan Zhang Committed by Android (Google) Code Review
Browse files

Merge "Create a page to manage dnd permission for individual app"

parents f5e2bfee 5bb2a87b
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -7939,6 +7939,9 @@
    <!-- Sound & notification > Advanced section: Title for managing Do Not Disturb access option. [CHAR LIMIT=40] -->
    <string name="manage_zen_access_title">Do Not Disturb access</string>
    <!-- Button title that grants 'Do Not Disturb' permission to an app [CHAR_LIMIT=60]-->
    <string name="zen_access_detail_switch">Allow Do Not Disturb</string>
    <!-- Sound & notification > Do Not Disturb access > Text to display when the list is empty. [CHAR LIMIT=NONE] -->
    <string name="zen_access_empty_text">No installed apps have requested Do Not Disturb access</string>
+27 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  Copyright (C) 2019 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.
  -->

<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:key="zen_access_permission_detail_settings"
    android:title="@string/manage_zen_access_title">

    <SwitchPreference
        android:key="zen_access_switch"
        android:title="@string/zen_access_detail_switch"/>

</PreferenceScreen>
 No newline at end of file
+76 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.zenaccess;

import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.os.Bundle;
import android.text.TextUtils;

import androidx.appcompat.app.AlertDialog;

import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;

/**
 * Warning dialog when revoking zen access warning that zen rule instances will be deleted.
 */
public class FriendlyWarningDialogFragment extends InstrumentedDialogFragment {
    static final String KEY_PKG = "p";
    static final String KEY_LABEL = "l";


    @Override
    public int getMetricsCategory() {
        return SettingsEnums.DIALOG_ZEN_ACCESS_REVOKE;
    }

    public FriendlyWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
        Bundle args = new Bundle();
        args.putString(KEY_PKG, pkg);
        args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
        setArguments(args);
        return this;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Bundle args = getArguments();
        final String pkg = args.getString(KEY_PKG);
        final String label = args.getString(KEY_LABEL);

        final String title = getResources().getString(
                R.string.zen_access_revoke_warning_dialog_title, label);
        final String summary = getResources()
                .getString(R.string.zen_access_revoke_warning_dialog_summary);
        return new AlertDialog.Builder(getContext())
                .setMessage(summary)
                .setTitle(title)
                .setCancelable(true)
                .setPositiveButton(R.string.okay,
                        (dialog, id) -> {
                            ZenAccessController.deleteRules(getContext(), pkg);
                            ZenAccessController.setAccess(getContext(), pkg, false);
                        })
                .setNegativeButton(R.string.cancel,
                        (dialog, id) -> {
                            // pass
                        })
                .create();
    }
}
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.zenaccess;

import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.os.Bundle;
import android.text.TextUtils;

import androidx.appcompat.app.AlertDialog;

import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.notification.ZenAccessSettings;

/**
 * Warning dialog when allowing zen access warning about the privileges being granted.
 */
public class ScaryWarningDialogFragment extends InstrumentedDialogFragment {
    static final String KEY_PKG = "p";
    static final String KEY_LABEL = "l";

    @Override
    public int getMetricsCategory() {
        return SettingsEnums.DIALOG_ZEN_ACCESS_GRANT;
    }

    public ScaryWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
        Bundle args = new Bundle();
        args.putString(KEY_PKG, pkg);
        args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
        setArguments(args);
        return this;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Bundle args = getArguments();
        final String pkg = args.getString(KEY_PKG);
        final String label = args.getString(KEY_LABEL);

        final String title = getResources().getString(R.string.zen_access_warning_dialog_title,
                label);
        final String summary = getResources()
                .getString(R.string.zen_access_warning_dialog_summary);
        return new AlertDialog.Builder(getContext())
                .setMessage(summary)
                .setTitle(title)
                .setCancelable(true)
                .setPositiveButton(R.string.allow,
                        (dialog, id) -> ZenAccessController.setAccess(getContext(), pkg, true))
                .setNegativeButton(R.string.deny,
                        (dialog, id) -> {
                            // pass
                        })
                .create();
    }
}
+78 −1
Original line number Diff line number Diff line
@@ -17,12 +17,29 @@
package com.android.settings.applications.specialaccess.zenaccess;

import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.NotificationManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.ParceledListSlice;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Log;

import androidx.annotation.VisibleForTesting;

import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;

import java.util.List;
import java.util.Set;

public class ZenAccessController extends BasePreferenceController {

    private static final String TAG = "ZenAccessController";

    private final ActivityManager mActivityManager;

    public ZenAccessController(Context context, String preferenceKey) {
@@ -32,8 +49,68 @@ public class ZenAccessController extends BasePreferenceController {

    @Override
    public int getAvailabilityStatus() {
        return !mActivityManager.isLowRamDevice()
        return isSupported(mActivityManager)
                ? AVAILABLE_UNSEARCHABLE
                : UNSUPPORTED_ON_DEVICE;
    }

    public static boolean isSupported(ActivityManager activityManager) {
        return !activityManager.isLowRamDevice();
    }

    public static Set<String> getPackagesRequestingNotificationPolicyAccess() {
        final ArraySet<String> requestingPackages = new ArraySet<>();
        try {
            final String[] PERM = {
                    android.Manifest.permission.ACCESS_NOTIFICATION_POLICY
            };
            final ParceledListSlice list = AppGlobals.getPackageManager()
                    .getPackagesHoldingPermissions(PERM, 0 /*flags*/,
                            ActivityManager.getCurrentUser());
            final List<PackageInfo> pkgs = list.getList();
            if (pkgs != null) {
                for (PackageInfo info : pkgs) {
                    requestingPackages.add(info.packageName);
                }
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Cannot reach packagemanager", e);
        }
        return requestingPackages;
    }

    public static Set<String> getAutoApprovedPackages(Context context) {
        final Set<String> autoApproved = new ArraySet<>();
        autoApproved.addAll(context.getSystemService(NotificationManager.class)
                .getEnabledNotificationListenerPackages());
        return autoApproved;
    }

    public static boolean hasAccess(Context context, String pkg) {
        return context.getSystemService(
                NotificationManager.class).isNotificationPolicyAccessGrantedForPackage(pkg);
    }

    public static void setAccess(final Context context, final String pkg, final boolean access) {
        logSpecialPermissionChange(access, pkg, context);
        AsyncTask.execute(() -> {
            final NotificationManager mgr = context.getSystemService(NotificationManager.class);
            mgr.setNotificationPolicyAccessGranted(pkg, access);
        });
    }

    public static void deleteRules(final Context context, final String pkg) {
        AsyncTask.execute(() -> {
            final NotificationManager mgr = context.getSystemService(NotificationManager.class);
            mgr.removeAutomaticZenRules(pkg);
        });
    }

    @VisibleForTesting
    static void logSpecialPermissionChange(boolean enable, String packageName, Context context) {
        int logCategory = enable ? SettingsEnums.APP_SPECIAL_PERMISSION_DND_ALLOW
                : SettingsEnums.APP_SPECIAL_PERMISSION_DND_DENY;
        FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context,
                logCategory, packageName);
    }
}
Loading