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 /**
33  * A struct which represents a single fragmented request. The caller should use
34  * this class along with FragmentedLoadTransaction to get global attributes for
35  * the transaction and encode the load request using
36  * HostProtocolHost::encodeFragmentedLoadNanoappRequest.
37  */
38 struct FragmentedLoadRequest {
39   size_t fragmentId;
40   uint32_t transactionId;
41   uint64_t appId;
42   uint32_t appVersion;
43   uint32_t appFlags;
44   uint32_t targetApiVersion;
45   size_t appTotalSizeBytes;
46   std::vector<uint8_t> binary;
47 
FragmentedLoadRequestFragmentedLoadRequest48   FragmentedLoadRequest(size_t fragmentId, uint32_t transactionId,
49                         const std::vector<uint8_t> &binary)
50       : FragmentedLoadRequest(fragmentId, transactionId, 0, 0, 0, 0, 0,
51                               binary) {}
52 
FragmentedLoadRequestFragmentedLoadRequest53   FragmentedLoadRequest(size_t fragmentId, uint32_t transactionId,
54                         uint64_t appId, uint32_t appVersion, uint32_t appFlags,
55                         uint32_t targetApiVersion, size_t appTotalSizeBytes,
56                         const std::vector<uint8_t> &binary)
57       : fragmentId(fragmentId),
58         transactionId(transactionId),
59         appId(appId),
60         appVersion(appVersion),
61         appFlags(appFlags),
62         targetApiVersion(targetApiVersion),
63         appTotalSizeBytes(appTotalSizeBytes),
64         binary(binary) {}
65 };
66 
67 /**
68  * A class which splits a load transaction into separate requests with
69  * fragmented binaries. This class can be used to send smaller chunks of data
70  * when the kernel is under memory pressure and has limited contiguous memory.
71  * The caller should use the getNextRequest() to retrieve the next available
72  * fragment and send a load request with the fragmented binary and the fragment
73  * ID.
74  */
75 class FragmentedLoadTransaction {
76  public:
77   /**
78    * @param transactionId the unique ID of the unfragmented load transaction
79    * @param appId the unique ID of the nanoapp
80    * @param appVersion the version of the nanoapp
81    * @param appFlags the flags specified by the nanoapp to be loaded.
82    * @param targetApiVersion the API version this nanoapp is targeted for
83    * @param appBinary the nanoapp binary data
84    * @param fragmentSize the size of each fragment in bytes
85    */
86   FragmentedLoadTransaction(uint32_t transactionId, uint64_t appId,
87                             uint32_t appVersion, uint32_t appFlags,
88                             uint32_t targetApiVersion,
89                             const std::vector<uint8_t> &appBinary,
90                             size_t fragmentSize = kDefaultFragmentSize);
91 
92   /**
93    * Retrieves the FragmentedLoadRequest including the next fragment of the
94    * binary. Invoking getNextRequest() will prepare the next fragment for a
95    * subsequent invocation.
96    *
97    * Invoking this method when there is no next request (i.e. isComplete()
98    * returns true) is illegal.
99    *
100    * @return returns a reference to the next fragment.
101    */
102   const FragmentedLoadRequest &getNextRequest();
103 
104   /**
105    * @return true if the last fragment has been retrieved by getNextRequest(),
106    *         false otherwise.
107    */
108   bool isComplete() const;
109 
getTransactionId()110   uint32_t getTransactionId() const {
111     return mTransactionId;
112   }
113 
114  private:
115   std::vector<FragmentedLoadRequest> mFragmentRequests;
116   size_t mCurrentRequestIndex = 0;
117   uint32_t mTransactionId;
118 
119   static constexpr size_t kDefaultFragmentSize =
120       CHRE_HOST_DEFAULT_FRAGMENT_SIZE;
121 };
122 
123 }  // namespace chre
124 }  // namespace android
125 
126 #endif  // CHRE_HOST_FRAGMENTED_LOAD_TRANSACTION_H_
127