Snap for 5523284 from 7a2d54df8493112865f000390aa8815ec1dac77f to qt-release

Change-Id: I62721ecc7b722279bbeecd7ad9124330e61037e7
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index 70583af..eb4b1b8 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -23,6 +23,9 @@
 
 struct ThreadInfo {
   std::unique_ptr<unwindstack::Regs> registers;
+
+  pid_t uid;
+
   pid_t tid;
   std::string thread_name;
 
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index 3196ce8..88c206f 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -343,6 +343,16 @@
   ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
 }
 
+TEST_F(TombstoneTest, dump_thread_info_uid) {
+  dump_thread_info(&log_, ThreadInfo{.uid = 1,
+                                     .pid = 2,
+                                     .tid = 3,
+                                     .thread_name = "some_thread",
+                                     .process_name = "some_process"});
+  std::string expected = "pid: 2, tid: 3, name: some_thread  >>> some_process <<<\nuid: 1\n";
+  ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
+}
+
 TEST_F(TombstoneTest, dump_timestamp) {
   setenv("TZ", "UTC", 1);
   tzset();
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index d1726cd..d246722 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -151,6 +151,7 @@
 
   _LOG(log, logtype::HEADER, "pid: %d, tid: %d, name: %s  >>> %s <<<\n", thread_info.pid,
        thread_info.tid, thread_info.thread_name.c_str(), thread_info.process_name.c_str());
+  _LOG(log, logtype::HEADER, "uid: %d\n", thread_info.uid);
 }
 
 static void dump_stack_segment(log_t* log, unwindstack::Maps* maps, unwindstack::Memory* memory,
@@ -615,6 +616,7 @@
 
 void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, siginfo_t* siginfo,
                                 ucontext_t* ucontext) {
+  pid_t uid = getuid();
   pid_t pid = getpid();
   pid_t tid = gettid();
 
@@ -636,6 +638,7 @@
   std::map<pid_t, ThreadInfo> threads;
   threads[gettid()] = ThreadInfo{
       .registers = std::move(regs),
+      .uid = uid,
       .tid = tid,
       .thread_name = thread_name,
       .pid = pid,
diff --git a/init/README.md b/init/README.md
index d86f077..929f0e4 100644
--- a/init/README.md
+++ b/init/README.md
@@ -191,7 +191,7 @@
 
 `critical`
 > This is a device-critical service. If it exits more than four times in
-  four minutes, the device will reboot into bootloader.
+  four minutes or before boot completes, the device will reboot into bootloader.
 
 `disabled`
 > This service will not automatically start with its class.
@@ -412,6 +412,10 @@
   not already running.  See the start entry for more information on
   starting services.
 
+`class_start_post_data <serviceclass>`
+> Like `class_start`, but only considers services that were started
+  after /data was mounted. Only used for FDE devices.
+
 `class_stop <serviceclass>`
 > Stop and disable all services of the specified class if they are
   currently running.
@@ -421,6 +425,10 @@
   currently running, without disabling them. They can be restarted
   later using `class_start`.
 
+`class_reset_post_data <serviceclass>`
+> Like `class_reset`, but only considers services that were started
+  after /data was mounted. Only used for FDE devices.
+
 `class_restart <serviceclass>`
 > Restarts all services of the specified class.
 
@@ -490,6 +498,10 @@
 `loglevel <level>`
 > Sets the kernel log level to level. Properties are expanded within _level_.
 
+`mark_post_data`
+> Used to mark the point right after /data is mounted. Used to implement the
+  `class_reset_post_data` and `class_start_post_data` commands.
+
 `mkdir <path> [mode] [owner] [group]`
 > Create a directory at _path_, optionally with the given mode, owner, and
   group. If not provided, the directory is created with permissions 755 and
diff --git a/init/builtins.cpp b/init/builtins.cpp
index fc75072..34f229b 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -104,23 +104,37 @@
     }
 }
 
