1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.server.backup.fullbackup; 18 19 import static com.android.server.backup.BackupManagerService.MORE_DEBUG; 20 import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT; 21 import static com.android.server.backup.BackupManagerService.TAG; 22 23 import android.app.backup.IBackupManager; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.ServiceConnection; 28 import android.content.pm.PackageInfo; 29 import android.os.IBinder; 30 import android.os.ParcelFileDescriptor; 31 import android.os.UserHandle; 32 import android.util.Slog; 33 34 import com.android.internal.backup.IObbBackupService; 35 import com.android.internal.util.Preconditions; 36 import com.android.server.backup.BackupAgentTimeoutParameters; 37 import com.android.server.backup.BackupManagerService; 38 import com.android.server.backup.utils.FullBackupUtils; 39 40 import java.io.IOException; 41 import java.io.OutputStream; 42 43 /** 44 * Full backup/restore to a file/socket. 45 */ 46 public class FullBackupObbConnection implements ServiceConnection { 47 48 private BackupManagerService backupManagerService; 49 volatile IObbBackupService mService; 50 private final BackupAgentTimeoutParameters mAgentTimeoutParameters; 51 52 public FullBackupObbConnection(BackupManagerService backupManagerService) { 53 this.backupManagerService = backupManagerService; 54 mService = null; 55 mAgentTimeoutParameters = Preconditions.checkNotNull( 56 backupManagerService.getAgentTimeoutParameters(), 57 "Timeout parameters cannot be null"); 58 } 59 60 public void establish() { 61 if (MORE_DEBUG) { 62 Slog.i(TAG, "Initiating bind of OBB service on " + this); 63 } 64 Intent obbIntent = new Intent().setComponent(new ComponentName( 65 "com.android.sharedstoragebackup", 66 "com.android.sharedstoragebackup.ObbBackupService")); 67 backupManagerService.getContext().bindServiceAsUser( 68 obbIntent, this, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM); 69 } 70 71 public void tearDown() { 72 backupManagerService.getContext().unbindService(this); 73 } 74 75 public boolean backupObbs(PackageInfo pkg, OutputStream out) { 76 boolean success = false; 77 waitForConnection(); 78 79 ParcelFileDescriptor[] pipes = null; 80 try { 81 pipes = ParcelFileDescriptor.createPipe(); 82 int token = backupManagerService.generateRandomIntegerToken(); 83 long fullBackupAgentTimeoutMillis = 84 mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis(); 85 backupManagerService.prepareOperationTimeout( 86 token, fullBackupAgentTimeoutMillis, null, OP_TYPE_BACKUP_WAIT); 87 mService.backupObbs(pkg.packageName, pipes[1], token, 88 backupManagerService.getBackupManagerBinder()); 89 FullBackupUtils.routeSocketDataToOutput(pipes[0], out); 90 success = backupManagerService.waitUntilOperationComplete(token); 91 } catch (Exception e) { 92 Slog.w(TAG, "Unable to back up OBBs for " + pkg, e); 93 } finally { 94 try { 95 out.flush(); 96 if (pipes != null) { 97 if (pipes[0] != null) { 98 pipes[0].close(); 99 } 100 if (pipes[1] != null) { 101 pipes[1].close(); 102 } 103 } 104 } catch (IOException e) { 105 Slog.w(TAG, "I/O error closing down OBB backup", e); 106 } 107 } 108 return success; 109 } 110 111 public void restoreObbFile(String pkgName, ParcelFileDescriptor data, 112 long fileSize, int type, String path, long mode, long mtime, 113 int token, IBackupManager callbackBinder) { 114 waitForConnection(); 115 116 try { 117 mService.restoreObbFile(pkgName, data, fileSize, type, path, mode, mtime, 118 token, callbackBinder); 119 } catch (Exception e) { 120 Slog.w(TAG, "Unable to restore OBBs for " + pkgName, e); 121 } 122 } 123 124 private void waitForConnection() { 125 synchronized (this) { 126 while (mService == null) { 127 if (MORE_DEBUG) { 128 Slog.i(TAG, "...waiting for OBB service binding..."); 129 } 130 try { 131 this.wait(); 132 } catch (InterruptedException e) { /* never interrupted */ } 133 } 134 if (MORE_DEBUG) { 135 Slog.i(TAG, "Connected to OBB service; continuing"); 136 } 137 } 138 } 139 140 @Override 141 public void onServiceConnected(ComponentName name, IBinder service) { 142 synchronized (this) { 143 mService = IObbBackupService.Stub.asInterface(service); 144 if (MORE_DEBUG) { 145 Slog.i(TAG, "OBB service connection " + mService + " connected on " + this); 146 } 147 this.notifyAll(); 148 } 149 } 150 151 @Override 152 public void onServiceDisconnected(ComponentName name) { 153 synchronized (this) { 154 mService = null; 155 if (MORE_DEBUG) { 156 Slog.i(TAG, "OBB service connection disconnected on " + this); 157 } 158 this.notifyAll(); 159 } 160 } 161 162 } 163