• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 ART_RUNTIME_OAT_SDC_FILE_H_
18 #define ART_RUNTIME_OAT_SDC_FILE_H_
19 
20 #include <memory>
21 #include <string>
22 #include <string_view>
23 #include <utility>
24 
25 #include "base/macros.h"
26 #include "base/os.h"
27 
28 namespace art HIDDEN {
29 
30 // A helper class to read a secure dex metadata companion (SDC) file.
31 //
32 // Secure dex metadata companion (SDC) file is a file type that augments a secure dex metadata (SDM)
33 // file with additional metadata.
34 //
35 // 1. There may be exactly one SDC file accompanying each SDM file. An SDC file without a
36 //    corresponding SDM file, or with a mismatching SDM timestamp, is garbage.
37 // 2. They are always local on device.
38 // 3. They are only read and written by the ART module.
39 // 4. A later version of the ART module must be able to understand the contents.
40 //
41 // It is a text file in the format of:
42 //   key1=value1\n
43 //   key2=value2\n
44 //   ...
45 // Repeated keys are not allowed. This is an extensible format, so versioning is not needed.
46 //
47 // In principle, ART Service generates an SDC file for an SDM file during installation.
48 // Specifically, during dexopt, which typically takes place during installation, if there is an SDM
49 // file while the corresponding SDC file is missing (meaning the SDM file is newly installed) or
50 // stale (meaning the SDM file is newly replaced), ART Service will generate a new SDC file. This
51 // means an SDM file without a corresponding SDC file is a transient state and is valid from ART
52 // Service's perspective.
53 //
54 // From the runtime's perspective, an SDM file without a corresponding SDC file is incomplete. That
55 // means:
56 // - At app execution time, the runtime ignores an SDM file without a corresponding SDC.
57 // - ART Service's file GC, which uses the runtime's judgement, considers an SDM file without a
58 //   corresponding SDC invalid and may clean it up. This may race with a package installation before
59 //   the SDC is created, but it's rare and the effect is recoverable, so it's considered acceptable.
60 class EXPORT SdcReader {
61  public:
62   static std::unique_ptr<SdcReader> Load(const std::string& filename, std::string* error_msg);
63 
64   // The mtime of the SDM file on device, in nanoseconds.
65   // This is for detecting obsolete SDC files.
GetSdmTimestampNs()66   int64_t GetSdmTimestampNs() const { return sdm_timestamp_ns_; }
67 
68   // The value of `Runtime::GetApexVersions` at the time where the SDM file was first seen on
69   // device. This is for detecting samegrade placebos.
GetApexVersions()70   std::string_view GetApexVersions() const { return apex_versions_; }
71 
72  private:
73   SdcReader() = default;
74 
75   std::string content_;
76   int64_t sdm_timestamp_ns_;
77   std::string_view apex_versions_;
78 };
79 
80 // A helper class to write a secure dex metadata companion (SDC) file.
81 class EXPORT SdcWriter {
82  public:
83   // Takes ownership of the file.
SdcWriter(File && file)84   explicit SdcWriter(File&& file) : file_(std::move(file)) {}
85 
86   // See `SdcReader::GetSdmTimestampNs`.
SetSdmTimestampNs(int64_t value)87   void SetSdmTimestampNs(int64_t value) { sdm_timestamp_ns_ = value; }
88 
89   // See `SdcReader::GetApexVersions`.
SetApexVersions(std::string_view value)90   void SetApexVersions(std::string_view value) { apex_versions_ = value; }
91 
92   bool Save(std::string* error_msg);
93 
94  private:
95   File file_;
96   int64_t sdm_timestamp_ns_ = 0;
97   std::string apex_versions_;
98 };
99 
100 }  // namespace art
101 
102 #endif  // ART_RUNTIME_OAT_SDC_FILE_H_
103