-static Result<Success> do_class_start(const BuiltinArguments& args) {
+static Result<Success> class_start(const std::string& class_name, bool post_data_only) {
     // Do not start a class if it has a property persist.dont_start_class.CLASS set to 1.
-    if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false))
+    if (android::base::GetBoolProperty("persist.init.dont_start_class." + class_name, false))
         return Success();
     // Starting a class does not start services which are explicitly disabled.
     // They must  be started individually.
     for (const auto& service : ServiceList::GetInstance()) {
-        if (service->classnames().count(args[1])) {
+        if (service->classnames().count(class_name)) {
+            if (post_data_only && !service->is_post_data()) {
+                continue;
+            }
             if (auto result = service->StartIfNotDisabled(); !result) {
                 LOG(ERROR) << "Could not start service '" << service->name()
-                           << "' as part of class '" << args[1] << "': " << result.error();
+                           << "' as part of class '" << class_name << "': " << result.error();
             }
         }
     }
     return Success();
 }
 
+static Result<Success> do_class_start(const BuiltinArguments& args) {
+    return class_start(args[1], false /* post_data_only */);
+}
+
+static Result<Success> do_class_start_post_data(const BuiltinArguments& args) {
+    if (args.context != kInitContext) {
+        return Error() << "command 'class_start_post_data' only available in init context";
+    }
+    return class_start(args[1], true /* post_data_only */);
+}
+
 static Result<Success> do_class_stop(const BuiltinArguments& args) {
     ForEachServiceInClass(args[1], &Service::Stop);
     return Success();
@@ -131,6 +145,14 @@
     return Success();
 }
 
+static Result<Success> do_class_reset_post_data(const BuiltinArguments& args) {
+    if (args.context != kInitContext) {
+        return Error() << "command 'class_reset_post_data' only available in init context";
+    }
+    ForEachServiceInClass(args[1], &Service::ResetIfPostData);
+    return Success();
+}
+
 static Result<Success> do_class_restart(const BuiltinArguments& args) {
     // Do not restart a class if it has a property persist.dont_start_class.CLASS set to 1.
     if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false))
@@ -1119,6 +1141,12 @@
         {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context});
 }
 
+static Result<Success> do_mark_post_data(const BuiltinArguments& args) {
+    ServiceList::GetInstance().MarkPostData();
+
+    return Success();
+}
+
 static Result<Success> do_parse_apex_configs(const BuiltinArguments& args) {
     glob_t glob_result;
     // @ is added to filter out the later paths, which are bind mounts of the places
@@ -1170,8 +1198,10 @@
         {"chmod",                   {2,     2,    {true,   do_chmod}}},
         {"chown",                   {2,     3,    {true,   do_chown}}},
         {"class_reset",             {1,     1,    {false,  do_class_reset}}},
+        {"class_reset_post_data",   {1,     1,    {false,  do_class_reset_post_data}}},
         {"class_restart",           {1,     1,    {false,  do_class_restart}}},
         {"class_start",             {1,     1,    {false,  do_class_start}}},
+        {"class_start_post_data",   {1,     1,    {false,  do_class_start_post_data}}},
         {"class_stop",              {1,     1,    {false,  do_class_stop}}},
         {"copy",                    {2,     2,    {true,   do_copy}}},
         {"domainname",              {1,     1,    {true,   do_domainname}}},
@@ -1191,6 +1221,7 @@
         {"load_persist_props",      {0,     0,    {false,  do_load_persist_props}}},
         {"load_system_props",       {0,     0,    {false,  do_load_system_props}}},
         {"loglevel",                {1,     1,    {false,  do_loglevel}}},
+        {"mark_post_data",          {0,     0,    {false,  do_mark_post_data}}},
         {"mkdir",                   {1,     4,    {true,   do_mkdir}}},
         // TODO: Do mount operations in vendor_init.
         // mount_all is currently too complex to run in vendor_init as it queues action triggers,
diff --git a/init/service.cpp b/init/service.cpp
index f5c13b9..2f96681 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -362,7 +362,7 @@
 
     // Oneshot processes go into the disabled state on exit,
     // except when manually restarted.
-    if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) {
+    if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART) && !(flags_ & SVC_RESET)) {
         flags_ |= SVC_DISABLED;
     }
 
@@ -372,16 +372,20 @@
         return;
     }
 
