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

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

Merge "Persist incomplete pkg restore data for longer" into main

parents 9a58057c 36816072
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -2514,7 +2514,8 @@ public class NotificationManagerService extends SystemService {
                mNotificationChannelLogger,
                mAppOps,
                mUserProfiles,
                mShowReviewPermissionsNotification);
                mShowReviewPermissionsNotification,
                Clock.systemUTC());
        mRankingHelper = new RankingHelper(getContext(), mRankingHandler, mPreferencesHelper,
                mZenModeHelper, mUsageStats, extractorNames, mPlatformCompat);
        mSnoozeHelper = snoozeHelper;
+108 −68
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.io.PrintWriter;
import java.time.Clock;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -113,6 +115,8 @@ public class PreferencesHelper implements RankingConfig {
    private static final int XML_VERSION_REVIEW_PERMISSIONS_NOTIFICATION = 4;
    @VisibleForTesting
    static final int UNKNOWN_UID = UserHandle.USER_NULL;
    // The amount of time pacakage preferences can exist without the app being installed.
    private static final long PREF_GRACE_PERIOD_MS = Duration.ofDays(2).toMillis();

    @VisibleForTesting
    static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000;
@@ -149,6 +153,8 @@ public class PreferencesHelper implements RankingConfig {
    private static final String ATT_USER_DEMOTED_INVALID_MSG_APP = "user_demote_msg_app";
    private static final String ATT_SENT_VALID_BUBBLE = "sent_valid_bubble";

    private static final String ATT_CREATION_TIME = "creation_time";

    private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT;
    private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
    private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED;
@@ -208,11 +214,13 @@ public class PreferencesHelper implements RankingConfig {
    private boolean mHideSilentStatusBarIcons = DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS;
    private final boolean mShowReviewPermissionsNotification;

    Clock mClock;

    public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
            ZenModeHelper zenHelper, PermissionHelper permHelper, PermissionManager permManager,
            NotificationChannelLogger notificationChannelLogger,
            AppOpsManager appOpsManager, ManagedServices.UserProfiles userProfiles,
            boolean showReviewPermissionsNotification) {
            boolean showReviewPermissionsNotification, Clock clock) {
        mContext = context;
        mZenModeHelper = zenHelper;
        mRankingHandler = rankingHandler;
@@ -225,7 +233,7 @@ public class PreferencesHelper implements RankingConfig {
        mShowReviewPermissionsNotification = showReviewPermissionsNotification;
        mIsMediaNotificationFilteringEnabled = context.getResources()
                .getBoolean(R.bool.config_quickSettingsShowMediaPlayer);

        mClock = clock;
        XML_VERSION = 4;

        updateBadgingEnabled();
@@ -309,7 +317,7 @@ public class PreferencesHelper implements RankingConfig {
                    parser.getAttributeInt(null, ATT_PRIORITY, DEFAULT_PRIORITY),
                    parser.getAttributeInt(null, ATT_VISIBILITY, DEFAULT_VISIBILITY),
                    parser.getAttributeBoolean(null, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE),
                    bubblePref);
                    bubblePref, parser.getAttributeLong(null, ATT_CREATION_TIME, mClock.millis()));
            r.bubblePreference = bubblePref;
            r.priority = parser.getAttributeInt(null, ATT_PRIORITY, DEFAULT_PRIORITY);
            r.visibility = parser.getAttributeInt(null, ATT_VISIBILITY, DEFAULT_VISIBILITY);
@@ -463,12 +471,12 @@ public class PreferencesHelper implements RankingConfig {
        // TODO (b/194833441): use permissionhelper instead of DEFAULT_IMPORTANCE
        return getOrCreatePackagePreferencesLocked(pkg, UserHandle.getUserId(uid), uid,
                DEFAULT_IMPORTANCE, DEFAULT_PRIORITY, DEFAULT_VISIBILITY, DEFAULT_SHOW_BADGE,
                DEFAULT_BUBBLE_PREFERENCE);
                DEFAULT_BUBBLE_PREFERENCE, mClock.millis());
    }

    private PackagePreferences getOrCreatePackagePreferencesLocked(String pkg,
            @UserIdInt int userId, int uid, int importance, int priority, int visibility,
            boolean showBadge, int bubblePreference) {
            boolean showBadge, int bubblePreference, long creationTime) {
        final String key = packagePreferencesKey(pkg, uid);
        PackagePreferences
                r = (uid == UNKNOWN_UID)
@@ -483,6 +491,11 @@ public class PreferencesHelper implements RankingConfig {
            r.visibility = visibility;
            r.showBadge = showBadge;
            r.bubblePreference = bubblePreference;
            if (Flags.persistIncompleteRestoreData()) {
                if (r.uid == UNKNOWN_UID) {
                    r.creationTime = creationTime;
                }
            }

            try {
                createDefaultChannelIfNeededLocked(r);
@@ -496,6 +509,12 @@ public class PreferencesHelper implements RankingConfig {
                mPackagePreferences.put(key, r);
            }
        }
        if (r.uid == UNKNOWN_UID) {
            if (Flags.persistIncompleteRestoreData()
                    && PREF_GRACE_PERIOD_MS < (mClock.millis() - r.creationTime)) {
                mRestoredWithoutUids.remove(unrestoredPackageKey(pkg, userId));
            }
        }
        return r;
    }

@@ -590,6 +609,35 @@ public class PreferencesHelper implements RankingConfig {
                if (forBackup && UserHandle.getUserId(r.uid) != userId) {
                    continue;
                }
                writePackageXml(r, out, notifPermissions, forBackup);
            }
        }
        if (Flags.persistIncompleteRestoreData() && !forBackup) {
            synchronized (mRestoredWithoutUids) {
                final int N = mRestoredWithoutUids.size();
                for (int i = 0; i < N; i++) {
                    final PackagePreferences r = mRestoredWithoutUids.valueAt(i);
                    writePackageXml(r, out, notifPermissions, false);
                }
            }
        }
        // Some apps have permissions set but don't have expanded notification settings
        if (!notifPermissions.isEmpty()) {
            for (Pair<Integer, String> app : notifPermissions.keySet()) {
                out.startTag(null, TAG_PACKAGE);
                out.attribute(null, ATT_NAME, app.second);
                out.attributeInt(null, ATT_IMPORTANCE,
                        notifPermissions.get(app).first ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE);
                out.endTag(null, TAG_PACKAGE);
            }
        }
        out.endTag(null, TAG_RANKING);
    }

    public void writePackageXml(PackagePreferences r, TypedXmlSerializer out,
            ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> notifPermissions,
            boolean forBackup) throws
            IOException {
        out.startTag(null, TAG_PACKAGE);
        out.attribute(null, ATT_NAME, r.pkg);
        if (!notifPermissions.isEmpty()) {
@@ -624,6 +672,10 @@ public class PreferencesHelper implements RankingConfig {
                r.userDemotedMsgApp);
        out.attributeBoolean(null, ATT_SENT_VALID_BUBBLE, r.hasSentValidBubble);

        if (Flags.persistIncompleteRestoreData() && r.uid == UNKNOWN_UID) {
            out.attributeLong(null, ATT_CREATION_TIME, r.creationTime);
        }

        if (!forBackup) {
            out.attributeInt(null, ATT_UID, r.uid);
        }
@@ -655,19 +707,6 @@ public class PreferencesHelper implements RankingConfig {

        out.endTag(null, TAG_PACKAGE);
    }
        }
        // Some apps have permissions set but don't have expanded notification settings
        if (!notifPermissions.isEmpty()) {
            for (Pair<Integer, String> app : notifPermissions.keySet()) {
                out.startTag(null, TAG_PACKAGE);
                out.attribute(null, ATT_NAME, app.second);
                out.attributeInt(null, ATT_IMPORTANCE,
                        notifPermissions.get(app).first ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE);
                out.endTag(null, TAG_PACKAGE);
            }
        }
        out.endTag(null, TAG_RANKING);
    }

    /**
     * Sets whether bubbles are allowed.
@@ -2906,6 +2945,7 @@ public class PreferencesHelper implements RankingConfig {
        boolean hasSentValidBubble = false;

        boolean migrateToPm = false;
        long creationTime;

        Delegate delegate = null;
        ArrayMap<String, NotificationChannel> channels = new ArrayMap<>();
+6 −0
Original line number Diff line number Diff line
@@ -95,3 +95,9 @@ flag {
  bug: "331967355"
}

flag {
  name: "persist_incomplete_restore_data"
  namespace: "systemui"
  description: "Stores restore data for not-yet-installed pkgs for 48 hours"
  bug: "334999659"
}
+183 −10
Original line number Diff line number Diff line
@@ -46,10 +46,13 @@ import static android.media.AudioAttributes.USAGE_NOTIFICATION;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_SYSTEM;

import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.PROPAGATE_CHANNEL_UPDATES_TO_CONVERSATIONS;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED;
import static com.android.server.notification.Flags.FLAG_ALL_NOTIFS_NEED_TTL;
import static com.android.server.notification.Flags.FLAG_PERSIST_INCOMPLETE_RESTORE_DATA;
import static com.android.server.notification.NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_UPDATED_BY_USER;
import static com.android.server.notification.PreferencesHelper.DEFAULT_BUBBLE_PREFERENCE;
import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT;
@@ -110,6 +113,9 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.permission.PermissionManager;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.FlagsParameterization;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
@@ -140,6 +146,9 @@ import com.android.os.AtomsProto.PackageNotificationPreferences;
import com.android.server.UiServiceTestCase;
import com.android.server.notification.PermissionHelper.PackagePermission;

import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.protobuf.InvalidProtocolBufferException;
@@ -148,6 +157,7 @@ import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -160,6 +170,8 @@ import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.Clock;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -171,7 +183,7 @@ import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;

@SmallTest
@RunWith(AndroidJUnit4.class)
@RunWith(ParameterizedAndroidJunit4.class)
public class PreferencesHelperTest extends UiServiceTestCase {
    private static final int UID_HEADLESS = 1000000;
    private static final UserHandle USER = UserHandle.of(0);
@@ -212,6 +224,22 @@ public class PreferencesHelperTest extends UiServiceTestCase {
    private AudioAttributes mAudioAttributes;
    private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake();

    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);

    @Mock
    Clock mClock;

    @Parameters(name = "{0}")
    public static List<FlagsParameterization> getParams() {
        return FlagsParameterization.allCombinationsOf(
                FLAG_PERSIST_INCOMPLETE_RESTORE_DATA);
    }

    public PreferencesHelperTest(FlagsParameterization flags) {
        mSetFlagsRule.setFlagsParameterization(flags);
    }

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
@@ -326,13 +354,14 @@ public class PreferencesHelperTest extends UiServiceTestCase {
            currentProfileIds.add(UserHandle.getUserId(UID_HEADLESS));
        }
        when(mUserProfiles.getCurrentProfileIds()).thenReturn(currentProfileIds);
        when(mClock.millis()).thenReturn(System.currentTimeMillis());

        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                false);
                false, mClock);
        mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                false);
                false, mClock);
        resetZenModeHelper();

        mAudioAttributes = new AudioAttributes.Builder()
@@ -680,7 +709,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
    public void testReadXml_oldXml_migrates() throws Exception {
        mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                /* showReviewPermissionsNotification= */ true);
                /* showReviewPermissionsNotification= */ true, mClock);

        String xml = "<ranking version=\"2\">\n"
                + "<package name=\"" + PKG_N_MR1 + "\" uid=\"" + UID_N_MR1
