1 /* 2 * Copyright (C) 2018 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 #ifndef CHRE_HOST_FRAGMENTED_LOAD_TRANSACTION_H_ 18 #define CHRE_HOST_FRAGMENTED_LOAD_TRANSACTION_H_ 19 20 #include <cinttypes> 21 #include <vector> 22 23 #ifndef CHRE_HOST_DEFAULT_FRAGMENT_SIZE 24 // Use 30KB fragment size to fit within 32KB memory fragments at the kernel 25 // for most devices. 26 #define CHRE_HOST_DEFAULT_FRAGMENT_SIZE (30 * 1024) 27 #endif 28 29 namespace android { 30 namespace chre { 31 32 // A special fragment id indicating the loading is not started yet. First 33 // fragment starts from id 1. 34 static constexpr uint32_t kNoFragmentId = 0; 35 36 /** 37 * A struct which represents a single fragmented request. The caller should use 38 * this class along with FragmentedLoadTransaction to get global attributes for 39 * the transaction and encode the load request using 40 * HostProtocolHost::encodeFragmentedLoadNanoappRequest. 41 */ 42 struct FragmentedLoadRequest { 43 size_t fragmentId; 44 uint32_t transactionId; 45 uint64_t appId; 46 uint32_t appVersion; 47 uint32_t appFlags; 48 uint32_t targetApiVersion; 49 size_t appTotalSizeBytes; 50 std::vector<uint8_t> binary; 51 FragmentedLoadRequestFragmentedLoadRequest52 FragmentedLoadRequest(size_t fragmentId, uint32_t transactionId, 53 uint64_t appId, const std::vector<uint8_t> &binary) 54 : FragmentedLoadRequest(fragmentId, transactionId, appId, 0, 0, 0, 0, 55 binary) {} 56 FragmentedLoadRequestFragmentedLoadRequest57 FragmentedLoadRequest(size_t fragmentId, uint32_t transactionId, 58 uint64_t appId, uint32_t appVersion, uint32_t appFlags, 59 uint32_t targetApiVersion, size_t appTotalSizeBytes, 60 const std::vector<uint8_t> &binary) 61 : fragmentId(fragmentId), 62 transactionId(transactionId), 63 appId(appId), 64 appVersion(appVersion), 65 appFlags(appFlags), 66 targetApiVersion(targetApiVersion), 67 appTotalSizeBytes(appTotalSizeBytes), 68 binary(binary) {} 69 }; 70 71 /** 72 * A class which splits a load transaction into separate requests with 73 * fragmented binaries. This class can be used to send smaller chunks of data 74 * when the kernel is under memory pressure and has limited contiguous memory. 75 * The caller should use the getNextRequest() to retrieve the next available 76 * fragment and send a load request with the fragmented binary and the fragment 77 * ID. 78 */ 79 class FragmentedLoadTransaction { 80 public: 81 /** 82 * @param transactionId the unique ID of the unfragmented load transaction 83 * @param appId the unique ID of the nanoapp 84 * @param appVersion the version of the nanoapp 85 * @param appFlags the flags specified by the nanoapp to be loaded. 86 * @param targetApiVersion the API version this nanoapp is targeted for 87 * @param appBinary the nanoapp binary data 88 * @param fragmentSize the size of each fragment in bytes 89 */ 90 FragmentedLoadTransaction(uint32_t transactionId, uint64_t appId, 91 uint32_t appVersion, uint32_t appFlags, 92 uint32_t targetApiVersion, 93 const std::vector<uint8_t> &appBinary, 94 size_t fragmentSize = kDefaultFragmentSize); 95 96 /** 97 * Retrieves the FragmentedLoadRequest including the next fragment of the 98 * binary. Invoking getNextRequest() will prepare the next fragment for a 99 * subsequent invocation. 100 * 101 * Invoking this method when there is no next request (i.e. isComplete() 102 * returns true) is illegal. 103 * 104 * @return returns a reference to the next fragment. 105 */ 106 const FragmentedLoadRequest &getNextRequest(); 107 108 /** 109 * @return true if the last fragment has been retrieved by getNextRequest(), 110 * false otherwise. 111 */ 112 [[nodiscard]] bool isComplete() const; 113 getTransactionId()114 [[nodiscard]] uint32_t getTransactionId() const { 115 return mFragmentRequests[0].transactionId; 116 } 117 getNanoappId()118 [[nodiscard]] uint64_t getNanoappId() const { 119 return mFragmentRequests[0].appId; 120 } 121 getNanoappTotalSize()122 [[nodiscard]] size_t getNanoappTotalSize() const { 123 return !mFragmentRequests[0].appTotalSizeBytes; 124 } 125 getNanoappVersion()126 [[nodiscard]] uint32_t getNanoappVersion() const { 127 return mFragmentRequests[0].appVersion; 128 } 129 130 private: 131 std::vector<FragmentedLoadRequest> mFragmentRequests; 132 size_t mCurrentRequestIndex = 0; 133 134 static constexpr size_t kDefaultFragmentSize = 135 CHRE_HOST_DEFAULT_FRAGMENT_SIZE; 136 }; 137 138 } // namespace chre 139 } // namespace android 140 141 #endif // CHRE_HOST_FRAGMENTED_LOAD_TRANSACTION_H_ 142