• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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