@@ -816,7 +845,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
    public void testReadXml_newXml_noMigration_showPermissionNotification() throws Exception {
        mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                /* showReviewPermissionsNotification= */ true);
                /* showReviewPermissionsNotification= */ true, mClock);

        String xml = "<ranking version=\"3\">\n"
                + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -875,7 +904,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
    public void testReadXml_newXml_permissionNotificationOff() throws Exception {
        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                /* showReviewPermissionsNotification= */ false);
                /* showReviewPermissionsNotification= */ false, mClock);

        String xml = "<ranking version=\"3\">\n"
                + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -934,7 +963,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
    public void testReadXml_newXml_noMigration_noPermissionNotification() throws Exception {
        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                /* showReviewPermissionsNotification= */ true);
                /* showReviewPermissionsNotification= */ true, mClock);

        String xml = "<ranking version=\"4\">\n"
                + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -1010,7 +1039,8 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(1234);
        final ApplicationInfo app = new ApplicationInfo();
        app.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
        when(mPm.getApplicationInfoAsUser(eq("something"), anyInt(), anyInt())).thenReturn(app);
        when(mPm.getApplicationInfoAsUser(
                eq("something"), anyInt(), eq(USER_SYSTEM))).thenReturn(app);

        mXmlHelper.onPackagesChanged(false, 0, new String[] {"something"}, new int[] {1234});

