OLD | NEW |
---|---|
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 namespace { | 25 namespace { |
Luis Héctor Chávez
2016/12/16 23:02:13
nit: maybe add a newline before for consistency?
hidehiko
2016/12/19 07:41:21
Done.
| |
26 constexpr int64_t kReconnectDelayInSeconds = 5; | 26 |
27 constexpr base::TimeDelta kDefaultRestartDelay = | |
28 base::TimeDelta::FromSeconds(5); | |
29 | |
27 } // namespace | 30 } // namespace |
28 | 31 |
29 ArcBridgeServiceImpl::ArcBridgeServiceImpl( | 32 ArcBridgeServiceImpl::ArcBridgeServiceImpl( |
30 const scoped_refptr<base::TaskRunner>& blocking_task_runner) | 33 const scoped_refptr<base::TaskRunner>& blocking_task_runner) |
31 : session_started_(false), | 34 : session_started_(false), |
35 restart_delay_(kDefaultRestartDelay), | |
32 factory_(base::Bind(ArcSession::Create, this, blocking_task_runner)), | 36 factory_(base::Bind(ArcSession::Create, this, blocking_task_runner)), |
33 weak_factory_(this) {} | 37 weak_factory_(this) {} |
34 | 38 |
35 ArcBridgeServiceImpl::~ArcBridgeServiceImpl() { | 39 ArcBridgeServiceImpl::~ArcBridgeServiceImpl() { |
36 if (arc_session_) | 40 if (arc_session_) |
37 arc_session_->RemoveObserver(this); | 41 arc_session_->RemoveObserver(this); |
38 } | 42 } |
39 | 43 |
40 void ArcBridgeServiceImpl::RequestStart() { | 44 void ArcBridgeServiceImpl::RequestStart() { |
41 DCHECK(CalledOnValidThread()); | 45 DCHECK(CalledOnValidThread()); |
42 if (session_started_) | 46 if (session_started_) |
43 return; | 47 return; |
44 VLOG(1) << "Session started"; | 48 VLOG(1) << "Session started"; |
45 session_started_ = true; | 49 session_started_ = true; |
46 PrerequisitesChanged(); | 50 PrerequisitesChanged(); |
47 } | 51 } |
48 | 52 |
49 void ArcBridgeServiceImpl::RequestStop() { | 53 void ArcBridgeServiceImpl::RequestStop() { |
50 DCHECK(CalledOnValidThread()); | 54 DCHECK(CalledOnValidThread()); |
51 if (!session_started_) | 55 if (!session_started_) |
52 return; | 56 return; |
53 VLOG(1) << "Session ended"; | 57 VLOG(1) << "Session ended"; |
54 session_started_ = false; | 58 session_started_ = false; |
55 PrerequisitesChanged(); | 59 PrerequisitesChanged(); |
56 } | 60 } |
57 | 61 |
58 void ArcBridgeServiceImpl::OnShutdown() { | 62 void ArcBridgeServiceImpl::OnShutdown() { |
59 DCHECK(CalledOnValidThread()); | 63 DCHECK(CalledOnValidThread()); |
64 | |
60 VLOG(1) << "OnShutdown"; | 65 VLOG(1) << "OnShutdown"; |
61 if (!session_started_) | |
62 return; | |
63 session_started_ = false; | 66 session_started_ = false; |
64 reconnect_ = false; | 67 restart_timer_.Stop(); |
65 if (arc_session_) | 68 if (arc_session_) |
66 arc_session_->OnShutdown(); | 69 arc_session_->OnShutdown(); |
70 // ArcSession::OnShutdown() invokes OnSessionStopped() synchronously. | |
71 // In the observer method, |arc_session_| should be destroyed. | |
72 DCHECK(!arc_session_); | |
67 } | 73 } |
68 | 74 |
69 void ArcBridgeServiceImpl::SetArcSessionFactoryForTesting( | 75 void ArcBridgeServiceImpl::SetArcSessionFactoryForTesting( |
70 const ArcSessionFactory& factory) { | 76 const ArcSessionFactory& factory) { |
71 DCHECK(!factory.is_null()); | 77 DCHECK(!factory.is_null()); |
72 factory_ = factory; | 78 factory_ = factory; |
73 } | 79 } |
74 | 80 |
75 void ArcBridgeServiceImpl::DisableReconnectDelayForTesting() { | 81 void ArcBridgeServiceImpl::SetRestartDelayForTesting( |
76 use_delay_before_reconnecting_ = false; | 82 const base::TimeDelta& restart_delay) { |
83 DCHECK_EQ(state(), State::STOPPED); | |
84 DCHECK(!arc_session_); | |
85 DCHECK(!restart_timer_.IsRunning()); | |
86 restart_delay_ = restart_delay; | |
77 } | 87 } |
78 | 88 |
79 void ArcBridgeServiceImpl::PrerequisitesChanged() { | 89 void ArcBridgeServiceImpl::PrerequisitesChanged() { |
Luis Héctor Chávez
2016/12/16 23:02:13
Now that you've removed the third caller of Prereq
Luis Héctor Chávez
2016/12/16 23:06:35
Nevermind about this, I just saw your second patch
hidehiko
2016/12/19 07:41:21
Yes. Let me work on it in the following CL.
| |
80 DCHECK(CalledOnValidThread()); | 90 DCHECK(CalledOnValidThread()); |
81 VLOG(1) << "Prerequisites changed. " | 91 VLOG(1) << "Prerequisites changed. " |
82 << "state=" << static_cast<uint32_t>(state()) | 92 << "state=" << static_cast<uint32_t>(state()) |
83 << ", session_started=" << session_started_; | 93 << ", session_started=" << session_started_; |
84 if (state() == State::STOPPED) { | 94 if (state() == State::STOPPED) { |
85 if (!session_started_) | 95 if (!session_started_) { |
96 // We were explicitly asked to stop, so do not restart. | |
97 restart_timer_.Stop(); | |
Luis Héctor Chávez
2016/12/16 23:02:13
How about you move this to L96-97 to RequestStop()
hidehiko
2016/12/19 07:41:21
If this is not a big problem, can I keep this in t
| |
86 return; | 98 return; |
99 } | |
100 DCHECK(!restart_timer_.IsRunning()); | |
Luis Héctor Chávez
2016/12/16 23:02:13
Both branches check for this. Move to after L93?
hidehiko
2016/12/19 07:41:21
Similar to above, can I address this in the follow
| |
87 VLOG(0) << "Prerequisites met, starting ARC"; | 101 VLOG(0) << "Prerequisites met, starting ARC"; |
88 SetStopReason(StopReason::SHUTDOWN); | 102 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 { | 103 } else { |
104 DCHECK(!restart_timer_.IsRunning()); | |
98 if (session_started_) | 105 if (session_started_) |
99 return; | 106 return; |
100 VLOG(0) << "Prerequisites stopped being met, stopping ARC"; | 107 VLOG(0) << "Prerequisites stopped being met, stopping ARC"; |
101 StopInstance(); | 108 StopInstance(); |
102 } | 109 } |
103 } | 110 } |
104 | 111 |
112 void ArcBridgeServiceImpl::StartArcSession() { | |
113 DCHECK(CalledOnValidThread()); | |
114 DCHECK_EQ(state(), State::STOPPED); | |
115 DCHECK(!arc_session_); | |
116 DCHECK(!restart_timer_.IsRunning()); | |
117 | |
118 VLOG(1) << "Starting ARC instance"; | |
119 SetStopReason(StopReason::SHUTDOWN); | |
120 arc_session_ = factory_.Run(); | |
121 arc_session_->AddObserver(this); | |
122 SetState(State::CONNECTING); | |
123 arc_session_->Start(); | |
124 } | |
125 | |
105 void ArcBridgeServiceImpl::StopInstance() { | 126 void ArcBridgeServiceImpl::StopInstance() { |
106 DCHECK(CalledOnValidThread()); | 127 DCHECK(CalledOnValidThread()); |
107 if (state() == State::STOPPED || state() == State::STOPPING) { | 128 DCHECK_NE(state(), State::STOPPED); |
129 DCHECK(!restart_timer_.IsRunning()); | |
130 | |
131 if (state() == State::STOPPING) { | |
108 VLOG(1) << "StopInstance() called when ARC is not running"; | 132 VLOG(1) << "StopInstance() called when ARC is not running"; |
109 return; | 133 return; |
110 } | 134 } |
111 | 135 |
112 // We were explicitly asked to stop, so do not reconnect. | |
113 reconnect_ = false; | |
114 | |
115 VLOG(1) << "Stopping ARC"; | 136 VLOG(1) << "Stopping ARC"; |
116 DCHECK(arc_session_.get()); | 137 DCHECK(arc_session_.get()); |
117 SetState(State::STOPPING); | 138 SetState(State::STOPPING); |
118 | 139 |
119 // Note: this can call OnStopped() internally as a callback. | 140 // Note: this can call OnStopped() internally as a callback. |
120 arc_session_->Stop(); | 141 arc_session_->Stop(); |
121 } | 142 } |
122 | 143 |
123 void ArcBridgeServiceImpl::OnSessionReady() { | 144 void ArcBridgeServiceImpl::OnSessionReady() { |
124 DCHECK(CalledOnValidThread()); | 145 DCHECK(CalledOnValidThread()); |
125 if (state() != State::CONNECTING) { | 146 if (state() != State::CONNECTING) { |
126 VLOG(1) << "StopInstance() called while connecting"; | 147 VLOG(1) << "StopInstance() called while connecting"; |
127 return; | 148 return; |
128 } | 149 } |
129 | 150 |
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"; | 151 VLOG(0) << "ARC ready"; |
134 SetState(State::READY); | 152 SetState(State::READY); |
135 } | 153 } |
136 | 154 |
137 void ArcBridgeServiceImpl::OnSessionStopped(StopReason stop_reason) { | 155 void ArcBridgeServiceImpl::OnSessionStopped(StopReason stop_reason) { |
138 DCHECK(CalledOnValidThread()); | 156 DCHECK(CalledOnValidThread()); |
157 DCHECK(!restart_timer_.IsRunning()); | |
158 | |
139 VLOG(0) << "ARC stopped: " << stop_reason; | 159 VLOG(0) << "ARC stopped: " << stop_reason; |
140 arc_session_->RemoveObserver(this); | 160 arc_session_->RemoveObserver(this); |
141 arc_session_.reset(); | 161 arc_session_.reset(); |
162 | |
163 // If READY, ARC instance is unexpectedly crashed so we need to restart it | |
Luis Héctor Chávez
2016/12/16 23:02:13
nit: "ARC instance unexpectedly crashed".
hidehiko
2016/12/19 07:41:21
Done.
| |
164 // automatically. If STOPPING, it is the result of consecutive RequestStop() | |
165 // followed by RequestStart() invocation. | |
166 // If CONNECTING, ARC instance has not been booted properly, so do not | |
167 // restart it automatically. | |
168 if (session_started_ && | |
Luis Héctor Chávez
2016/12/16 23:02:13
In the same spirit as we did reset |reconnect_|, s
hidehiko
2016/12/19 07:41:21
IIUC, unlike |reconnect_|, |session_started_| shou
Luis Héctor Chávez
2016/12/19 22:23:38
I like the proposed condition much better, since i
hidehiko
2016/12/20 13:38:02
Sure, done. Just in case, could you take another l
| |
169 (state() == State::READY || state() == State::STOPPING)) { | |
170 // There was a previous invocation and it crashed for some reason. Try | |
171 // starting ARC instance later again. | |
172 // Note that even |restart_delay_| is 0 (for testing), it needs to | |
173 // PostTask, because observer callback may call RequestStart()/Stop(), | |
174 // which can change restarting. | |
175 VLOG(0) << "ARC restarting"; | |
176 restart_timer_.Start(FROM_HERE, restart_delay_, | |
177 base::Bind(&ArcBridgeServiceImpl::StartArcSession, | |
178 weak_factory_.GetWeakPtr())); | |
179 } | |
180 | |
142 SetStopReason(stop_reason); | 181 SetStopReason(stop_reason); |
143 SetState(State::STOPPED); | 182 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 } | 183 } |
164 | 184 |
165 } // namespace arc | 185 } // namespace arc |
OLD | NEW |