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

Commit 987d14b8 authored by Julia Reynolds's avatar Julia Reynolds Committed by Android (Google) Code Review
Browse files

Merge "reduce number of binder calls when loading page" into main

parents 2bab900f a37572a4
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.notification.modes;

import android.annotation.Nullable;
import android.app.INotificationManager;
import android.app.ZenBypassingApp;
import android.content.ContentProvider;
import android.content.Context;
import android.content.pm.ParceledListSlice;
@@ -30,6 +31,7 @@ import android.os.UserManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.service.notification.ConversationChannelWrapper;
import android.util.ArrayMap;
import android.util.Log;

import androidx.annotation.NonNull;
@@ -41,8 +43,9 @@ import com.google.common.collect.ImmutableList;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
@@ -76,16 +79,20 @@ class ZenHelperBackend {
    }

    /**
     * Returns all of a user's packages that have at least one channel that will bypass DND
     * Returns a mapping between a user's packages that have at least one channel that will
     * bypass DND, and a Boolean indicating whether all of the package's channels bypass.
     */
    List<String> getPackagesBypassingDnd(int userId,
            boolean includeConversationChannels) {
    Map<String, Boolean> getPackagesBypassingDnd(int userId) {
        Map<String, Boolean> bypassingAppsMap = new HashMap<>();
        try {
            return mInm.getPackagesBypassingDnd(userId, includeConversationChannels);
            List<ZenBypassingApp> bypassingApps = mInm.getPackagesBypassingDnd(userId).getList();
            for (ZenBypassingApp zba : bypassingApps) {
                bypassingAppsMap.put(zba.getPkg(), zba.doAllChannelsBypass());
            }
        } catch (Exception e) {
            Log.w(TAG, "Error calling NoMan", e);
            return new ArrayList<>();
        }
        return bypassingAppsMap;
    }

    /** Returns all conversation channels for profiles of the current user. */
+27 −17
Original line number Diff line number Diff line
@@ -22,7 +22,9 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.core.text.BidiFormatter;
@@ -35,7 +37,6 @@ import com.android.settings.R;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.app.AppChannelsBypassingDndSettings;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
@@ -44,7 +45,9 @@ import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.AppPreference;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Adds a preference to the PreferenceScreen for each notification channel that can bypass DND.
@@ -54,7 +57,8 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
    public static final String KEY_NO_APPS = "all_none";
    private static final String KEY = "zen_mode_bypassing_apps_list";

    @Nullable private final NotificationBackend mNotificationBackend;
    @Nullable private final ZenHelperBackend mHelperBackend;
    private final UserManager mUserManager;

    @Nullable @VisibleForTesting ApplicationsState mApplicationsState;
    @VisibleForTesting PreferenceCategory mPreferenceCategory;
@@ -64,18 +68,18 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
    @Nullable private Fragment mHostFragment;

    public ZenModeAllBypassingAppsPreferenceController(Context context, @Nullable Application app,
            @Nullable Fragment host, @Nullable NotificationBackend notificationBackend) {
        this(context, app == null ? null : ApplicationsState.getInstance(app), host,
                notificationBackend);
            @Nullable Fragment host, @Nullable ZenHelperBackend helperBackend) {
        this(context, app == null ? null : ApplicationsState.getInstance(app), host, helperBackend);
    }

    private ZenModeAllBypassingAppsPreferenceController(Context context,
            @Nullable ApplicationsState appState, @Nullable Fragment host,
            @Nullable NotificationBackend notificationBackend) {
            @Nullable ZenHelperBackend helperBackend) {
        super(context);
        mNotificationBackend = notificationBackend;
        mApplicationsState = appState;
        mHostFragment = host;
        mHelperBackend = helperBackend;
        mUserManager = context.getSystemService(UserManager.class);

        if (mApplicationsState != null && host != null) {
            mAppSession = mApplicationsState.newSession(mAppSessionCallbacks, host.getLifecycle());
@@ -140,19 +144,25 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
        }

        boolean doAnyAppsPassCriteria = false;
        Map<Integer, Map<String, Boolean>> packagesBypassingDndByUser = new HashMap<>();
        for (UserHandle userHandle : mUserManager.getUserProfiles()) {
            packagesBypassingDndByUser.put(userHandle.getIdentifier(),
                    mHelperBackend.getPackagesBypassingDnd(userHandle.getIdentifier()));
        }
        for (ApplicationsState.AppEntry app : apps) {
            String pkg = app.info.packageName;
            final String key = getKey(pkg, app.info.uid);
            final int appChannels = mNotificationBackend.getChannelCount(pkg, app.info.uid);
            final int appChannelsBypassingDnd = mNotificationBackend
                    .getNotificationChannelsBypassingDnd(pkg, app.info.uid).getList().size();
            if (appChannelsBypassingDnd > 0) {
            boolean doesAppBypassDnd = false;
            int userId = UserHandle.getUserId(app.info.uid);
            Map<String, Boolean> packagesBypassingDnd =
                    packagesBypassingDndByUser.getOrDefault(userId, new HashMap<>());
            if (packagesBypassingDnd.containsKey(pkg)) {
                doAnyAppsPassCriteria = true;
                doesAppBypassDnd = true;
            }

            Preference pref = mPreferenceCategory.findPreference(key);
            if (pref == null) {
                if (appChannelsBypassingDnd > 0) {
                if (doesAppBypassDnd) {
                    // does not exist but should
                    pref = new AppPreference(mPrefContext);
                    pref.setKey(key);
@@ -172,14 +182,14 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
                    });
                    pref.setTitle(BidiFormatter.getInstance().unicodeWrap(app.label));
                    updateIcon(pref, app);
                    if (appChannels > appChannelsBypassingDnd) {
                        pref.setSummary(R.string.zen_mode_bypassing_apps_summary_some);
                    } else {
                    if (packagesBypassingDnd.get(pkg)) {
                        pref.setSummary(R.string.zen_mode_bypassing_apps_summary_all);
                    } else {
                        pref.setSummary(R.string.zen_mode_bypassing_apps_summary_some);
                    }
                    mPreferenceCategory.addPreference(pref);
                }
            } else if (appChannelsBypassingDnd == 0) {
            } else if (!doesAppBypassDnd) {
                // exists but shouldn't anymore
                mPreferenceCategory.removePreference(pref);
            }
+1 −2
Original line number Diff line number Diff line
@@ -161,8 +161,7 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
        Multimap<Integer, String> packagesBypassingDnd = HashMultimap.create();
        for (UserHandle userHandle : mUserManager.getUserProfiles()) {
            packagesBypassingDnd.putAll(userHandle.getIdentifier(),
                    mHelperBackend.getPackagesBypassingDnd(userHandle.getIdentifier(),
                            /* includeConversationChannels= */ false));
                    mHelperBackend.getPackagesBypassingDnd(userHandle.getIdentifier()).keySet());
        }

        return ImmutableList.copyOf(
+6 −4
Original line number Diff line number Diff line
@@ -48,15 +48,17 @@ public class ZenModeSelectBypassingAppsFragment extends ZenModeFragmentBase impl
        } else {
            app = null;
        }
        return buildPreferenceControllers(context, app, this, new NotificationBackend());
        return buildPreferenceControllers(context, app, this, new NotificationBackend(),
                new ZenHelperBackend(context));
    }

    private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
            @Nullable Application app, @Nullable Fragment host,
            @Nullable NotificationBackend notificationBackend) {
            @Nullable NotificationBackend notificationBackend,
            @Nullable ZenHelperBackend zenHelperBackend) {
        final List<AbstractPreferenceController> controllers = new ArrayList<>();
        controllers.add(new ZenModeAllBypassingAppsPreferenceController(context, app, host,
                notificationBackend));
                zenHelperBackend));
        controllers.add(new ZenModeAddBypassingAppsPreferenceController(context, app, host,
                notificationBackend));
        return controllers;
