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