-    // If we crash > 4 times in 4 minutes, reboot into bootloader or set crashing property
+    // If we crash > 4 times in 4 minutes or before boot_completed,
+    // reboot into bootloader or set crashing property
     boot_clock::time_point now = boot_clock::now();
     if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
-        if (now < time_crashed_ + 4min) {
+        bool boot_completed = android::base::GetBoolProperty("sys.boot_completed", false);
+        if (now < time_crashed_ + 4min || !boot_completed) {
             if (++crash_count_ > 4) {
                 if (flags_ & SVC_CRITICAL) {
                     // Aborts into bootloader
-                    LOG(FATAL) << "critical process '" << name_ << "' exited 4 times in 4 minutes";
+                    LOG(FATAL) << "critical process '" << name_ << "' exited 4 times "
+                               << (boot_completed ? "in 4 minutes" : "before boot completed");
                 } else {
-                    LOG(ERROR) << "updatable process '" << name_ << "' exited 4 times in 4 minutes";
+                    LOG(ERROR) << "updatable process '" << name_ << "' exited 4 times "
+                               << (boot_completed ? "in 4 minutes" : "before boot completed");
                     // Notifies update_verifier and apexd
                     property_set("ro.init.updatable_crashing", "1");
                 }
@@ -947,6 +951,8 @@
         pre_apexd_ = true;
     }
 
+    post_data_ = ServiceList::GetInstance().IsPostData();
+
     LOG(INFO) << "starting service '" << name_ << "'...";
 
     pid_t pid = -1;
@@ -1146,6 +1152,12 @@
     StopOrReset(SVC_RESET);
 }
 
+void Service::ResetIfPostData() {
+    if (post_data_) {
+        StopOrReset(SVC_RESET);
+    }
+}
+
 void Service::Stop() {
     StopOrReset(SVC_DISABLED);
 }
@@ -1339,6 +1351,14 @@
     }
 }
 
+void ServiceList::MarkPostData() {
+    post_data_ = true;
+}
+
+bool ServiceList::IsPostData() {
+    return post_data_;
+}
+
 void ServiceList::MarkServicesUpdate() {
     services_update_finished_ = true;
 
diff --git a/init/service.h b/init/service.h
index c42a5a3..dc2b128 100644
--- a/init/service.h
+++ b/init/service.h
@@ -81,6 +81,7 @@
     Result<Success> StartIfNotDisabled();
     Result<Success> Enable();
     void Reset();
+    void ResetIfPostData();
     void Stop();
     void Terminate();
     void Timeout();
@@ -124,6 +125,7 @@
     std::optional<std::chrono::seconds> timeout_period() const { return timeout_period_; }
     const std::vector<std::string>& args() const { return args_; }
     bool is_updatable() const { return updatable_; }
+    bool is_post_data() const { return post_data_; }
 
   private:
     using OptionParser = Result<Success> (Service::*)(std::vector<std::string>&& args);
@@ -244,6 +246,8 @@
     std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
 
     bool pre_apexd_ = false;
+
+    bool post_data_ = false;
 };
 
 class ServiceList {
@@ -285,6 +289,8 @@
     const std::vector<std::unique_ptr<Service>>& services() const { return services_; }
     const std::vector<Service*> services_in_shutdown_order() const;
 
+    void MarkPostData();
+    bool IsPostData();
     void MarkServicesUpdate();
     bool IsServicesUpdated() const { return services_update_finished_; }
     void DelayService(const Service& service);
@@ -292,6 +298,7 @@
   private:
     std::vector<std::unique_ptr<Service>> services_;
 
+    bool post_data_ = false;
     bool services_update_finished_ = false;
     std::vector<std::string> delayed_service_names_;
 };
diff --git a/libmeminfo/tools/procrank.cpp b/libmeminfo/tools/procrank.cpp
index 5e89254..cb3757d 100644
--- a/libmeminfo/tools/procrank.cpp
+++ b/libmeminfo/tools/procrank.cpp
@@ -42,7 +42,6 @@
   public:
     ProcessRecord(pid_t pid, bool get_wss = false, uint64_t pgflags = 0, uint64_t pgflags_mask = 0)
         : pid_(-1),
