1// Copyright 2015 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "libweaved/command.h"
16
17#include "android/weave/IWeaveCommand.h"
18#include "common/binder_utils.h"
19
20using weaved::binder_utils::ParseDictionary;
21using weaved::binder_utils::ToString;
22using weaved::binder_utils::ToString16;
23using weaved::binder_utils::StatusToError;
24
25namespace weaved {
26
27namespace {
28
29// Converts binder exception code into a weave error code string.
30std::string BinderExceptionString(int32_t exception_code) {
31  if (exception_code == android::binder::Status::EX_NONE)
32    return "_none";
33  else if (exception_code == android::binder::Status::EX_SECURITY)
34    return "_security";
35  else if (exception_code == android::binder::Status::EX_BAD_PARCELABLE)
36    return "_bad_parcelable";
37  else if (exception_code == android::binder::Status::EX_ILLEGAL_ARGUMENT)
38    return "_illegal_argument";
39  else if (exception_code == android::binder::Status::EX_NULL_POINTER)
40    return "_null_pointer";
41  else if (exception_code == android::binder::Status::EX_ILLEGAL_STATE)
42    return "_illegal_state";
43  else if (exception_code == android::binder::Status::EX_NETWORK_MAIN_THREAD)
44    return "_network_error";
45  else if (exception_code == android::binder::Status::EX_UNSUPPORTED_OPERATION)
46    return "_unsupported_operation";
47  else if (exception_code == android::binder::Status::EX_SERVICE_SPECIFIC)
48    return "_general_failure";
49
50  return "_unknown";
51}
52
53}  // anonymous namespace
54
55Command::Command(const android::sp<android::weave::IWeaveCommand>& proxy)
56    : binder_proxy_{proxy} {}
57
58Command::~Command() {}
59
60std::string Command::GetID() const {
61  std::string id;
62  android::String16 id16;
63  if (binder_proxy_->getId(&id16).isOk())
64    id.assign(ToString(id16));
65  return id;
66}
67
68std::string Command::GetName() const {
69  std::string name;
70  android::String16 name16;
71  if (binder_proxy_->getId(&name16).isOk())
72    name.assign(ToString(name16));
73  return name;
74}
75
76std::string Command::GetComponent() const {
77  std::string component;
78  android::String16 component16;
79  if (binder_proxy_->getId(&component16).isOk())
80    component.assign(ToString(component16));
81  return component;
82}
83
84Command::State Command::GetState() const {
85  std::string state;
86  android::String16 state16;
87  if (binder_proxy_->getState(&state16).isOk())
88    state.assign(ToString(state16));
89  if (state == "queued")
90    return Command::State::kQueued;
91  else if (state == "inProgress")
92    return Command::State::kInProgress;
93  else if (state == "paused")
94    return Command::State::kPaused;
95  else if (state == "error")
96    return Command::State::kError;
97  else if (state == "done")
98    return Command::State::kDone;
99  else if (state == "cancelled")
100    return Command::State::kCancelled;
101  else if (state == "aborted")
102    return Command::State::kAborted;
103  else if (state == "expired")
104    return Command::State::kExpired;
105  LOG(WARNING) << "Unknown command state: " << state;
106  return Command::State::kQueued;
107}
108
109Command::Origin Command::GetOrigin() const {
110  std::string origin;
111  android::String16 origin16;
112  if (binder_proxy_->getState(&origin16).isOk())
113    origin.assign(ToString(origin16));
114  if (origin == "local")
115    return Command::Origin::kLocal;
116  else if (origin == "cloud")
117    return Command::Origin::kCloud;
118  LOG(WARNING) << "Unknown command origin: " << origin;
119  return Command::Origin::kLocal;
120}
121
122const base::DictionaryValue& Command::GetParameters() const {
123  if (!parameter_cache_) {
124    android::String16 params_string16;
125    if (!binder_proxy_->getParameters(&params_string16).isOk() ||
126        !ParseDictionary(params_string16, &parameter_cache_).isOk()) {
127      parameter_cache_.reset(new base::DictionaryValue);
128    }
129  }
130  return *parameter_cache_;
131}
132
133bool Command::SetProgress(const base::DictionaryValue& progress,
134                          brillo::ErrorPtr* error) {
135  return StatusToError(binder_proxy_->setProgress(ToString16(progress)), error);
136}
137
138bool Command::Complete(const base::DictionaryValue& results,
139                       brillo::ErrorPtr* error) {
140  return StatusToError(binder_proxy_->complete(ToString16(results)), error);
141}
142
143bool Command::Abort(const std::string& error_code,
144                    const std::string& error_message,
145                    brillo::ErrorPtr* error) {
146  return StatusToError(binder_proxy_->abort(ToString16(error_code),
147                                            ToString16(error_message)),
148                       error);
149}
150
151bool Command::AbortWithCustomError(const brillo::Error* command_error,
152                                   brillo::ErrorPtr* error) {
153  std::string error_code = "_" + command_error->GetCode();
154  return Abort(error_code, command_error->GetMessage(), error);
155}
156
157bool Command::AbortWithCustomError(android::binder::Status status,
158                                   brillo::ErrorPtr* error) {
159  std::string error_code = BinderExceptionString(status.exceptionCode());
160  return Abort(error_code, status.exceptionMessage().string(), error);
161}
162
163bool Command::Cancel(brillo::ErrorPtr* error) {
164  return StatusToError(binder_proxy_->cancel(), error);
165}
166
167bool Command::Pause(brillo::ErrorPtr* error) {
168  return StatusToError(binder_proxy_->pause(), error);
169}
170
171bool Command::SetError(const std::string& error_code,
172                       const std::string& error_message,
173                       brillo::ErrorPtr* error) {
174  return StatusToError(binder_proxy_->setError(ToString16(error_code),
175                                               ToString16(error_message)),
176                       error);
177}
178
179bool Command::SetCustomError(const brillo::Error* command_error,
180                             brillo::ErrorPtr* error) {
181  std::string error_code = "_" + command_error->GetCode();
182  return SetError(error_code, command_error->GetMessage(), error);
183}
184
185bool Command::SetCustomError(android::binder::Status status,
186                             brillo::ErrorPtr* error) {
187  std::string error_code = BinderExceptionString(status.exceptionCode());
188  return SetError(error_code, status.exceptionMessage().string(), error);
189}
190
191}  // namespace weave
192