sensor: update app uninstall event dbus signal
[platform/core/context/context-provider.git] / src / app-stats / ActiveWindowMonitor.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <sys/types.h>
18 #include <time.h>
19 #include <app_manager.h>
20
21 #include <Json.h>
22 #include <Types.h>
23 #include "../shared/SystemInfo.h"
24 #include "AppStatisticsTypes.h"
25 #include "ActiveWindowMonitor.h"
26
27 /* Active window changes frequently.
28  * We thus consider the apps being foregrounded at least 3 secs */
29 #define ONE_DAY_IN_SEC 86400
30
31 ctx::AppUseMonitor::AppUseMonitor() :
32         __signalId(-1),
33         __lastCleanupTime(0),
34         __dbusWatcher(DBusType::SYSTEM)
35 {
36         __startLogging();
37 }
38
39 ctx::AppUseMonitor::~AppUseMonitor()
40 {
41         __stopLogging();
42 }
43
44 bool ctx::AppUseMonitor::__startLogging()
45 {
46         __signalId = __dbusWatcher.watch(NULL, "/Org/Tizen/Aul/AppStatus", "org.tizen.aul.AppStatus", "AppStatusChange", this);
47         _D("Active window monitoring started (%lld)", __signalId);
48         return (__signalId > 0);
49 }
50
51 void ctx::AppUseMonitor::__stopLogging()
52 {
53         if (__signalId > 0) {
54                 __dbusWatcher.unwatch(__signalId);
55                 _D("Active window monitoring stopped");
56         }
57 }
58
59 void ctx::AppUseMonitor::onSignal(const char* sender, const char* path, const char* iface, const char* name, GVariant* param)
60 {
61         gint pid = 0;
62         const gchar *appId = NULL;
63         const gchar *pkgId = NULL;
64         const gchar *status = NULL;
65         const gchar *type = NULL;
66
67         g_variant_get(param, "(i&s&s&s&s)", &pid, &appId, &pkgId, &status, &type);
68         _D("AppEvent: %s, %s, %s", appId, status, type);
69
70         IF_FAIL_VOID(appId && status && type);
71         IF_FAIL_VOID(STR_EQ(type, "uiapp") && !__isSkippable(appId));
72
73         if (STR_EQ(status, "fg")) {
74                 __createRecord(appId);
75         } else if (STR_EQ(status, "bg")) {
76                 __finishRecord(appId);
77                 __removeExpired();
78         }
79 }
80
81 void ctx::AppUseMonitor::__createRecord(std::string appId)
82 {
83         int audioJack;
84         int systemVolume;
85         int mediaVolume;
86         std::string bssid;
87         Json data;
88         data.set(NULL, KEY_APP_ID, appId);
89
90         if (ctx::system_info::getAudioJackState(&audioJack))
91                 data.set(NULL, KEY_AUDIO_JACK, audioJack);
92
93         if (ctx::system_info::getVolume(&systemVolume, &mediaVolume)) {
94                 data.set(NULL, KEY_SYSTEM_VOLUME, systemVolume);
95                 data.set(NULL, KEY_MEDIA_VOLUME, mediaVolume);
96         }
97
98         if (ctx::system_info::getWifiBssid(bssid))
99                 data.set(NULL, KEY_BSSID, bssid);
100
101         __dbManager.insert(0, APP_TABLE_USAGE_LOG, data, NULL);
102 }
103
104 void ctx::AppUseMonitor::__finishRecord(std::string appId)
105 {
106         /* TODO: It might be necessary to update system status here */
107         std::stringstream query;
108         query <<
109                 "UPDATE " APP_TABLE_USAGE_LOG \
110                 " SET " KEY_DURATION " = strftime('%s', 'now') - " KEY_UNIV_TIME \
111                 " WHERE " KEY_COL_ROW_ID " = (" \
112                         "SELECT MAX(" KEY_COL_ROW_ID ") FROM " APP_TABLE_USAGE_LOG \
113                         " WHERE " KEY_APP_ID " = '" << appId << "'" \
114                         " AND " KEY_DURATION " = 0)";
115         __dbManager.execute(0, query.str().c_str(), NULL);
116 }
117
118 bool ctx::AppUseMonitor::__isSkippable(std::string appId)
119 {
120         /* TODO: circular cache */
121         app_info_h appInfo = NULL;
122         int err = app_manager_get_app_info(appId.c_str(), &appInfo);
123         IF_FAIL_RETURN_TAG(err == APP_MANAGER_ERROR_NONE && appInfo, true, _E, "app_manager_get_app_info() failed");
124
125         bool nodisp = false;
126         err = app_info_is_nodisplay(appInfo, &nodisp);
127         if (err != APP_MANAGER_ERROR_NONE) {
128                 app_info_destroy(appInfo);
129                 _E("app_info_is_nodisplay() failed");
130                 return true;
131         }
132
133         app_info_destroy(appInfo);
134         return nodisp;
135 }
136
137 void ctx::AppUseMonitor::__removeExpired()
138 {
139         int timestamp = static_cast<int>(time(NULL));
140         IF_FAIL_VOID(timestamp - __lastCleanupTime >= ONE_DAY_IN_SEC);
141
142         __lastCleanupTime = timestamp;
143
144         std::stringstream query;
145         query << "DELETE FROM " APP_TABLE_USAGE_LOG " WHERE " \
146                 KEY_UNIV_TIME " < strftime('%s', 'now') - " << LOG_RETENTION_PERIOD;
147         __dbManager.execute(0, query.str().c_str(), NULL);
148 }