-          procmem_(nullptr),
           oomadj_(OOM_SCORE_ADJ_MAX + 1),
           cmdline_(""),
           proportional_swap_(0),
@@ -79,15 +78,15 @@
         // The .c_str() assignment below then takes care of trimming the cmdline at the first
         // 0x00. This is how original procrank worked (luckily)
         cmdline_.resize(strlen(cmdline_.c_str()));
-        procmem_ = std::move(procmem);
+        usage_or_wss_ = get_wss ? procmem->Wss() : procmem->Usage();
+        swap_offsets_ = procmem->SwapOffsets();
         pid_ = pid;
     }
 
     bool valid() const { return pid_ != -1; }
 
     void CalculateSwap(const uint16_t* swap_offset_array, float zram_compression_ratio) {
-        const std::vector<uint16_t>& swp_offs = procmem_->SwapOffsets();
-        for (auto& off : swp_offs) {
+        for (auto& off : swap_offsets_) {
             proportional_swap_ += getpagesize() / swap_offset_array[off];
             unique_swap_ += swap_offset_array[off] == 1 ? getpagesize() : 0;
             zswap_ = proportional_swap_ * zram_compression_ratio;
@@ -103,18 +102,19 @@
     uint64_t zswap() const { return zswap_; }
 
     // Wrappers to ProcMemInfo
-    const std::vector<uint16_t>& SwapOffsets() const { return procmem_->SwapOffsets(); }
-    const MemUsage& Usage() const { return procmem_->Usage(); }
-    const MemUsage& Wss() const { return procmem_->Wss(); }
+    const std::vector<uint16_t>& SwapOffsets() const { return swap_offsets_; }
+    const MemUsage& Usage() const { return usage_or_wss_; }
+    const MemUsage& Wss() const { return usage_or_wss_; }
 
   private:
     pid_t pid_;
-    std::unique_ptr<ProcMemInfo> procmem_;
     int32_t oomadj_;
     std::string cmdline_;
     uint64_t proportional_swap_;
     uint64_t unique_swap_;
     uint64_t zswap_;
+    MemUsage usage_or_wss_;
+    std::vector<uint16_t> swap_offsets_;
 };
 
 // Show working set instead of memory consumption
@@ -171,7 +171,7 @@
     while ((dir = readdir(procdir.get()))) {
         if (!::android::base::ParseInt(dir->d_name, &pid)) continue;
         if (!for_each_pid(pid)) return false;
-        pids->push_back(pid);
+        pids->emplace_back(pid);
     }
 
     return true;
@@ -471,7 +471,7 @@
         }
 
         // Skip processes with no memory mappings
-        uint64_t vss = proc.Usage().vss;
+        uint64_t vss = show_wss ? proc.Wss().vss : proc.Usage().vss;
         if (vss == 0) return true;
 
         // collect swap_offset counts from all processes in 1st pass
@@ -481,7 +481,7 @@
             return false;
         }
 
-        procs.push_back(std::move(proc));
+        procs.emplace_back(std::move(proc));
         return true;
     };
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index dfde53c..cb45c42 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -405,6 +405,8 @@
     class_start early_hal
 
 on post-fs-data
+    mark_post_data
+
     # Start checkpoint before we touch data
     start vold
     exec - system system -- /system/bin/vdc checkpoint prepareCheckpoint
@@ -753,9 +755,6 @@
 on charger
     class_start charger
 
-on property:vold.decrypt=trigger_reset_main
-    class_reset main
-
 on property:vold.decrypt=trigger_load_persist_props
     load_persist_props
     start logd
@@ -773,6 +772,8 @@
 on property:vold.decrypt=trigger_restart_framework
     # A/B update verifier that marks a successful boot.
     exec_start update_verifier
+    class_start_post_data hal
+    class_start_post_data core
     class_start main
     class_start late_start
     setprop service.bootanim.exit 0
@@ -781,6 +782,8 @@
 on property:vold.decrypt=trigger_shutdown_framework
     class_reset late_start
     class_reset main
+    class_reset_post_data core
+    class_reset_post_data hal
 
 on property:sys.boot_completed=1
     bootchart stop