Home | History | Annotate | Download | only in update_engine
      1 //
      2 // Copyright (C) 2012 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 #include "update_engine/real_system_state.h"
     18 
     19 #include <string>
     20 
     21 #include <base/bind.h>
     22 #include <base/files/file_util.h>
     23 #include <base/location.h>
     24 #include <base/time/time.h>
     25 #include <brillo/make_unique_ptr.h>
     26 #include <brillo/message_loops/message_loop.h>
     27 #if USE_LIBCROS
     28 #include <chromeos/dbus/service_constants.h>
     29 #endif  // USE_LIBCROS
     30 
     31 #include "update_engine/common/boot_control.h"
     32 #include "update_engine/common/boot_control_stub.h"
     33 #include "update_engine/common/constants.h"
     34 #include "update_engine/common/hardware.h"
     35 #include "update_engine/common/utils.h"
     36 #if USE_DBUS
     37 #include "update_engine/dbus_connection.h"
     38 #endif  // USE_DBUS
     39 #include "update_engine/update_manager/state_factory.h"
     40 
     41 using brillo::MessageLoop;
     42 
     43 namespace chromeos_update_engine {
     44 
     45 RealSystemState::~RealSystemState() {
     46   // Prevent any DBus communication from UpdateAttempter when shutting down the
     47   // daemon.
     48   if (update_attempter_)
     49     update_attempter_->ClearObservers();
     50 }
     51 
     52 bool RealSystemState::Initialize() {
     53   metrics_lib_.Init();
     54 
     55   boot_control_ = boot_control::CreateBootControl();
     56   if (!boot_control_) {
     57     LOG(WARNING) << "Unable to create BootControl instance, using stub "
     58                  << "instead. All update attempts will fail.";
     59     boot_control_ = brillo::make_unique_ptr(new BootControlStub());
     60   }
     61 
     62   hardware_ = hardware::CreateHardware();
     63   if (!hardware_) {
     64     LOG(ERROR) << "Error intializing the HardwareInterface.";
     65     return false;
     66   }
     67 
     68 #if USE_LIBCROS
     69   libcros_proxy_.reset(new org::chromium::LibCrosServiceInterfaceProxy(
     70       DBusConnection::Get()->GetDBus(), chromeos::kLibCrosServiceName));
     71   network_proxy_service_proxy_.reset(
     72       new org::chromium::NetworkProxyServiceInterfaceProxy(
     73           DBusConnection::Get()->GetDBus(),
     74           chromeos::kNetworkProxyServiceName));
     75 #endif  // USE_LIBCROS
     76 
     77   LOG_IF(INFO, !hardware_->IsNormalBootMode()) << "Booted in dev mode.";
     78   LOG_IF(INFO, !hardware_->IsOfficialBuild()) << "Booted non-official build.";
     79 
     80   connection_manager_ = connection_manager::CreateConnectionManager(this);
     81   if (!connection_manager_) {
     82     LOG(ERROR) << "Error intializing the ConnectionManagerInterface.";
     83     return false;
     84   }
     85 
     86   power_manager_ = power_manager::CreatePowerManager();
     87   if (!power_manager_) {
     88     LOG(ERROR) << "Error intializing the PowerManagerInterface.";
     89     return false;
     90   }
     91 
     92   // Initialize standard and powerwash-safe prefs.
     93   base::FilePath non_volatile_path;
     94   // TODO(deymo): Fall back to in-memory prefs if there's no physical directory
     95   // available.
     96   if (!hardware_->GetNonVolatileDirectory(&non_volatile_path)) {
     97     LOG(ERROR) << "Failed to get a non-volatile directory.";
     98     return false;
     99   }
    100   Prefs* prefs;
    101   prefs_.reset(prefs = new Prefs());
    102   if (!prefs->Init(non_volatile_path.Append(kPrefsSubDirectory))) {
    103     LOG(ERROR) << "Failed to initialize preferences.";
    104     return false;
    105   }
    106 
    107   base::FilePath powerwash_safe_path;
    108   if (!hardware_->GetPowerwashSafeDirectory(&powerwash_safe_path)) {
    109     // TODO(deymo): Fall-back to in-memory prefs if there's no powerwash-safe
    110     // directory, or disable powerwash feature.
    111     powerwash_safe_path = non_volatile_path.Append("powerwash-safe");
    112     LOG(WARNING) << "No powerwash-safe directory, using non-volatile one.";
    113   }
    114   powerwash_safe_prefs_.reset(prefs = new Prefs());
    115   if (!prefs->Init(
    116           powerwash_safe_path.Append(kPowerwashSafePrefsSubDirectory))) {
    117     LOG(ERROR) << "Failed to initialize powerwash preferences.";
    118     return false;
    119   }
    120 
    121   // Check the system rebooted marker file.
    122   std::string boot_id;
    123   if (utils::GetBootId(&boot_id)) {
    124     std::string prev_boot_id;
    125     system_rebooted_ = (!prefs_->GetString(kPrefsBootId, &prev_boot_id) ||
    126                         prev_boot_id != boot_id);
    127     prefs_->SetString(kPrefsBootId, boot_id);
    128   } else {
    129     LOG(WARNING) << "Couldn't detect the bootid, assuming system was rebooted.";
    130     system_rebooted_ = true;
    131   }
    132 
    133   // Initialize the OmahaRequestParams with the default settings. These settings
    134   // will be re-initialized before every request using the actual request
    135   // options. This initialization here pre-loads current channel and version, so
    136   // the DBus service can access it.
    137   if (!request_params_.Init("", "", false)) {
    138     LOG(WARNING) << "Ignoring OmahaRequestParams initialization error. Some "
    139                     "features might not work properly.";
    140   }
    141 
    142   certificate_checker_.reset(
    143       new CertificateChecker(prefs_.get(), &openssl_wrapper_));
    144   certificate_checker_->Init();
    145 
    146 #if USE_LIBCROS
    147   org::chromium::NetworkProxyServiceInterfaceProxyInterface* net_proxy =
    148       network_proxy_service_proxy_.get();
    149   org::chromium::LibCrosServiceInterfaceProxyInterface* libcros_proxy =
    150       libcros_proxy_.get();
    151 #else
    152   org::chromium::NetworkProxyServiceInterfaceProxyInterface* net_proxy =
    153       nullptr;
    154   org::chromium::LibCrosServiceInterfaceProxyInterface* libcros_proxy =
    155       nullptr;
    156 #endif  // USE_LIBCROS
    157 
    158   // Initialize the UpdateAttempter before the UpdateManager.
    159   update_attempter_.reset(new UpdateAttempter(this, certificate_checker_.get(),
    160                                               net_proxy));
    161   update_attempter_->Init();
    162 
    163   // Initialize the Update Manager using the default state factory.
    164   chromeos_update_manager::State* um_state =
    165       chromeos_update_manager::DefaultStateFactory(
    166           &policy_provider_, libcros_proxy, this);
    167   if (!um_state) {
    168     LOG(ERROR) << "Failed to initialize the Update Manager.";
    169     return false;
    170   }
    171   update_manager_.reset(
    172       new chromeos_update_manager::UpdateManager(
    173           &clock_, base::TimeDelta::FromSeconds(5),
    174           base::TimeDelta::FromHours(12), um_state));
    175 
    176   // The P2P Manager depends on the Update Manager for its initialization.
    177   p2p_manager_.reset(P2PManager::Construct(
    178           nullptr, &clock_, update_manager_.get(), "cros_au",
    179           kMaxP2PFilesToKeep, base::TimeDelta::FromDays(kMaxP2PFileAgeDays)));
    180 
    181   if (!payload_state_.Initialize(this)) {
    182     LOG(ERROR) << "Failed to initialize the payload state object.";
    183     return false;
    184   }
    185 
    186   // All is well. Initialization successful.
    187   return true;
    188 }
    189 
    190 bool RealSystemState::StartUpdater() {
    191   // Initiate update checks.
    192   update_attempter_->ScheduleUpdates();
    193 
    194   // Update boot flags after 45 seconds.
    195   MessageLoop::current()->PostDelayedTask(
    196       FROM_HERE,
    197       base::Bind(&UpdateAttempter::UpdateBootFlags,
    198                  base::Unretained(update_attempter_.get())),
    199       base::TimeDelta::FromSeconds(45));
    200 
    201   // Broadcast the update engine status on startup to ensure consistent system
    202   // state on crashes.
    203   MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
    204       &UpdateAttempter::BroadcastStatus,
    205       base::Unretained(update_attempter_.get())));
    206 
    207   // Run the UpdateEngineStarted() method on |update_attempter|.
    208   MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
    209       &UpdateAttempter::UpdateEngineStarted,
    210       base::Unretained(update_attempter_.get())));
    211   return true;
    212 }
    213 
    214 void RealSystemState::AddObserver(ServiceObserverInterface* observer) {
    215   CHECK(update_attempter_.get());
    216   update_attempter_->AddObserver(observer);
    217 }
    218 
    219 void RealSystemState::RemoveObserver(ServiceObserverInterface* observer) {
    220   CHECK(update_attempter_.get());
    221   update_attempter_->RemoveObserver(observer);
    222 }
    223 
    224 }  // namespace chromeos_update_engine
    225