[Application] Release data pointers as soon as possible 85/316185/1
authorPiotr Kosko/Tizen API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Tue, 3 Dec 2024 10:59:57 +0000 (11:59 +0100)
committerPiotr Kosko <p.kosko@samsung.com>
Wed, 11 Dec 2024 09:35:43 +0000 (09:35 +0000)
commitf9f8b0b1a5b8bcd0c5f80a153e970baf6c65a039
tree609c35f8d83d333d0c538bd7607cd5223d259a1d
parent3830d1aa587777ff3a4f2a9d1f9b93e29552b8ef
[Application] Release data pointers as soon as possible

Result and reply callback share user_data and the moment of releasing it
can be difficult to determine.

[Bug] Previous implementation was just holding all pointers through the
application lifetime, but this can be become a problem for applications
working continuously for really long time and starting other
applications with AppControl.

[JIRA] https://jira.sec.samsung.net/browse/TDAF-2090

[Fix] Current implementation makes few assumptions:
1. If Web Application doesn't set reply callback just assume that data
   need to be released in result callback.
2. Result callback and reply callback are always called on main
   application thread, thus there is no concurrency issues.
3. If reply callback is set, reference count is done to control the data
   release and data is released after callee will respond with data.
4. If callee doesn't respond to caller as expected, data handler would
   stay as 'pending' in memory and released during application closure.

[Verification] Code compiles without errors.
TCT application passrate 100% (M + A)

Additional verification scenarios with Callee application starting
Callee application, which respond with one of below options:
        var data = new tizen.ApplicationControlData(
        "test", ["test"]);
        // scenario 1 - reply once
        reqAppControl.replyResult([data]);

        // scenario 2 - call reply twice
reqAppControl.replyResult([data]);
reqAppControl.replyResult([data]);

// scenario 3 - no reply

// scenario 4 - delay
setTimeout(function() {
reqAppControl.replyResult([data]);
}, 10000);

// scenario 5 - instant reply and delayed
reqAppControl.replyResult([data]);
setTimeout(function() {
reqAppControl.replyResult([data]);
}, 5000);

// scenario 6 - two delayed replies
setTimeout(function() {
reqAppControl.replyResult([data]);
}, 5000);
setTimeout(function() {
reqAppControl.replyResult([data]);
}, 10000);

        // Failure cases:
        // scenario 1 - reply once
        reqAppControl.replyFailure();

        // scenario 2 - call reply twice
reqAppControl.replyFailure();
reqAppControl.replyFailure();

// scenario 3 - no reply

// scenario 4 - delay
setTimeout(function() {
reqAppControl.replyFailure();
}, 5000);

// scenario 5 - instant reply and delayed
reqAppControl.replyFailure();
setTimeout(function() {
reqAppControl.replyFailure();
}, 5000);

// scenario 6 - two delayed replies
setTimeout(function() {
reqAppControl.replyFailure();
}, 5000);
setTimeout(function() {
reqAppControl.replyFailure();
}, 10000);

Additionally checked scenarios with:
1. Scenario without optional reply callback - data released in result callback
2. Scenario with callee application being closed before receiving reply
   callback (instantly after launchAppControl() call) - data released in
destructor and properly handled in callbacks as 'not valid'
3. Scenario without a reply on callee side, caller keeps handle till the
   destructor and then just releases memory properly

Change-Id: If04d7fa488f416a2964303d3179d351fadf6f593
(cherry picked from commit 0b91d1ee9b4778ac91eab27614bad00f4c519f66)
src/application/application_manager.cc
src/application/application_manager.h