2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <sys/types.h>
19 #include <app_manager.h>
23 #include "../shared/SystemInfo.h"
24 #include "AppStatisticsTypes.h"
25 #include "ActiveWindowMonitor.h"
27 /* Active window changes frequently.
28 * We thus consider the apps being foregrounded at least 3 secs */
29 #define ONE_DAY_IN_SEC 86400
31 ctx::AppUseMonitor::AppUseMonitor() :
34 __dbusWatcher(DBusType::SYSTEM)
39 ctx::AppUseMonitor::~AppUseMonitor()
44 bool ctx::AppUseMonitor::__startLogging()
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);
51 void ctx::AppUseMonitor::__stopLogging()
54 __dbusWatcher.unwatch(__signalId);
55 _D("Active window monitoring stopped");
59 void ctx::AppUseMonitor::onSignal(const char* sender, const char* path, const char* iface, const char* name, GVariant* param)
62 const gchar *appId = NULL;
63 const gchar *pkgId = NULL;
64 const gchar *status = NULL;
65 const gchar *type = NULL;
67 g_variant_get(param, "(i&s&s&s&s)", &pid, &appId, &pkgId, &status, &type);
68 _D("AppEvent: %s, %s, %s", appId, status, type);
70 IF_FAIL_VOID(appId && status && type);
71 IF_FAIL_VOID(STR_EQ(type, "uiapp") && !__isSkippable(appId));
73 if (STR_EQ(status, "fg")) {
74 __createRecord(appId);
75 } else if (STR_EQ(status, "bg")) {
76 __finishRecord(appId);
81 void ctx::AppUseMonitor::__createRecord(std::string appId)
88 data.set(NULL, KEY_APP_ID, appId);
90 if (ctx::system_info::getAudioJackState(&audioJack))
91 data.set(NULL, KEY_AUDIO_JACK, audioJack);
93 if (ctx::system_info::getVolume(&systemVolume, &mediaVolume)) {
94 data.set(NULL, KEY_SYSTEM_VOLUME, systemVolume);
95 data.set(NULL, KEY_MEDIA_VOLUME, mediaVolume);
98 if (ctx::system_info::getWifiBssid(bssid))
99 data.set(NULL, KEY_BSSID, bssid);
101 __dbManager.insert(0, APP_TABLE_USAGE_LOG, data, NULL);
104 void ctx::AppUseMonitor::__finishRecord(std::string appId)
106 /* TODO: It might be necessary to update system status here */
107 std::stringstream 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);
118 bool ctx::AppUseMonitor::__isSkippable(std::string appId)
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");
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");
133 app_info_destroy(appInfo);
137 void ctx::AppUseMonitor::__removeExpired()
139 int timestamp = static_cast<int>(time(NULL));
140 IF_FAIL_VOID(timestamp - __lastCleanupTime >= ONE_DAY_IN_SEC);
142 __lastCleanupTime = timestamp;
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);