@@ -1452,6 +1482,149 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        assertTrue(actualChannel.isSoundRestored());
    }

    @Test
    @EnableFlags(Flags.FLAG_PERSIST_INCOMPLETE_RESTORE_DATA)
    public void testRestoreXml_delayedRestore() throws Exception {
        // simulate package not installed
        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UNKNOWN_UID);
        when(mPm.getApplicationInfoAsUser(eq(PKG_R), anyInt(), anyInt())).thenThrow(
                new PackageManager.NameNotFoundException());
        when(mClock.millis()).thenReturn(System.currentTimeMillis());

        String id = "id";
        String xml = "<ranking version=\"1\">\n"
                + "<package name=\"" + PKG_R + "\" show_badge=\"true\">\n"
                + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" "
                + "show_badge=\"true\" />\n"
                + "</package>\n"
                + "</ranking>\n";

        loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM);

        // settings are not available with real uid because pkg is not installed
        assertThat(mXmlHelper.getNotificationChannel(PKG_R, UID_P, id, false)).isNull();
        // but the settings are in memory with unknown_uid
        assertThat(mXmlHelper.getNotificationChannel(PKG_R, UNKNOWN_UID, id, false)).isNotNull();

        // package is "installed"
        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UID_P);

        // Trigger 2nd restore pass
        mXmlHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_R},
                new int[]{UID_P});

        NotificationChannel channel = mXmlHelper.getNotificationChannel(PKG_R, UID_P, id,
                false);
        assertThat(channel.getImportance()).isEqualTo(2);
        assertThat(channel.canShowBadge()).isTrue();
        assertThat(channel.canBypassDnd()).isFalse();

        // removed from 'pending install' set
        assertThat(mXmlHelper.getNotificationChannel(PKG_R, UNKNOWN_UID, id,false)).isNull();
    }

    @Test
    @EnableFlags(Flags.FLAG_PERSIST_INCOMPLETE_RESTORE_DATA)
    public void testRestoreXml_delayedRestore_afterReboot() throws Exception {
        // load restore data
        ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
        appPermissions.put(new Pair<>(UID_R, PKG_R), new Pair<>(true, false));
        when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM))
                .thenReturn(appPermissions);

        // simulate package not installed
        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UNKNOWN_UID);
        when(mPm.getApplicationInfoAsUser(eq(PKG_R), anyInt(), anyInt())).thenThrow(
                new PackageManager.NameNotFoundException());
        when(mClock.millis()).thenReturn(System.currentTimeMillis());

        String id = "id";
        String xml = "<ranking version=\"1\">\n"
                + "<package name=\"" + PKG_R + "\" show_badge=\"true\">\n"
                + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" "
                + "show_badge=\"true\" />\n"
                + "</package>\n"
                + "</ranking>\n";

        loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM);

        // simulate write to disk
        TypedXmlSerializer serializer = Xml.newFastSerializer();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
        serializer.startDocument(null, true);
        mXmlHelper.writeXml(serializer, false, USER_SYSTEM);
        serializer.endDocument();
        serializer.flush();

        // simulate load after reboot
        mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                false, mClock);
        loadByteArrayXml(baos.toByteArray(), false, USER_SYSTEM);

        // Trigger 2nd restore pass
        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UID_P);
        mXmlHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_R},
                new int[]{UID_P});

        NotificationChannel channel = mXmlHelper.getNotificationChannel(PKG_R, UID_P, id,
                false);
        assertThat(channel.getImportance()).isEqualTo(2);
        assertThat(channel.canShowBadge()).isTrue();
        assertThat(channel.canBypassDnd()).isFalse();
    }

    @Test
    @EnableFlags(Flags.FLAG_PERSIST_INCOMPLETE_RESTORE_DATA)
    public void testRestoreXml_delayedRestore_packageMissingAfterTwoDays() throws Exception {
        // load restore data
        ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
        appPermissions.put(new Pair<>(UID_R, PKG_R), new Pair<>(true, false));
        when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM))
                .thenReturn(appPermissions);

        // simulate package not installed
        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UNKNOWN_UID);
        when(mPm.getApplicationInfoAsUser(eq(PKG_R), anyInt(), anyInt())).thenThrow(
                new PackageManager.NameNotFoundException());

        String id = "id";
        String xml = "<ranking version=\"1\">\n"
                + "<package name=\"" + PKG_R + "\" show_badge=\"true\">\n"
                + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" "
                + "show_badge=\"true\" />\n"
                + "</package>\n"
                + "</ranking>\n";

        loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM);

        // simulate write to disk
        TypedXmlSerializer serializer = Xml.newFastSerializer();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
        serializer.startDocument(null, true);
        mXmlHelper.writeXml(serializer, false, USER_SYSTEM);
        serializer.endDocument();
        serializer.flush();

        // advance time by 2 days
        when(mClock.millis()).thenReturn(
                Duration.ofDays(2).toMillis() + System.currentTimeMillis());

        // simulate load after reboot
        mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                false, mClock);
        loadByteArrayXml(xml.getBytes(), false, USER_SYSTEM);

        // Trigger 2nd restore pass
        mXmlHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_R},
                new int[]{UID_P});

        // verify the 2nd restore pass failed because the restore data had been removed
        assertThat(mXmlHelper.getNotificationChannel(PKG_R, UNKNOWN_UID, id, false)).isNull();
    }

    /**
     * Although we don't make backups with uncanonicalized uris anymore, we used to, so we have to
@@ -1520,10 +1693,10 @@ public class PreferencesHelperTest extends UiServiceTestCase {

        mHelper = new PreferencesHelper(mContext, mPm, mHandler, mMockZenModeHelper,
                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                false);
                false, mClock);
        mXmlHelper = new PreferencesHelper(mContext, mPm, mHandler, mMockZenModeHelper,
                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                false);
                false, mClock);

        NotificationChannel channel =
                new NotificationChannel("id", "name", IMPORTANCE_LOW);