@@ -86,7 +88,7 @@ public class ZenModeSelectBypassingAppsFragment extends ZenModeFragmentBase impl
                @Override
                public List<AbstractPreferenceController> createPreferenceControllers(
                        Context context) {
                    return buildPreferenceControllers(context, null, null, null);
                    return buildPreferenceControllers(context, null, null, null, null);
                }
            };
}
+15 −11
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -28,10 +27,8 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Flags;
import android.app.NotificationChannel;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ParceledListSlice;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;

@@ -39,7 +36,6 @@ import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;

import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.applications.ApplicationsState;

import org.junit.Before;
@@ -54,6 +50,7 @@ import org.robolectric.RuntimeEnvironment;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@RunWith(RobolectricTestRunner.class)
@EnableFlags(Flags.FLAG_MODES_UI)
@@ -66,7 +63,7 @@ public class ZenModeAllBypassingAppsPreferenceControllerTest {

    private Context mContext;
    @Mock
    private NotificationBackend mBackend;
    private ZenHelperBackend mBackend;
    @Mock
    private PreferenceCategory mPreferenceCategory;
    @Mock
@@ -102,18 +99,25 @@ public class ZenModeAllBypassingAppsPreferenceControllerTest {
        entry2.info.packageName = "test2";
        entry2.info.uid = 0;

        ApplicationsState.AppEntry entry3= mock(ApplicationsState.AppEntry.class);
        entry3.info = new ApplicationInfo();
        entry3.info.packageName = "test3";
        entry3.info.uid = 0;

        List<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
        appEntries.add(entry1);
        appEntries.add(entry2);
        List<NotificationChannel> channelsBypassing = new ArrayList<>();
        channelsBypassing.add(mock(NotificationChannel.class));
        channelsBypassing.add(mock(NotificationChannel.class));
        when(mBackend.getNotificationChannelsBypassingDnd(anyString(),
                anyInt())).thenReturn(new ParceledListSlice<>(channelsBypassing));
        appEntries.add(entry3);
        when(mBackend.getPackagesBypassingDnd(anyInt())).thenReturn(
                Map.of("test", true, "test2", false));

        // THEN there's are two preferences
        mController.updateAppList(appEntries);
        verify(mPreferenceCategory, times(2)).addPreference(any());
        ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
        verify(mPreferenceCategory, times(2)).addPreference(captor.capture());
        List<Preference> prefs = captor.getAllValues();
        assertThat(prefs.get(0).getSummary().toString()).isEqualTo("All notifications");
        assertThat(prefs.get(1).getSummary().toString()).isEqualTo("Some notifications");
    }

    @Test
Loading