Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1522)

Side by Side Diff: components/arc/arc_bridge_service_impl.cc

Issue 2582003002: Refactor ArcBridgeServiceImpl part 1. (Closed)
Patch Set: Fix the latest bug. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/arc/arc_bridge_service_impl.h ('k') | components/arc/arc_bridge_service_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/arc/arc_bridge_service_impl.h" 5 #include "components/arc/arc_bridge_service_impl.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/json/json_writer.h" 11 #include "base/json/json_writer.h"
12 #include "base/sequenced_task_runner.h" 12 #include "base/sequenced_task_runner.h"
13 #include "base/sys_info.h" 13 #include "base/sys_info.h"
14 #include "base/task_runner_util.h" 14 #include "base/task_runner_util.h"
15 #include "base/threading/thread_task_runner_handle.h" 15 #include "base/threading/thread_task_runner_handle.h"
16 #include "base/time/time.h" 16 #include "base/time/time.h"
17 #include "chromeos/chromeos_switches.h" 17 #include "chromeos/chromeos_switches.h"
18 #include "chromeos/dbus/dbus_method_call_status.h" 18 #include "chromeos/dbus/dbus_method_call_status.h"
19 #include "chromeos/dbus/dbus_thread_manager.h" 19 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "components/arc/arc_session.h" 20 #include "components/arc/arc_session.h"
21 #include "components/prefs/pref_registry_simple.h" 21 #include "components/prefs/pref_registry_simple.h"
22 #include "components/prefs/pref_service.h" 22 #include "components/prefs/pref_service.h"
23 23
24 namespace arc { 24 namespace arc {
25
25 namespace { 26 namespace {
26 constexpr int64_t kReconnectDelayInSeconds = 5; 27
28 constexpr base::TimeDelta kDefaultRestartDelay =
29 base::TimeDelta::FromSeconds(5);
30
27 } // namespace 31 } // namespace
28 32
29 ArcBridgeServiceImpl::ArcBridgeServiceImpl( 33 ArcBridgeServiceImpl::ArcBridgeServiceImpl(
30 const scoped_refptr<base::TaskRunner>& blocking_task_runner) 34 const scoped_refptr<base::TaskRunner>& blocking_task_runner)
31 : session_started_(false), 35 : session_started_(false),
36 restart_delay_(kDefaultRestartDelay),
32 factory_(base::Bind(ArcSession::Create, this, blocking_task_runner)), 37 factory_(base::Bind(ArcSession::Create, this, blocking_task_runner)),
33 weak_factory_(this) {} 38 weak_factory_(this) {}
34 39
35 ArcBridgeServiceImpl::~ArcBridgeServiceImpl() { 40 ArcBridgeServiceImpl::~ArcBridgeServiceImpl() {
36 if (arc_session_) 41 if (arc_session_)
37 arc_session_->RemoveObserver(this); 42 arc_session_->RemoveObserver(this);
38 } 43 }
39 44
40 void ArcBridgeServiceImpl::RequestStart() { 45 void ArcBridgeServiceImpl::RequestStart() {
41 DCHECK(CalledOnValidThread()); 46 DCHECK(CalledOnValidThread());
42 if (session_started_) 47 if (session_started_)
43 return; 48 return;
44 VLOG(1) << "Session started"; 49 VLOG(1) << "Session started";
45 session_started_ = true; 50 session_started_ = true;
46 PrerequisitesChanged(); 51 PrerequisitesChanged();
47 } 52 }
48 53
49 void ArcBridgeServiceImpl::RequestStop() { 54 void ArcBridgeServiceImpl::RequestStop() {
50 DCHECK(CalledOnValidThread()); 55 DCHECK(CalledOnValidThread());
51 if (!session_started_) 56 if (!session_started_)
52 return; 57 return;
53 VLOG(1) << "Session ended"; 58 VLOG(1) << "Session ended";
54 session_started_ = false; 59 session_started_ = false;
55 PrerequisitesChanged(); 60 PrerequisitesChanged();
56 } 61 }
57 62
58 void ArcBridgeServiceImpl::OnShutdown() { 63 void ArcBridgeServiceImpl::OnShutdown() {
59 DCHECK(CalledOnValidThread()); 64 DCHECK(CalledOnValidThread());
65
60 VLOG(1) << "OnShutdown"; 66 VLOG(1) << "OnShutdown";
61 if (!session_started_)
62 return;
63 session_started_ = false; 67 session_started_ = false;
64 reconnect_ = false; 68 restart_timer_.Stop();
65 if (arc_session_) 69 if (arc_session_) {
70 if (state() != State::STOPPING)
71 SetState(State::STOPPING);
66 arc_session_->OnShutdown(); 72 arc_session_->OnShutdown();
73 }
74 // ArcSession::OnShutdown() invokes OnSessionStopped() synchronously.
75 // In the observer method, |arc_session_| should be destroyed.
76 DCHECK(!arc_session_);
67 } 77 }
68 78
69 void ArcBridgeServiceImpl::SetArcSessionFactoryForTesting( 79 void ArcBridgeServiceImpl::SetArcSessionFactoryForTesting(
70 const ArcSessionFactory& factory) { 80 const ArcSessionFactory& factory) {
71 DCHECK(!factory.is_null()); 81 DCHECK(!factory.is_null());
72 factory_ = factory; 82 factory_ = factory;
73 } 83 }
74 84
75 void ArcBridgeServiceImpl::DisableReconnectDelayForTesting() { 85 void ArcBridgeServiceImpl::SetRestartDelayForTesting(
76 use_delay_before_reconnecting_ = false; 86 const base::TimeDelta& restart_delay) {
87 DCHECK_EQ(state(), State::STOPPED);
88 DCHECK(!arc_session_);
89 DCHECK(!restart_timer_.IsRunning());
90 restart_delay_ = restart_delay;
77 } 91 }
78 92
79 void ArcBridgeServiceImpl::PrerequisitesChanged() { 93 void ArcBridgeServiceImpl::PrerequisitesChanged() {
80 DCHECK(CalledOnValidThread()); 94 DCHECK(CalledOnValidThread());
81 VLOG(1) << "Prerequisites changed. " 95 VLOG(1) << "Prerequisites changed. "
82 << "state=" << static_cast<uint32_t>(state()) 96 << "state=" << static_cast<uint32_t>(state())
83 << ", session_started=" << session_started_; 97 << ", session_started=" << session_started_;
84 if (state() == State::STOPPED) { 98 if (state() == State::STOPPED) {
85 if (!session_started_) 99 if (!session_started_) {
100 // We were explicitly asked to stop, so do not restart.
101 restart_timer_.Stop();
86 return; 102 return;
103 }
104 DCHECK(!restart_timer_.IsRunning());
87 VLOG(0) << "Prerequisites met, starting ARC"; 105 VLOG(0) << "Prerequisites met, starting ARC";
88 SetStopReason(StopReason::SHUTDOWN); 106 StartArcSession();
89
90 if (arc_session_)
91 arc_session_->RemoveObserver(this);
92
93 SetState(State::CONNECTING);
94 arc_session_ = factory_.Run();
95 arc_session_->AddObserver(this);
96 arc_session_->Start();
97 } else { 107 } else {
108 DCHECK(!restart_timer_.IsRunning());
98 if (session_started_) 109 if (session_started_)
99 return; 110 return;
100 VLOG(0) << "Prerequisites stopped being met, stopping ARC"; 111 VLOG(0) << "Prerequisites stopped being met, stopping ARC";
101 StopInstance(); 112 StopInstance();
102 } 113 }
103 } 114 }
104 115
116 void ArcBridgeServiceImpl::StartArcSession() {
117 DCHECK(CalledOnValidThread());
118 DCHECK_EQ(state(), State::STOPPED);
119 DCHECK(!arc_session_);
120 DCHECK(!restart_timer_.IsRunning());
121
122 VLOG(1) << "Starting ARC instance";
123 SetStopReason(StopReason::SHUTDOWN);
124 arc_session_ = factory_.Run();
125 arc_session_->AddObserver(this);
126 SetState(State::CONNECTING);
127 arc_session_->Start();
128 }
129
105 void ArcBridgeServiceImpl::StopInstance() { 130 void ArcBridgeServiceImpl::StopInstance() {
106 DCHECK(CalledOnValidThread()); 131 DCHECK(CalledOnValidThread());
107 if (state() == State::STOPPED || state() == State::STOPPING) { 132 DCHECK_NE(state(), State::STOPPED);
133 DCHECK(!restart_timer_.IsRunning());
134
135 if (state() == State::STOPPING) {
108 VLOG(1) << "StopInstance() called when ARC is not running"; 136 VLOG(1) << "StopInstance() called when ARC is not running";
109 return; 137 return;
110 } 138 }
111 139
112 // We were explicitly asked to stop, so do not reconnect.
113 reconnect_ = false;
114
115 VLOG(1) << "Stopping ARC"; 140 VLOG(1) << "Stopping ARC";
116 DCHECK(arc_session_.get()); 141 DCHECK(arc_session_.get());
117 SetState(State::STOPPING); 142 SetState(State::STOPPING);
118 143
119 // Note: this can call OnStopped() internally as a callback. 144 // Note: this can call OnStopped() internally as a callback.
120 arc_session_->Stop(); 145 arc_session_->Stop();
121 } 146 }
122 147
123 void ArcBridgeServiceImpl::OnSessionReady() { 148 void ArcBridgeServiceImpl::OnSessionReady() {
124 DCHECK(CalledOnValidThread()); 149 DCHECK(CalledOnValidThread());
125 if (state() != State::CONNECTING) { 150 if (state() != State::CONNECTING) {
126 VLOG(1) << "StopInstance() called while connecting"; 151 VLOG(1) << "StopInstance() called while connecting";
127 return; 152 return;
128 } 153 }
129 154
130 // The container can be considered to have been successfully launched, so
131 // restart if the connection goes down without being requested.
132 reconnect_ = true;
133 VLOG(0) << "ARC ready"; 155 VLOG(0) << "ARC ready";
134 SetState(State::READY); 156 SetState(State::READY);
135 } 157 }
136 158
137 void ArcBridgeServiceImpl::OnSessionStopped(StopReason stop_reason) { 159 void ArcBridgeServiceImpl::OnSessionStopped(StopReason stop_reason) {
138 DCHECK(CalledOnValidThread()); 160 DCHECK(CalledOnValidThread());
161 DCHECK(!restart_timer_.IsRunning());
162
139 VLOG(0) << "ARC stopped: " << stop_reason; 163 VLOG(0) << "ARC stopped: " << stop_reason;
140 arc_session_->RemoveObserver(this); 164 arc_session_->RemoveObserver(this);
141 arc_session_.reset(); 165 arc_session_.reset();
166
167 // If READY, ARC instance unexpectedly crashed so we need to restart it
168 // automatically.
169 // If STOPPING, at least once RequestStop() is called. If |session_started_|
170 // is true, RequestStart() is following so schedule to restart ARC session.
171 // Otherwise, do nothing.
172 // If CONNECTING, ARC instance has not been booted properly, so do not
173 // restart it automatically.
174 if (state() == State::READY ||
175 (state() == State::STOPPING && session_started_)) {
176 // This check is for READY case. In READY case |session_started_| should be
177 // always true, because if once RequestStop() is called, the state() will
178 // be set to STOPPING.
179 DCHECK(session_started_);
180
181 // There was a previous invocation and it crashed for some reason. Try
182 // starting ARC instance later again.
183 // Note that even |restart_delay_| is 0 (for testing), it needs to
184 // PostTask, because observer callback may call RequestStart()/Stop(),
185 // which can change restarting.
186 VLOG(0) << "ARC restarting";
187 restart_timer_.Start(FROM_HERE, restart_delay_,
188 base::Bind(&ArcBridgeServiceImpl::StartArcSession,
189 weak_factory_.GetWeakPtr()));
190 }
191
192 // TODO(hidehiko): Consider to let observers know whether there is scheduled
193 // restarting event, or not.
142 SetStopReason(stop_reason); 194 SetStopReason(stop_reason);
143 SetState(State::STOPPED); 195 SetState(State::STOPPED);
144
145 if (reconnect_) {
146 // There was a previous invocation and it crashed for some reason. Try
147 // starting the container again.
148 reconnect_ = false;
149 VLOG(0) << "ARC reconnecting";
150 if (use_delay_before_reconnecting_) {
151 // Instead of immediately trying to restart the container, give it some
152 // time to finish tearing down in case it is still in the process of
153 // stopping.
154 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
155 FROM_HERE, base::Bind(&ArcBridgeServiceImpl::PrerequisitesChanged,
156 weak_factory_.GetWeakPtr()),
157 base::TimeDelta::FromSeconds(kReconnectDelayInSeconds));
158 } else {
159 // Restart immediately.
160 PrerequisitesChanged();
161 }
162 }
163 } 196 }
164 197
165 } // namespace arc 198 } // namespace arc
OLDNEW
« no previous file with comments | « components/arc/arc_bridge_service_impl.h ('k') | components/arc/arc_bridge_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698