display: config: handle client destroy sequence gracefully
- Split the IDisplayConfigCallback implementation to a
separate class.
- Notify the device when a client is getting destroyed
and perform cleanup on device side.
Change-Id: I020a3a9cac7f31195e0072540e2145cdd3da274c
diff --git a/services/config/src/client_impl.cpp b/services/config/src/client_impl.cpp
index 483ad29..0e1cdab 100644
--- a/services/config/src/client_impl.cpp
+++ b/services/config/src/client_impl.cpp
@@ -47,13 +47,25 @@
handle = client_handle;
};
int pid = getpid();
- display_config_->registerClient(client_name + std::to_string(pid), this, hidl_callback);
+ android::sp<ClientCallback> client_cb(new ClientCallback(callback));
+ display_config_->registerClient(client_name + std::to_string(pid), client_cb,
+ hidl_callback);
client_handle_ = handle;
- callback_ = callback;
return 0;
}
+void ClientImpl::DeInit() {
+ int32_t error = 0;
+ auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+ error = err;
+ };
+
+ display_config_->perform(client_handle_, kDestroy, {}, {}, hidl_cb);
+ display_config_.clear();
+ display_config_ = nullptr;
+}
+
int ClientImpl::IsDisplayConnected(DisplayType dpy, bool *connected) {
ByteStream input_params;
input_params.setToExternal(reinterpret_cast<uint8_t*>(&dpy), sizeof(DisplayType));
@@ -623,10 +635,6 @@
int ClientImpl::SetCWBOutputBuffer(uint32_t disp_id, const Rect rect, bool post_processed,
const native_handle_t *buffer) {
- if (callback_ == nullptr) {
- return -EINVAL;
- }
-
struct CwbBufferParams input = {disp_id, rect, post_processed};
ByteStream input_params;
input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct CwbBufferParams));
@@ -834,11 +842,11 @@
return error;
}
-void ClientImpl::ParseNotifyCWBBufferDone(const ByteStream &input_params,
- const HandleStream &input_handles) {
+void ClientCallback::ParseNotifyCWBBufferDone(const ByteStream &input_params,
+ const HandleStream &input_handles) {
const int *error;
- if (input_params.size() == 0 || input_handles.size() == 0) {
+ if (callback_ == nullptr || input_params.size() == 0 || input_handles.size() == 0) {
return;
}
@@ -848,10 +856,10 @@
callback_->NotifyCWBBufferDone(*error, buffer.getNativeHandle());
}
-void ClientImpl::ParseNotifyQsyncChange(const ByteStream &input_params) {
+void ClientCallback::ParseNotifyQsyncChange(const ByteStream &input_params) {
const struct QsyncCallbackParams *qsync_data;
- if (input_params.size() == 0) {
+ if (callback_ == nullptr || input_params.size() == 0) {
return;
}
@@ -861,8 +869,8 @@
qsync_data->qsync_refresh_rate);
}
-Return<void> ClientImpl::perform(uint32_t op_code, const ByteStream &input_params,
- const HandleStream &input_handles) {
+Return<void> ClientCallback::perform(uint32_t op_code, const ByteStream &input_params,
+ const HandleStream &input_handles) {
switch (op_code) {
case kSetCwbOutputBuffer:
ParseNotifyCWBBufferDone(input_params, input_handles);
diff --git a/services/config/src/client_impl.h b/services/config/src/client_impl.h
index ebcfa85..a76d3de 100644
--- a/services/config/src/client_impl.h
+++ b/services/config/src/client_impl.h
@@ -50,9 +50,24 @@
typedef hidl_vec<uint8_t> ByteStream;
typedef hidl_vec<hidl_handle> HandleStream;
-class ClientImpl : public ClientInterface, public IDisplayConfigCallback {
+class ClientCallback: public IDisplayConfigCallback {
+ public:
+ ClientCallback(ConfigCallback *cb) {
+ callback_ = cb;
+ }
+
+ private:
+ virtual Return<void> perform(uint32_t op_code, const ByteStream &input_params,
+ const HandleStream &input_handles);
+ void ParseNotifyCWBBufferDone(const ByteStream &input_params, const HandleStream &input_handles);
+ void ParseNotifyQsyncChange(const ByteStream &input_params);
+ ConfigCallback *callback_ = nullptr;
+};
+
+class ClientImpl : public ClientInterface {
public:
int Init(std::string client_name, ConfigCallback *callback);
+ void DeInit();
virtual int IsDisplayConnected(DisplayType dpy, bool *connected);
virtual int SetDisplayStatus(DisplayType dpy, ExternalStatus status);
@@ -102,12 +117,7 @@
virtual int SendTUIEvent(DisplayType dpy, TUIEventType event_type);
private:
- virtual Return<void> perform(uint32_t op_code, const ByteStream &input_params,
- const HandleStream &input_handles);
- void ParseNotifyCWBBufferDone(const ByteStream &input_params, const HandleStream &input_handles);
- void ParseNotifyQsyncChange(const ByteStream &input_params);
android::sp<IDisplayConfig> display_config_ = nullptr;
- ConfigCallback *callback_ = nullptr;
uint64_t client_handle_ = 0;
};
diff --git a/services/config/src/client_interface.cpp b/services/config/src/client_interface.cpp
index 94be1b9..9c9ecd2 100644
--- a/services/config/src/client_interface.cpp
+++ b/services/config/src/client_interface.cpp
@@ -56,7 +56,9 @@
void ClientInterface::Destroy(ClientInterface *intf) {
if (intf) {
- delete static_cast<ClientImpl *>(intf);
+ ClientImpl *impl = static_cast<ClientImpl *>(intf);
+ impl->DeInit();
+ delete impl;
}
}
diff --git a/services/config/src/device_impl.cpp b/services/config/src/device_impl.cpp
index 37a0778..5a590a8 100644
--- a/services/config/src/device_impl.cpp
+++ b/services/config/src/device_impl.cpp
@@ -96,8 +96,11 @@
}
}
-DeviceImpl::DeviceClientContext::DeviceClientContext(const sp<IDisplayConfigCallback> callback) {
- callback_ = callback;
+DeviceImpl::DeviceClientContext::DeviceClientContext(
+ const sp<IDisplayConfigCallback> callback) : callback_(callback) { }
+
+sp<IDisplayConfigCallback> DeviceImpl::DeviceClientContext::GetDeviceConfigCallback() {
+ return callback_;
}
void DeviceImpl::DeviceClientContext::SetDeviceConfigIntf(ConfigInterface *intf) {
@@ -700,6 +703,26 @@
_hidl_cb(error, {}, {});
}
+void DeviceImpl::ParseDestroy(uint64_t client_handle, perform_cb _hidl_cb) {
+ auto itr = display_config_map_.find(client_handle);
+ if (itr == display_config_map_.end()) {
+ _hidl_cb(-EINVAL, {}, {});
+ return;
+ }
+
+ std::shared_ptr<DeviceClientContext> client = itr->second;
+ if (client != NULL) {
+ sp<IDisplayConfigCallback> callback = client->GetDeviceConfigCallback();
+ callback->unlinkToDeath(this);
+ ConfigInterface *intf = client->GetDeviceConfigIntf();
+ intf_->UnRegisterClientContext(intf);
+ client.reset();
+ display_config_map_.erase(itr);
+ }
+
+ _hidl_cb(0, {}, {});
+}
+
Return<void> DeviceImpl::perform(uint64_t client_handle, uint32_t op_code,
const ByteStream &input_params, const HandleStream &input_handles,
perform_cb _hidl_cb) {
@@ -847,6 +870,9 @@
case kSendTUIEvent:
client->ParseSendTUIEvent(input_params, _hidl_cb);
break;
+ case kDestroy:
+ ParseDestroy(client_handle, _hidl_cb);
+ break;
default:
break;
}
diff --git a/services/config/src/device_impl.h b/services/config/src/device_impl.h
index bc0c4a1..39b7587 100644
--- a/services/config/src/device_impl.h
+++ b/services/config/src/device_impl.h
@@ -66,6 +66,7 @@
void SetDeviceConfigIntf(ConfigInterface *intf);
ConfigInterface* GetDeviceConfigIntf();
+ sp<IDisplayConfigCallback> GetDeviceConfigCallback();
virtual void NotifyCWBBufferDone(int32_t error, const native_handle_t *buffer);
virtual void NotifyQsyncChange(bool qsync_enabled, int32_t refresh_rate,
@@ -119,7 +120,7 @@
private:
ConfigInterface *intf_ = nullptr;
- sp<IDisplayConfigCallback> callback_;
+ const sp<IDisplayConfigCallback> callback_;
};
Return<void> registerClient(const hidl_string &client_name, const sp<IDisplayConfigCallback>& cb,
@@ -128,6 +129,7 @@
const HandleStream &input_handles, perform_cb _hidl_cb) override;
void serviceDied(uint64_t client_handle,
const android::wp<::android::hidl::base::V1_0::IBase>& callback);
+ void ParseDestroy(uint64_t client_handle, perform_cb _hidl_cb);
ClientContext *intf_ = nullptr;
std::map<uint64_t, std::shared_ptr<DeviceClientContext>> display_config_map_;
diff --git a/services/config/src/opcode_types.h b/services/config/src/opcode_types.h
index 6f49b6f..b589d8a 100644
--- a/services/config/src/opcode_types.h
+++ b/services/config/src/opcode_types.h
@@ -76,6 +76,8 @@
kIsRotatorSupportedFormat = 40,
kControlQsyncCallback = 41,
kSendTUIEvent = 42,
+
+ kDestroy = 0xFFFF, // Destroy sequence execution
};
} // namespace DisplayConfig