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

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

Merge "Handle usageevents for work profile apps"

parents 48cdfcb3 cb691873
Loading
Loading
Loading
Loading
+72 −13
Original line number Diff line number Diff line
@@ -15,9 +15,13 @@
 */
package com.android.settings.applications;

import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.view.View;
@@ -25,6 +29,7 @@ import android.view.ViewGroup;
import android.widget.Switch;

import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
@@ -33,6 +38,7 @@ import com.android.settingslib.utils.StringUtil;

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

/**
@@ -42,17 +48,24 @@ import java.util.Map;
public class AppStateNotificationBridge extends AppStateBaseBridge {

    private final Context mContext;
    private UsageStatsManager mUsageStatsManager;
    private IUsageStatsManager mUsageStatsManager;
    protected List<Integer> mUserIds;
    private NotificationBackend mBackend;
    private static final int DAYS_TO_CHECK = 7;

    public AppStateNotificationBridge(Context context, ApplicationsState appState,
            Callback callback, UsageStatsManager usageStatsManager,
            NotificationBackend backend) {
            Callback callback, IUsageStatsManager usageStatsManager,
            UserManager userManager, NotificationBackend backend) {
        super(appState, callback);
        mContext = context;
        mUsageStatsManager = usageStatsManager;
        mBackend = backend;
        mUserIds = new ArrayList<>();
        mUserIds.add(mContext.getUserId());
        int workUserId = Utils.getManagedProfileId(userManager, mContext.getUserId());
        if (workUserId != UserHandle.USER_NULL) {
            mUserIds.add(workUserId);
        }
    }

    @Override
@@ -62,7 +75,8 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {

        final Map<String, NotificationsSentState> map = getAggregatedUsageEvents();
        for (AppEntry entry : apps) {
            NotificationsSentState stats = map.get(entry.info.packageName);
            NotificationsSentState stats =
                    map.get(getKey(UserHandle.getUserId(entry.info.uid), entry.info.packageName));
            calculateAvgSentCounts(stats);
            addBlockStatus(entry, stats);
            entry.extraInfo = stats;
@@ -71,8 +85,8 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {

    @Override
    protected void updateExtraInfo(AppEntry entry, String pkg, int uid) {
        Map<String, NotificationsSentState> map = getAggregatedUsageEvents();
        NotificationsSentState stats = map.get(entry.info.packageName);
        NotificationsSentState stats = getAggregatedUsageEvents(
                UserHandle.getUserId(entry.info.uid), entry.info.packageName);
        calculateAvgSentCounts(stats);
        addBlockStatus(entry, stats);
        entry.extraInfo = stats;
@@ -116,15 +130,23 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {

        long now = System.currentTimeMillis();
        long startTime = now - (DateUtils.DAY_IN_MILLIS * DAYS_TO_CHECK);
        UsageEvents events = mUsageStatsManager.queryEvents(startTime, now);
        for (int userId : mUserIds) {
            UsageEvents events = null;
            try {
                events = mUsageStatsManager.queryEventsForUser(
                        startTime, now, userId, mContext.getPackageName());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            if (events != null) {
                UsageEvents.Event event = new UsageEvents.Event();
                while (events.hasNextEvent()) {
                    events.getNextEvent(event);
                NotificationsSentState stats = aggregatedStats.get(event.getPackageName());
                    NotificationsSentState stats =
                            aggregatedStats.get(getKey(userId, event.getPackageName()));
                    if (stats == null) {
                        stats = new NotificationsSentState();
                    aggregatedStats.put(event.getPackageName(), stats);
                        aggregatedStats.put(getKey(userId, event.getPackageName()), stats);
                    }

                    if (event.getEventType() == UsageEvents.Event.NOTIFICATION_INTERRUPTION) {
@@ -136,9 +158,42 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {

                }
            }
        }
        return aggregatedStats;
    }

    protected NotificationsSentState getAggregatedUsageEvents(int userId, String pkg) {
        NotificationsSentState stats = null;

        long now = System.currentTimeMillis();
        long startTime = now - (DateUtils.DAY_IN_MILLIS * DAYS_TO_CHECK);
        UsageEvents events = null;
        try {
            events = mUsageStatsManager.queryEventsForPackageForUser(
                    startTime, now, userId, pkg, mContext.getPackageName());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        if (events != null) {
            UsageEvents.Event event = new UsageEvents.Event();
            while (events.hasNextEvent()) {
                events.getNextEvent(event);

                if (event.getEventType() == UsageEvents.Event.NOTIFICATION_INTERRUPTION) {
                    if (stats == null) {
                        stats = new NotificationsSentState();
                    }
                    if (event.getTimeStamp() > stats.lastSent) {
                        stats.lastSent = event.getTimeStamp();
                    }
                    stats.sentCount++;
                }

            }
        }
        return stats;
    }

    private static NotificationsSentState getNotificationsSentState(AppEntry entry) {
        if (entry == null || entry.extraInfo == null) {
            return null;
@@ -149,6 +204,10 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {
        return null;
    }

    protected static String getKey(int userId, String pkg) {
        return userId + "|" + pkg;
    }

    public View.OnClickListener getSwitchOnClickListener(final AppEntry entry) {
        if (entry != null) {
            return v -> {
+8 −3
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import static com.android.settings.applications.manageapplications.AppFilterRegi
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.app.Activity;
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
@@ -48,6 +49,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
import android.os.Bundle;
import android.os.Environment;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.PreferenceFrameLayout;
@@ -224,7 +226,8 @@ public class ManageApplications extends InstrumentedFragment
    private View mSpinnerHeader;
    private Spinner mFilterSpinner;
    private FilterSpinnerAdapter mFilterAdapter;
    private UsageStatsManager mUsageStatsManager;
    private IUsageStatsManager mUsageStatsManager;
    private UserManager mUserManager;
    private NotificationBackend mNotificationBackend;
    private ResetAppsHelper mResetAppsHelper;
    private String mVolumeUuid;
@@ -294,8 +297,9 @@ public class ManageApplications extends InstrumentedFragment
            screenTitle = R.string.change_wifi_state_title;
        } else if (className.equals(Settings.NotificationAppListActivity.class.getName())) {
            mListType = LIST_TYPE_NOTIFICATION;
            mUsageStatsManager =
                    (UsageStatsManager) getContext().getSystemService(Context.USAGE_STATS_SERVICE);
            mUsageStatsManager = IUsageStatsManager.Stub.asInterface(
                    ServiceManager.getService(Context.USAGE_STATS_SERVICE));
            mUserManager = UserManager.get(getContext());
            mNotificationBackend = new NotificationBackend();
            mSortOrder = R.id.sort_order_recent_notification;
            screenTitle = R.string.app_notifications_title;
@@ -889,6 +893,7 @@ public class ManageApplications extends InstrumentedFragment
            if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
                mExtraInfoBridge = new AppStateNotificationBridge(mContext, mState, this,
                        manageApplications.mUsageStatsManager,
                        manageApplications.mUserManager,
                        manageApplications.mNotificationBackend);
            } else if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
                mExtraInfoBridge = new AppStateUsageBridge(mContext, mState, this);
+102 −28
Original line number Diff line number Diff line
@@ -36,17 +36,21 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Looper;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.view.ViewGroup;
import android.widget.Switch;

@@ -79,7 +83,9 @@ public class AppStateNotificationBridgeTest {
    @Mock
    private ApplicationsState mState;
    @Mock
    private UsageStatsManager mUsageStats;
    private IUsageStatsManager mUsageStats;
    @Mock
    private UserManager mUserManager;
    @Mock
    private NotificationBackend mBackend;
    private Context mContext;
@@ -92,10 +98,12 @@ public class AppStateNotificationBridgeTest {
        when(mState.getBackgroundLooper()).thenReturn(mock(Looper.class));
        when(mBackend.getNotificationsBanned(anyString(), anyInt())).thenReturn(true);
        when(mBackend.isSystemApp(any(), any())).thenReturn(true);
        // most tests assume no work profile
        when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
        mContext = RuntimeEnvironment.application.getApplicationContext();

        mBridge = new AppStateNotificationBridge(mContext, mState,
                mock(AppStateBaseBridge.Callback.class), mUsageStats, mBackend);
                mock(AppStateBaseBridge.Callback.class), mUsageStats, mUserManager, mBackend);
    }

    private AppEntry getMockAppEntry(String pkg) {
@@ -115,14 +123,15 @@ public class AppStateNotificationBridgeTest {
    }

    @Test
    public void testGetAggregatedUsageEvents_noEvents() {
        when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(mock(UsageEvents.class));
    public void testGetAggregatedUsageEvents_noEvents() throws Exception {
        when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString()))
                .thenReturn(mock(UsageEvents.class));

        assertThat(mBridge.getAggregatedUsageEvents()).isEmpty();
    }

    @Test
    public void testGetAggregatedUsageEvents_onlyNotificationEvents() {
    public void testGetAggregatedUsageEvents_onlyNotificationEvents() throws Exception {
        List<Event> events = new ArrayList<>();
        Event good = new Event();
        good.mEventType = Event.NOTIFICATION_INTERRUPTION;
@@ -136,14 +145,15 @@ public class AppStateNotificationBridgeTest {
        events.add(bad);

        UsageEvents usageEvents = getUsageEvents(events);
        when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
        when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString()))
                .thenReturn(usageEvents);

        Map<String, NotificationsSentState> map = mBridge.getAggregatedUsageEvents();
        assertThat(map.get(PKG1).sentCount).isEqualTo(1);
        assertThat(map.get(mBridge.getKey(0, PKG1)).sentCount).isEqualTo(1);
    }

    @Test
    public void testGetAggregatedUsageEvents_multipleEventsAgg() {
    public void testGetAggregatedUsageEvents_multipleEventsAgg() throws Exception {
        List<Event> events = new ArrayList<>();
        Event good = new Event();
        good.mEventType = Event.NOTIFICATION_INTERRUPTION;
@@ -157,15 +167,16 @@ public class AppStateNotificationBridgeTest {
        events.add(good1);

        UsageEvents usageEvents = getUsageEvents(events);
        when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
        when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString()))
                .thenReturn(usageEvents);

        Map<String, NotificationsSentState> map  = mBridge.getAggregatedUsageEvents();
        assertThat(map.get(PKG1).sentCount).isEqualTo(2);
        assertThat(map.get(PKG1).lastSent).isEqualTo(6);
        assertThat(map.get(mBridge.getKey(0, PKG1)).sentCount).isEqualTo(2);
        assertThat(map.get(mBridge.getKey(0, PKG1)).lastSent).isEqualTo(6);
    }

    @Test
    public void testGetAggregatedUsageEvents_multiplePkgs() {
    public void testGetAggregatedUsageEvents_multiplePkgs() throws Exception {
        List<Event> events = new ArrayList<>();
        Event good = new Event();
        good.mEventType = Event.NOTIFICATION_INTERRUPTION;
@@ -179,19 +190,21 @@ public class AppStateNotificationBridgeTest {
        events.add(good1);

        UsageEvents usageEvents = getUsageEvents(events);
        when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
        when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString()))
                .thenReturn(usageEvents);

        Map<String, NotificationsSentState> map
                = mBridge.getAggregatedUsageEvents();
        assertThat(map.get(PKG1).sentCount).isEqualTo(1);
        assertThat(map.get(PKG2).sentCount).isEqualTo(1);
        assertThat(map.get(PKG1).lastSent).isEqualTo(6);
        assertThat(map.get(PKG2).lastSent).isEqualTo(1);
        assertThat(map.get(mBridge.getKey(0, PKG1)).sentCount).isEqualTo(1);
        assertThat(map.get(mBridge.getKey(0, PKG2)).sentCount).isEqualTo(1);
        assertThat(map.get(mBridge.getKey(0, PKG1)).lastSent).isEqualTo(6);
        assertThat(map.get(mBridge.getKey(0, PKG2)).lastSent).isEqualTo(1);
    }

    @Test
    public void testLoadAllExtraInfo_noEvents() {
        when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(mock(UsageEvents.class));
    public void testLoadAllExtraInfo_noEvents() throws RemoteException {
        when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString()))
                .thenReturn(mock(UsageEvents.class));
        ArrayList<AppEntry> apps = new ArrayList<>();
        apps.add(getMockAppEntry(PKG1));
        when(mSession.getAllApps()).thenReturn(apps);
@@ -201,7 +214,7 @@ public class AppStateNotificationBridgeTest {
    }

    @Test
    public void testLoadAllExtraInfo_multipleEventsAgg() {
    public void testLoadAllExtraInfo_multipleEventsAgg() throws RemoteException {
        List<Event> events = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            Event good = new Event();
@@ -212,7 +225,8 @@ public class AppStateNotificationBridgeTest {
        }

        UsageEvents usageEvents = getUsageEvents(events);
        when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
        when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString()))
                .thenReturn(usageEvents);

        ArrayList<AppEntry> apps = new ArrayList<>();
        apps.add(getMockAppEntry(PKG1));
@@ -229,7 +243,7 @@ public class AppStateNotificationBridgeTest {
    }

    @Test
    public void testLoadAllExtraInfo_multiplePkgs() {
    public void testLoadAllExtraInfo_multiplePkgs() throws RemoteException {
        List<Event> events = new ArrayList<>();
        for (int i = 0; i < 8; i++) {
            Event good = new Event();
@@ -245,7 +259,8 @@ public class AppStateNotificationBridgeTest {
        events.add(good1);

        UsageEvents usageEvents = getUsageEvents(events);
        when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
        when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString()))
                .thenReturn(usageEvents);

        ArrayList<AppEntry> apps = new ArrayList<>();
        apps.add(getMockAppEntry(PKG1));
@@ -265,8 +280,66 @@ public class AppStateNotificationBridgeTest {
    }

    @Test
    public void testUpdateExtraInfo_noEvents() {
        when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(mock(UsageEvents.class));
    public void testLoadAllExtraInfo_multipleUsers() throws RemoteException {
        // has work profile
        when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{1});
        mBridge = new AppStateNotificationBridge(mContext, mState,
                mock(AppStateBaseBridge.Callback.class), mUsageStats, mUserManager, mBackend);

        List<Event> eventsProfileOwner = new ArrayList<>();
        for (int i = 0; i < 8; i++) {
            Event good = new Event();
            good.mEventType = Event.NOTIFICATION_INTERRUPTION;
            good.mPackage = PKG1;
            good.mTimeStamp = i;
            eventsProfileOwner.add(good);
        }

        List<Event> eventsProfile = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            Event good = new Event();
            good.mEventType = Event.NOTIFICATION_INTERRUPTION;
            good.mPackage = PKG1;
            good.mTimeStamp = i;
            eventsProfile.add(good);
        }

        UsageEvents usageEventsOwner = getUsageEvents(eventsProfileOwner);
        when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), eq(0), anyString()))
                .thenReturn(usageEventsOwner);

        UsageEvents usageEventsProfile = getUsageEvents(eventsProfile);
        when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), eq(1), anyString()))
                .thenReturn(usageEventsProfile);

        ArrayList<AppEntry> apps = new ArrayList<>();
        AppEntry owner = getMockAppEntry(PKG1);
        owner.info.uid = 1;
        apps.add(owner);

        AppEntry profile = getMockAppEntry(PKG1);
        profile.info.uid = UserHandle.PER_USER_RANGE + 1;
        apps.add(profile);
        when(mSession.getAllApps()).thenReturn(apps);

        mBridge.loadAllExtraInfo();

        assertThat(((NotificationsSentState) apps.get(0).extraInfo).sentCount).isEqualTo(8);
        assertThat(((NotificationsSentState) apps.get(0).extraInfo).lastSent).isEqualTo(7);
        assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentWeekly).isEqualTo(0);
        assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentDaily).isEqualTo(1);

        assertThat(((NotificationsSentState) apps.get(1).extraInfo).sentCount).isEqualTo(4);
        assertThat(((NotificationsSentState) apps.get(1).extraInfo).lastSent).isEqualTo(3);
        assertThat(((NotificationsSentState) apps.get(1).extraInfo).avgSentWeekly).isEqualTo(4);
        assertThat(((NotificationsSentState) apps.get(1).extraInfo).avgSentDaily).isEqualTo(1);
    }

    @Test
    public void testUpdateExtraInfo_noEvents() throws RemoteException {
        when(mUsageStats.queryEventsForPackageForUser(
                anyLong(), anyLong(), anyInt(), anyString(), anyString()))
                .thenReturn(mock(UsageEvents.class));
        AppEntry entry = getMockAppEntry(PKG1);

        mBridge.updateExtraInfo(entry, "", 0);
@@ -274,7 +347,7 @@ public class AppStateNotificationBridgeTest {
    }

    @Test
    public void testUpdateExtraInfo_multipleEventsAgg() {
    public void testUpdateExtraInfo_multipleEventsAgg() throws RemoteException {
        List<Event> events = new ArrayList<>();
        for (int i = 0; i < 13; i++) {
            Event good = new Event();
@@ -285,7 +358,8 @@ public class AppStateNotificationBridgeTest {
        }

        UsageEvents usageEvents = getUsageEvents(events);
        when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
        when(mUsageStats.queryEventsForPackageForUser(
                anyLong(), anyLong(), anyInt(), anyString(), anyString())).thenReturn(usageEvents);

        AppEntry entry = getMockAppEntry(PKG1);
        mBridge.updateExtraInfo(entry, "", 0);
+24 −8
Original line number Diff line number Diff line
@@ -16,14 +16,14 @@

package com.android.settings.applications.manageapplications;

import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_DRAGGING;
import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_ALL;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_MAIN;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_NOTIFICATION;
import static com.google.common.truth.Truth.assertThat;
import static com.android.settings.applications.manageapplications.AppFilterRegistry
        .FILTER_APPS_ALL;
import static com.android.settings.applications.manageapplications.ManageApplications
        .LIST_TYPE_MAIN;
import static com.android.settings.applications.manageapplications.ManageApplications
        .LIST_TYPE_NOTIFICATION;

import static junit.framework.Assert.assertEquals;
import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Matchers.any;
@@ -36,11 +36,14 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_DRAGGING;
import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Looper;
import androidx.recyclerview.widget.RecyclerView;
import android.os.UserManager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -63,6 +66,8 @@ import org.robolectric.util.ReflectionHelpers;

import java.util.ArrayList;

import androidx.recyclerview.widget.RecyclerView;

@RunWith(SettingsRobolectricTestRunner.class)
public class ManageApplicationsTest {

@@ -272,6 +277,10 @@ public class ManageApplicationsTest {
    @Test
    public void applicationsAdapter_onBindViewHolder_updateSwitch_notifications() {
        ManageApplications manageApplications = mock(ManageApplications.class);
        when(manageApplications.getActivity()).thenReturn(mock(Activity.class));
        UserManager um = mock(UserManager.class);
        when(um.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
        ReflectionHelpers.setField(manageApplications, "mUserManager", um);
        manageApplications.mListType = LIST_TYPE_NOTIFICATION;
        ApplicationViewHolder holder = mock(ApplicationViewHolder.class);
        ReflectionHelpers.setField(holder, "itemView", mock(View.class));
@@ -293,6 +302,9 @@ public class ManageApplicationsTest {
        manageApplications.mListType = LIST_TYPE_MAIN;
        ApplicationViewHolder holder = mock(ApplicationViewHolder.class);
        ReflectionHelpers.setField(holder, "itemView", mock(View.class));
        UserManager um = mock(UserManager.class);
        when(um.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
        ReflectionHelpers.setField(manageApplications, "mUserManager", um);
        ManageApplications.ApplicationsAdapter adapter =
                new ManageApplications.ApplicationsAdapter(mState,
                        manageApplications, mock(AppFilterItem.class),
@@ -308,6 +320,10 @@ public class ManageApplicationsTest {
    @Test
    public void sortOrderSavedOnRebuild() {
        ManageApplications manageApplications = mock(ManageApplications.class);
        when(manageApplications.getActivity()).thenReturn(mock(Activity.class));
        UserManager um = mock(UserManager.class);
        when(um.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
        ReflectionHelpers.setField(manageApplications, "mUserManager", um);
        manageApplications.mListType = LIST_TYPE_NOTIFICATION;
        manageApplications.mSortOrder = -1;
        ManageApplications.ApplicationsAdapter adapter =