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

Commit 02a1c080 authored by Denis Kuznetsov's avatar Denis Kuznetsov
Browse files

Add notification on succesful backups

Bug: 63885845
Test: make RunFrameworksServicesRoboTests

Change-Id: I6c8d04de7f5d7e82d695b1bf36de0aa27452db19
parent 23012115
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -7252,8 +7252,11 @@ public final class Settings {
         * full_backup_interval_milliseconds       (long)
         * full_backup_require_charging            (boolean)
         * full_backup_required_network_type       (int)
         * backup_finished_notification_receivers  (String[])
         * </pre>
         *
         * backup_finished_notification_receivers uses ":" as delimeter for values.
         *
         * <p>
         * Type: string
         * @hide
+21 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.KeyValueListParser;
import android.util.Slog;

@@ -51,6 +52,8 @@ class BackupManagerConstants extends ContentObserver {
            "full_backup_require_charging";
    private static final String FULL_BACKUP_REQUIRED_NETWORK_TYPE =
            "full_backup_required_network_type";
    private static final String BACKUP_FINISHED_NOTIFICATION_RECEIVERS =
            "backup_finished_notification_receivers";

    // Hard coded default values.
    private static final long DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS =
@@ -63,6 +66,7 @@ class BackupManagerConstants extends ContentObserver {
            24 * AlarmManager.INTERVAL_HOUR;
    private static final boolean DEFAULT_FULL_BACKUP_REQUIRE_CHARGING = true;
    private static final int DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE = 2;
    private static final String DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS = "";

    // Backup manager constants.
    private long mKeyValueBackupIntervalMilliseconds;
@@ -72,6 +76,7 @@ class BackupManagerConstants extends ContentObserver {
    private long mFullBackupIntervalMilliseconds;
    private boolean mFullBackupRequireCharging;
    private int mFullBackupRequiredNetworkType;
    private String[] mBackupFinishedNotificationReceivers;

    private ContentResolver mResolver;
    private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -116,6 +121,14 @@ class BackupManagerConstants extends ContentObserver {
                DEFAULT_FULL_BACKUP_REQUIRE_CHARGING);
        mFullBackupRequiredNetworkType = mParser.getInt(FULL_BACKUP_REQUIRED_NETWORK_TYPE,
                DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE);
        final String backupFinishedNotificationReceivers = mParser.getString(
                BACKUP_FINISHED_NOTIFICATION_RECEIVERS,
                DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS);
        if (backupFinishedNotificationReceivers.isEmpty()) {
            mBackupFinishedNotificationReceivers = new String[] {};
        } else {
            mBackupFinishedNotificationReceivers = backupFinishedNotificationReceivers.split(":");
        }
    }

    // The following are access methods for the individual parameters.
@@ -167,7 +180,6 @@ class BackupManagerConstants extends ContentObserver {
            Slog.v(TAG, "getFullBackupRequireCharging(...) returns " + mFullBackupRequireCharging);
        }
        return mFullBackupRequireCharging;

    }

    public synchronized int getFullBackupRequiredNetworkType() {
@@ -177,4 +189,12 @@ class BackupManagerConstants extends ContentObserver {
        }
        return mFullBackupRequiredNetworkType;
    }

    public synchronized String[] getBackupFinishedNotificationReceivers() {
        if (RefactoredBackupManagerService.DEBUG_SCHEDULING) {
            Slog.v(TAG, "getBackupFinishedNotificationReceivers(...) returns "
                    + TextUtils.join(", ", mBackupFinishedNotificationReceivers));
        }
        return mBackupFinishedNotificationReceivers;
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -203,6 +203,8 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter

    public static final String RUN_BACKUP_ACTION = "android.app.backup.intent.RUN";
    public static final String RUN_INITIALIZE_ACTION = "android.app.backup.intent.INIT";
    public static final String BACKUP_FINISHED_ACTION = "android.intent.action.BACKUP_FINISHED";
    public static final String BACKUP_FINISHED_PACKAGE_EXTRA = "packageName";

    // Timeout interval for deciding that a bind or clear-data has taken too long
    private static final long TIMEOUT_INTERVAL = 10 * 1000;
@@ -1418,6 +1420,14 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
    public void logBackupComplete(String packageName) {
        if (packageName.equals(PACKAGE_MANAGER_SENTINEL)) return;

        for (String receiver : mConstants.getBackupFinishedNotificationReceivers()) {
            final Intent notification = new Intent();
            notification.setAction(BACKUP_FINISHED_ACTION);
            notification.setPackage(receiver);
            notification.putExtra(BACKUP_FINISHED_PACKAGE_EXTRA, packageName);
            mContext.sendBroadcastAsUser(notification, UserHandle.OWNER);
        }

        mProcessedPackagesJournal.addPackage(packageName);
    }

+109 −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.server.backup;

import android.app.AlarmManager;
import android.content.Context;
import android.os.Handler;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;

import com.android.server.backup.testing.ShadowBackupTransportStub;
import com.android.server.backup.testing.ShadowContextImplForBackup;
import com.android.server.backup.testing.ShadowPackageManagerForBackup;
import com.android.server.testing.FrameworkRobolectricTestRunner;
import com.android.server.testing.SystemLoaderClasses;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

import static com.google.common.truth.Truth.assertThat;

@RunWith(FrameworkRobolectricTestRunner.class)
@Config(
        manifest = Config.NONE,
        sdk = 26,
        shadows = {
                ShadowContextImplForBackup.class,
                ShadowBackupTransportStub.class,
                ShadowPackageManagerForBackup.class
        }
)
@SystemLoaderClasses({TransportManager.class})
@Presubmit
public class BackupManagerConstantsTest {
    private static final String PACKAGE_NAME = "some.package.name";
    private static final String ANOTHER_PACKAGE_NAME = "another.package.name";

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void testDefaultValues() throws Exception {
        final Context context = RuntimeEnvironment.application.getApplicationContext();
        final Handler handler = new Handler();

        Settings.Secure.putString(context.getContentResolver(),
                Settings.Secure.BACKUP_MANAGER_CONSTANTS, null);

        final BackupManagerConstants constants =
                new BackupManagerConstants(handler, context.getContentResolver());
        constants.start();

        assertThat(constants.getKeyValueBackupIntervalMilliseconds())
                .isEqualTo(4 * AlarmManager.INTERVAL_HOUR);
        assertThat(constants.getKeyValueBackupFuzzMilliseconds()).isEqualTo(10 * 60 * 1000);
        assertThat(constants.getKeyValueBackupRequireCharging()).isEqualTo(true);
        assertThat(constants.getKeyValueBackupRequiredNetworkType()).isEqualTo(1);

        assertThat(constants.getFullBackupIntervalMilliseconds())
                .isEqualTo(24 * AlarmManager.INTERVAL_HOUR);
        assertThat(constants.getFullBackupRequireCharging()).isEqualTo(true);
        assertThat(constants.getFullBackupRequiredNetworkType()).isEqualTo(2);
        assertThat(constants.getBackupFinishedNotificationReceivers()).isEqualTo(new String[0]);
    }

    @Test
    public void testParseNotificationReceivers() throws Exception {
        final Context context = RuntimeEnvironment.application.getApplicationContext();
        final Handler handler = new Handler();

        final String recievers_setting = "backup_finished_notification_receivers=" +
                PACKAGE_NAME + ':' + ANOTHER_PACKAGE_NAME;
        Settings.Secure.putString(context.getContentResolver(),
                Settings.Secure.BACKUP_MANAGER_CONSTANTS, recievers_setting);

        final BackupManagerConstants constants =
                new BackupManagerConstants(handler, context.getContentResolver());
        constants.start();

        assertThat(constants.getBackupFinishedNotificationReceivers()).isEqualTo(new String[] {
                PACKAGE_NAME,
                ANOTHER_PACKAGE_NAME});
    }
}