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

Commit 2de1d857 authored by Chandan Nath's avatar Chandan Nath Committed by Android (Google) Code Review
Browse files

Merge "[Multi-user] No-op refactor to move backup dirs and settings, which...

Merge "[Multi-user] No-op refactor to move backup dirs and settings, which should be user-specific, to one class for each."
parents 570a4f0c 71508fda
Loading
Loading
Loading
Loading
+2 −48
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Environment;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -50,11 +49,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.SystemConfig;
import com.android.server.SystemService;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Set;
@@ -72,10 +67,6 @@ public class BackupManagerService {
    public static final boolean MORE_DEBUG = false;
    public static final boolean DEBUG_SCHEDULING = true;

    // File containing backup-enabled state. Contains a single byte to denote enabled status.
    // Nonzero is enabled; file missing or a zero byte is disabled.
    private static final String BACKUP_ENABLE_FILE = "backup_enabled";

    // The published binder is a singleton Trampoline object that calls through to the proper code.
    // This indirection lets us turn down the heavy implementation object on the fly without
    // disturbing binders that have been cached elsewhere in the system.
@@ -150,7 +141,8 @@ public class BackupManagerService {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
        try {
            // TODO(b/121198604): Make enable file per-user and clean up indirection.
            mTrampoline.setBackupEnabledForUser(userId, readBackupEnableState(userId));
            mTrampoline.setBackupEnabledForUser(
                    userId, UserBackupManagerFilePersistedSettings.readBackupEnableState(userId));
        } catch (RemoteException e) {
            // Can't happen, it's a local object.
        }
@@ -773,44 +765,6 @@ public class BackupManagerService {
        }
    }

    private static boolean readBackupEnableState(int userId) {
        File base = new File(Environment.getDataDirectory(), "backup");
        File enableFile = new File(base, BACKUP_ENABLE_FILE);
        if (enableFile.exists()) {
            try (FileInputStream fin = new FileInputStream(enableFile)) {
                int state = fin.read();
                return state != 0;
            } catch (IOException e) {
                // can't read the file; fall through to assume disabled
                Slog.e(TAG, "Cannot read enable state; assuming disabled");
            }
        } else {
            if (DEBUG) {
                Slog.i(TAG, "isBackupEnabled() => false due to absent settings file");
            }
        }
        return false;
    }

    static void writeBackupEnableState(boolean enable, int userId) {
        File base = new File(Environment.getDataDirectory(), "backup");
        File enableFile = new File(base, BACKUP_ENABLE_FILE);
        File stage = new File(base, BACKUP_ENABLE_FILE + "-stage");
        try (FileOutputStream fout = new FileOutputStream(stage)) {
            fout.write(enable ? 1 : 0);
            fout.close();
            stage.renameTo(enableFile);
            // will be synced immediately by the try-with-resources call to close()
        } catch (IOException | RuntimeException e) {
            Slog.e(
                    TAG,
                    "Unable to record backup enable state; reverting to disabled: "
                            + e.getMessage());
            enableFile.delete();
            stage.delete();
        }
    }

    /** Implementation to receive lifecycle event callbacks for system services. */
    public static final class Lifecycle extends SystemService {
        public Lifecycle(Context context) {
+78 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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 static com.android.server.backup.BackupManagerService.DEBUG;
import static com.android.server.backup.BackupManagerService.TAG;

import android.util.Slog;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/** User settings which are persisted across reboots. */
final class UserBackupManagerFilePersistedSettings {
    // File containing backup-enabled state. Contains a single byte to denote enabled status.
    // Nonzero is enabled; file missing or a zero byte is disabled.
    private static final String BACKUP_ENABLE_FILE = "backup_enabled";

    static boolean readBackupEnableState(int userId) {
        return readBackupEnableState(UserBackupManagerFiles.getBaseStateDir(userId));
    }

    static void writeBackupEnableState(int userId, boolean enable) {
        writeBackupEnableState(UserBackupManagerFiles.getBaseStateDir(userId), enable);
    }

    private static boolean readBackupEnableState(File baseDir) {
        File enableFile = new File(baseDir, BACKUP_ENABLE_FILE);
        if (enableFile.exists()) {
            try (FileInputStream fin = new FileInputStream(enableFile)) {
                int state = fin.read();
                return state != 0;
            } catch (IOException e) {
                // can't read the file; fall through to assume disabled
                Slog.e(TAG, "Cannot read enable state; assuming disabled");
            }
        } else {
            if (DEBUG) {
                Slog.i(TAG, "isBackupEnabled() => false due to absent settings file");
            }
        }
        return false;
    }

    private static void writeBackupEnableState(File baseDir, boolean enable) {
        File enableFile = new File(baseDir, BACKUP_ENABLE_FILE);
        File stage = new File(baseDir, BACKUP_ENABLE_FILE + "-stage");
        try (FileOutputStream fout = new FileOutputStream(stage)) {
            fout.write(enable ? 1 : 0);
            fout.close();
            stage.renameTo(enableFile);
            // will be synced immediately by the try-with-resources call to close()
        } catch (IOException | RuntimeException e) {
            Slog.e(
                    TAG,
                    "Unable to record backup enable state; reverting to disabled: "
                            + e.getMessage());
            enableFile.delete();
            stage.delete();
        }
    }
}
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.os.Environment;

import java.io.File;

/** Directories used for user specific backup/restore persistent state and book-keeping. */
public final class UserBackupManagerFiles {
    // Name of the directories the service stores bookkeeping data under.
    private static final String BACKUP_PERSISTENT_DIR = "backup";
    private static final String BACKUP_STAGING_DIR = "backup_stage";

    static File getBaseStateDir(int userId) {
        // TODO (b/120424138) this should be per user
        return new File(Environment.getDataDirectory(), BACKUP_PERSISTENT_DIR);
    }

    static File getDataDir(int userId) {
        // TODO (b/120424138) this should be per user
        // This dir on /cache is managed directly in init.rc
        return new File(Environment.getDownloadCacheDirectory(), BACKUP_STAGING_DIR);
    }

    /** Directory used by full backup engine to store state. */
    public static File getFullBackupEngineFilesDir(int userId) {
        // TODO (b/120424138) this should be per user
        return new File("/data/system");
    }
}
+6 −26
Original line number Diff line number Diff line
@@ -70,7 +70,6 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -164,17 +163,9 @@ import java.util.concurrent.atomic.AtomicInteger;

/** System service that performs backup/restore operations. */
public class UserBackupManagerService {
    // File containing backup-enabled state.  Contains a single byte;
    // nonzero == enabled.  File missing or contains a zero byte == disabled.
    private static final String BACKUP_ENABLE_FILE = "backup_enabled";

    // Persistently track the need to do a full init.
    private static final String INIT_SENTINEL_FILE_NAME = "_need_init_";

    // Name of the directories the service stores bookkeeping data under.
    private static final String BACKUP_PERSISTENT_DIR = "backup";
    private static final String BACKUP_STAGING_DIR = "backup_stage";

    // System-private key used for backing up an app's widget state.  Must
    // begin with U+FFxx by convention (we reserve all keys starting
    // with U+FF00 or higher for system use).
@@ -354,9 +345,9 @@ public class UserBackupManagerService {
    final AtomicInteger mNextToken = new AtomicInteger();

    // Where we keep our journal files and other bookkeeping.
    private File mBaseStateDir;
    private File mDataDir;
    private File mJournalDir;
    private final File mBaseStateDir;
    private final File mDataDir;
    private final File mJournalDir;
    @Nullable
    private DataChangedJournal mJournal;
    private File mFullBackupScheduleFile;
@@ -395,10 +386,8 @@ public class UserBackupManagerService {
        TransportManager transportManager =
                new TransportManager(context, transportWhitelist, currentTransport);

        File baseStateDir = new File(Environment.getDataDirectory(), BACKUP_PERSISTENT_DIR);

        // This dir on /cache is managed directly in init.rc
        File dataDir = new File(Environment.getDownloadCacheDirectory(), BACKUP_STAGING_DIR);
        File baseStateDir = UserBackupManagerFiles.getBaseStateDir(userId);
        File dataDir = UserBackupManagerFiles.getDataDir(userId);

        return createAndInitializeService(
                userId, context, trampoline, backupThread, baseStateDir, dataDir, transportManager);
@@ -726,18 +715,10 @@ public class UserBackupManagerService {
        return mBaseStateDir;
    }

    public void setBaseStateDir(File baseStateDir) {
        mBaseStateDir = baseStateDir;
    }

    public File getDataDir() {
        return mDataDir;
    }

    public void setDataDir(File dataDir) {
        mDataDir = dataDir;
    }

    @Nullable
    public DataChangedJournal getJournal() {
        return mJournal;
@@ -2735,8 +2716,7 @@ public class UserBackupManagerService {
        try {
            boolean wasEnabled = mEnabled;
            synchronized (this) {
                // TODO(b/118520567): Clean up writing backup enabled logic.
                BackupManagerService.writeBackupEnableState(enable, UserHandle.USER_SYSTEM);
                UserBackupManagerFilePersistedSettings.writeBackupEnableState(mUserId, enable);
                mEnabled = enable;
            }

+7 −4
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static com.android.server.backup.UserBackupManagerService.BACKUP_METADATA
import static com.android.server.backup.UserBackupManagerService.OP_TYPE_BACKUP_WAIT;
import static com.android.server.backup.UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;

import android.annotation.UserIdInt;
import android.app.ApplicationThreadConstants;
import android.app.IBackupAgent;
import android.app.backup.BackupTransport;
@@ -40,6 +41,7 @@ import com.android.internal.util.Preconditions;
import com.android.server.AppWidgetBackupBridge;
import com.android.server.backup.BackupAgentTimeoutParameters;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.UserBackupManagerFiles;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.remote.RemoteCall;
import com.android.server.backup.utils.FullBackupUtils;
@@ -66,6 +68,7 @@ public class FullBackupEngine {
    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;

    class FullBackupRunner implements Runnable {
        private final @UserIdInt int mUserId;
        private final PackageManager mPackageManager;
        private final PackageInfo mPackage;
        private final IBackupAgent mAgent;
@@ -81,13 +84,15 @@ public class FullBackupEngine {
                int token,
                boolean includeApks)
                throws IOException {
            // TODO: http://b/22388012
            mUserId = UserHandle.USER_SYSTEM;
            mPackageManager = backupManagerService.getPackageManager();
            mPackage = packageInfo;
            mAgent = agent;
            mPipe = ParcelFileDescriptor.dup(pipe.getFileDescriptor());
            mToken = token;
            mIncludeApks = includeApks;
            mFilesDir = new File("/data/system");
            mFilesDir = UserBackupManagerFiles.getFullBackupEngineFilesDir(mUserId);
        }

        @Override
@@ -114,10 +119,8 @@ public class FullBackupEngine {
                    manifestFile.delete();

                    // Write widget data.
                    // TODO: http://b/22388012
                    byte[] widgetData =
                            AppWidgetBackupBridge.getWidgetState(
                                    packageName, UserHandle.USER_SYSTEM);
                            AppWidgetBackupBridge.getWidgetState(packageName, mUserId);
                    if (widgetData != null && widgetData.length > 0) {
                        File metadataFile = new File(mFilesDir, BACKUP_METADATA_FILENAME);
                        appMetadataBackupWriter.backupWidget(