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

Commit 01ebe2d6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Limit unconfigurability to specified channels."

parents 5b2ed748 bbd4fc12
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -211,7 +211,8 @@ public class AppNotificationSettings extends NotificationSettingsBase {
        MasterSwitchPreference channelPref = new MasterSwitchPreference(
                getPrefContext());
        channelPref.setSwitchEnabled(mSuspendedAppsAdmin == null
                &&  isChannelBlockable(mAppRow.systemApp, channel));
                && isChannelBlockable(mAppRow.systemApp, channel)
                && isChannelConfigurable(channel));
        channelPref.setKey(channel.getId());
        channelPref.setTitle(channel.getName());
        channelPref.setChecked(channel.getImportance() != IMPORTANCE_NONE);
+3 −3
Original line number Diff line number Diff line
@@ -213,7 +213,7 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
    private void setupVibrate() {
        mVibrate = (RestrictedSwitchPreference) findPreference(KEY_VIBRATE);
        mVibrate.setDisabledByAdmin(mSuspendedAppsAdmin);
        mVibrate.setEnabled(!(mAppRow.lockedImportance || mVibrate.isDisabledByAdmin()));
        mVibrate.setEnabled(!mVibrate.isDisabledByAdmin() && isChannelConfigurable(mChannel));
        mVibrate.setChecked(mChannel.shouldVibrate());
        mVibrate.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
@@ -230,7 +230,7 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
    private void setupRingtone() {
        mRingtone = (NotificationSoundPreference) findPreference(KEY_RINGTONE);
        mRingtone.setRingtone(mChannel.getSound());
        mRingtone.setEnabled(!(mAppRow.lockedImportance));
        mRingtone.setEnabled(isChannelConfigurable(mChannel));
        mRingtone.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
@@ -286,7 +286,7 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
        channelArgs.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
        channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
        channelArgs.putString(Settings.EXTRA_CHANNEL_ID, mChannel.getId());
        mImportance.setEnabled(mSuspendedAppsAdmin == null && !mAppRow.lockedImportance);
        mImportance.setEnabled(mSuspendedAppsAdmin == null && isChannelConfigurable(mChannel));
        // Set up intent to show importance selection only if this setting is enabled.
        if (mImportance.isEnabled()) {
            Intent channelIntent = Utils.onBuildStartFragmentIntent(getActivity(),
+17 −2
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.os.UserHandle;
import android.util.IconDrawableFactory;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.Utils;

public class NotificationBackend {
@@ -60,15 +61,28 @@ public class NotificationBackend {
        row.systemApp = Utils.isSystemPackage(context.getResources(), pm, app);
        final String[] nonBlockablePkgs = context.getResources().getStringArray(
                    com.android.internal.R.array.config_nonBlockableNotificationPackages);
        markAppRowWithBlockables(nonBlockablePkgs, row, app.packageName);
        return row;
    }

    @VisibleForTesting static void markAppRowWithBlockables(String[] nonBlockablePkgs, AppRow row,
            String packageName) {
        if (nonBlockablePkgs != null) {
            int N = nonBlockablePkgs.length;
            for (int i = 0; i < N; i++) {
                if (app.packageName.equals(nonBlockablePkgs[i])) {
                String pkg = nonBlockablePkgs[i];
                if (pkg == null) {
                    continue;
                } else if (pkg.contains(":")) {
                    // Interpret as channel; lock only this channel for this app.
                    if (packageName.equals(pkg.split(":", 2)[0])) {
                        row.lockedChannelId = pkg.split(":", 2 )[1];
                    }
                } else if (packageName.equals(nonBlockablePkgs[i])) {
                    row.systemApp = row.lockedImportance = true;
                }
            }
        }
        return row;
    }

    public boolean getNotificationsBanned(String pkg, int uid) {
@@ -184,6 +198,7 @@ public class NotificationBackend {
        public boolean first;  // first app in section
        public boolean systemApp;
        public boolean lockedImportance;
        public String lockedChannelId;
        public boolean showBadge;
        public int userId;
    }
+8 −3
Original line number Diff line number Diff line
@@ -293,8 +293,8 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
    private void setupImportanceToggle() {
        mImportanceToggle = (RestrictedSwitchPreference) findPreference(KEY_ALLOW_SOUND);
        mImportanceToggle.setDisabledByAdmin(mSuspendedAppsAdmin);
        mImportanceToggle.setEnabled(!(mAppRow.lockedImportance
                || mImportanceToggle.isDisabledByAdmin()));
        mImportanceToggle.setEnabled(isChannelConfigurable(mChannel)
                && !mImportanceToggle.isDisabledByAdmin());
        mImportanceToggle.setChecked(mChannel.getImportance() >= IMPORTANCE_DEFAULT
                || mChannel.getImportance() == IMPORTANCE_UNSPECIFIED);
        mImportanceToggle.setOnPreferenceChangeListener(
@@ -315,7 +315,7 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
    protected void setupPriorityPref(boolean priority) {
        mPriority = (RestrictedSwitchPreference) findPreference(KEY_BYPASS_DND);
        mPriority.setDisabledByAdmin(mSuspendedAppsAdmin);
        mPriority.setEnabled(!(mAppRow.lockedImportance || mPriority.isDisabledByAdmin()));
        mPriority.setEnabled(isChannelConfigurable(mChannel) && !mPriority.isDisabledByAdmin());
        mPriority.setChecked(priority);
        mPriority.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
@@ -447,10 +447,15 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
        return lockscreenSecure;
    }

    protected boolean isChannelConfigurable(NotificationChannel channel) {
        return !channel.getId().equals(mAppRow.lockedChannelId);
    }

    protected boolean isChannelBlockable(boolean systemApp, NotificationChannel channel) {
        if (!mAppRow.systemApp) {
            return true;
        }

        return channel.isBlockableSystem()
                || channel.getImportance() == NotificationManager.IMPORTANCE_NONE;
    }
+134 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.notification;

import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.support.v7.preference.Preference;

import com.android.settings.R;
import com.android.settings.notification.NotificationBackend.AppRow;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import org.robolectric.annotation.Config;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;


@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class NotificationBackendTest {

    @Test
    public void testMarkAppRow_unblockablePackage() {
        AppRow appRow = new AppRow();
        String packageName = "foo.bar.unblockable";
        appRow.pkg = packageName;
        String[] nonBlockablePkgs = new String[2];
        nonBlockablePkgs[0] = packageName;
        nonBlockablePkgs[1] = "some.other.package";
        NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, appRow, packageName);

        // This package has a package lock but no locked channels
        assertTrue(appRow.lockedImportance);
        assertNull(appRow.lockedChannelId);
    }

    @Test
    public void testMarkAppRow_unblockableChannelOrPkg() {
        String channelBlockName = "foo.bar.pkgWithChannel";
        String pkgBlockName = "foo.bar.pkgBlock";
        String[] nonBlockablePkgs = new String[2];
        nonBlockablePkgs[0] = pkgBlockName;
        nonBlockablePkgs[1] = channelBlockName + ":SpecificChannel";

        // This package has a channel level lock but no full package lock
        AppRow channelBlockApp = new AppRow();
        channelBlockApp.pkg = channelBlockName;
        NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, channelBlockApp,
                channelBlockName);
        assertFalse(channelBlockApp.lockedImportance);
        assertEquals("SpecificChannel", channelBlockApp.lockedChannelId);

        // This other package has the reverse
        AppRow pkgBlock = new AppRow();
        pkgBlock.pkg = pkgBlockName;
        NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, pkgBlock, pkgBlockName);
        assertTrue(pkgBlock.lockedImportance);
        assertNull(pkgBlock.lockedChannelId);

        // This third package has no locks at all
        AppRow otherAppRow = new AppRow();
        otherAppRow.pkg ="foo.bar.nothingBlocked";
        NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, otherAppRow,
                "foo.bar.nothingBlocked");
        assertFalse(otherAppRow.lockedImportance);
        assertNull(otherAppRow.lockedChannelId);
    }

    @Test
    public void testMarkAppRow_unblockableChannelAndPkg() {
        AppRow appRow = new AppRow();
        String packageName = "foo.bar.unblockable";
        appRow.pkg = packageName;
        String[] nonBlockablePkgs = new String[2];
        nonBlockablePkgs[0] = "foo.bar.unblockable";
        nonBlockablePkgs[1] = "foo.bar.unblockable:SpecificChannel";
        NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, appRow, packageName);

        // This package has both a channel lock and a package lock
        assertTrue(appRow.lockedImportance);
        assertEquals("SpecificChannel", appRow.lockedChannelId);
    }

    @Test
    public void testMarkAppRow_channelNameWithColons() {
        AppRow appRow = new AppRow();
        String packageName = "foo.bar.unblockable";
        String channelName = "SpecificChannel:1234:abc:defg";
        appRow.pkg = packageName;
        String[] nonBlockablePkgs = new String[1];
        nonBlockablePkgs[0] = packageName + ":" + channelName;
        NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, appRow, packageName);

        assertEquals(channelName, appRow.lockedChannelId);
    }


    @Test
    public void testMarkAppRow_blocklistWithNullEntries() {
        AppRow appRow = new AppRow();
        String packageName = "foo.bar.unblockable";
        appRow.pkg = packageName;
        String[] nonBlockablePkgs = new String[6]; // extra long list with some entries left null
        nonBlockablePkgs[2] = "foo.bar.unblockable";
        nonBlockablePkgs[4] = "foo.bar.unblockable:SpecificChannel";
        NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, appRow, packageName);

        assertTrue(appRow.lockedImportance);
        assertEquals("SpecificChannel", appRow.lockedChannelId);
    }
}