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.utils;
18 
19 import static com.android.server.backup.BackupManagerService.TAG;
20 
21 import android.os.ParcelFileDescriptor;
22 import android.util.Slog;
23 
24 import com.android.server.backup.Flags;
25 
26 import java.io.DataInputStream;
27 import java.io.EOFException;
28 import java.io.FileInputStream;
29 import java.io.IOException;
30 import java.io.OutputStream;
31 
32 /**
33  * Low-level utility methods for full backup.
34  */
35 public class FullBackupUtils {
36 
37     /**
38      * Reads data from pipe and writes it to the stream.
39      *
40      * @param inPipe - pipe to read the data from.
41      * @param out - stream to write the data to.
42      * @throws IOException - in case of an error.
43      */
routeSocketDataToOutput(ParcelFileDescriptor inPipe, OutputStream out)44     public static void routeSocketDataToOutput(ParcelFileDescriptor inPipe, OutputStream out)
45             throws IOException {
46         // We do not take close() responsibility for the pipe FD
47         FileInputStream raw = new FileInputStream(inPipe.getFileDescriptor());
48         DataInputStream in = new DataInputStream(raw);
49         int chunkSizeInBytes = 32 * 1024; // 32KB
50         if (Flags.enableMaxSizeWritesToPipes()) {
51             // Linux pipe capacity (buffer size) is 16 pages where each page is 4KB
52             chunkSizeInBytes = 64 * 1024; // 64KB
53         }
54         byte[] buffer = new byte[chunkSizeInBytes];
55         int chunkTotal;
56         while ((chunkTotal = in.readInt()) > 0) {
57             while (chunkTotal > 0) {
58                 int toRead = (chunkTotal > buffer.length) ? buffer.length : chunkTotal;
59                 int nRead = in.read(buffer, 0, toRead);
60                 if (nRead < 0) {
61                     Slog.e(TAG, "Unexpectedly reached end of file while reading data");
62                     throw new EOFException();
63                 }
64                 out.write(buffer, 0, nRead);
65                 chunkTotal -= nRead;
66             }
67         }
68     }
69 }
70