• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 #pragma once
18 
19 #include <vector>
20 
21 #include "adb_unique_fd.h"
22 #include "fastdeploy/proto/ApkEntry.pb.h"
23 
24 /**
25  * This class is responsible for creating a patch that can be accepted by the deployagent. The
26  * patch format is documented in GeneratePatch.
27  */
28 class DeployPatchGenerator {
29   public:
30     using APKEntry = com::android::fastdeploy::APKEntry;
31     using APKMetaData = com::android::fastdeploy::APKMetaData;
32 
33     /**
34      * Simple struct to hold mapping between local metadata and device metadata.
35      */
36     struct SimpleEntry {
37         const APKEntry* localEntry;
38         const APKEntry* deviceEntry;
39     };
40 
41     /**
42      * If |is_verbose| is true ApkEntries that are similar between device and host are written to
43      * the console.
44      */
DeployPatchGenerator(bool is_verbose)45     explicit DeployPatchGenerator(bool is_verbose) : is_verbose_(is_verbose) {}
46     /**
47      * Given a |localApkPath|, and the |deviceApkMetadata| from an installed APK this function
48      * writes a patch to the given |output|.
49      */
50     bool CreatePatch(const char* localApkPath, APKMetaData deviceApkMetadata,
51                      android::base::borrowed_fd output);
52 
53   private:
54     bool is_verbose_;
55 
56     /**
57      * Log function only logs data to stdout when |is_verbose_| is true.
58      */
59     void Log(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
60 
61     /**
62      * Helper function to log the APKMetaData structure. If |is_verbose_| is false this function
63      * early outs. This function is used for debugging / information.
64      */
65     void APKMetaDataToLog(const APKMetaData& metadata);
66     /**
67      * Helper function to log APKEntry.
68      */
69     void APKEntryToLog(const APKEntry& entry);
70 
71     /**
72      * Given the |localApkMetadata| metadata, and the |deviceApkMetadata| from an installed APK this
73      * function writes a patch to the given |output|.
74      */
75     bool CreatePatch(APKMetaData localApkMetadata, APKMetaData deviceApkMetadata,
76                      android::base::borrowed_fd output);
77 
78     /**
79      * Helper function to report savings by fastdeploy. This function prints out savings even with
80      * |is_verbose_| set to false. |totalSize| is used to show a percentage of savings. Note:
81      * |totalSize| is the size of the ZipEntries. Not the size of the entire file. The metadata of
82      * the zip data needs to be sent across with every iteration.
83      * [Patch format]
84      * |Fixed String| Signature
85      * |long|         New Size of Apk
86      * |Packets[]|    Array of Packets
87      *
88      * [Packet Format]
89      * |long|     Size of data to use from patch
90      * |byte[]|   Patch data
91      * |long|     Offset of data to use already on device
92      * |long|     Length of data to read from device APK
93      * TODO(b/138306784): Move the patch format to a proto.
94      */
95     void ReportSavings(const std::vector<SimpleEntry>& identicalEntries, uint64_t totalSize);
96 
97     /**
98      * This enumerates each entry in |entriesToUseOnDevice| and builds a patch file copying data
99      * from |localApkPath| where we are unable to use entries already on the device. The new patch
100      * is written to |output|. The entries are expected to be sorted by data offset from lowest to
101      * highest.
102      */
103     void GeneratePatch(const std::vector<SimpleEntry>& entriesToUseOnDevice,
104                        const std::string& localApkPath, const std::string& deviceApkPath,
105                        android::base::borrowed_fd output);
106 
107   protected:
108     uint64_t BuildIdenticalEntries(std::vector<SimpleEntry>& outIdenticalEntries,
109                                    const APKMetaData& localApkMetadata,
110                                    const APKMetaData& deviceApkMetadata);
111 };
112