Add AlarmEvent publisher to support the time event of context-trigger 11/141211/4
authorMu-Woong Lee <muwoong.lee@samsung.com>
Fri, 28 Jul 2017 13:59:15 +0000 (22:59 +0900)
committerMu-Woong Lee <muwoong.lee@samsung.com>
Thu, 3 Aug 2017 11:26:14 +0000 (20:26 +0900)
Change-Id: I89ff1d2be18be227d07c5977090385c30bb12285
Signed-off-by: Mu-Woong Lee <muwoong.lee@samsung.com>
src/server/ContextPublisher.h
src/server/JobState.h
src/server/publisher/AlarmEvent.cpp [new file with mode: 0644]
src/shared/Attribute.cpp
src/shared/Attribute.h

index 7b85bdb..e5c8fc5 100644 (file)
@@ -40,8 +40,8 @@ namespace ctx {
        public:
                virtual ~ContextPublisher();
 
-               void addObserver(IContextObserver* observer, void* userData);
-               void removeObserver(IContextObserver* observer);
+               virtual void addObserver(IContextObserver* observer, void* userData);
+               virtual void removeObserver(IContextObserver* observer);
 
                virtual const char* getUri() const = 0;
                virtual const char* getPrivilege() const;
@@ -76,12 +76,12 @@ namespace ctx {
 
                Json::Value __data;
 
-       private:
                struct ObserverInfo {
                        IContextObserver* observer;
                        void* data;
                        ObserverInfo(IContextObserver* o, void* d);
                };
+
                std::list<ObserverInfo> __observers;
        };
 
index d71c568..35564f3 100644 (file)
@@ -37,6 +37,8 @@ namespace ctx {
                virtual void setClient(IClient* client);
                virtual void jobFinished();
 
+               JobInfo* getJobInfo();
+
        protected:
                JobState(JobRunner* runner);
                JobState(JobState* prevState);
@@ -44,7 +46,6 @@ namespace ctx {
                uid_t getUid() const;
                const std::string& getOwner() const;
                int getJobId() const;
-               JobInfo* getJobInfo();
                JobRunner* getJobRunner();
 
                void transit(JobState* nextState);
diff --git a/src/server/publisher/AlarmEvent.cpp b/src/server/publisher/AlarmEvent.cpp
new file mode 100644 (file)
index 0000000..166b2d2
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <map>
+#include <list>
+#include <system_info.h>
+#include <alarm.h>
+
+#include <ContextTypes.h>
+#include <JobSchedulerTypesPrivate.h>
+#include <job_scheduler_types_internal.h>
+#include <JobContext.h>
+#include <Attribute.h>
+#include "../JobState.h"
+#include "../ContextPublisher.h"
+#include "../IContextObserver.h"
+
+#define ONE_DAY        86400
+
+using namespace ctx;
+
+namespace {
+       class AlarmEvent : public ContextPublisher {
+       public:
+               AlarmEvent(uid_t uid);
+               ~AlarmEvent();
+
+               void addObserver(IContextObserver* observer, void* userData);
+               void removeObserver(IContextObserver* observer);
+
+               const char* getUri() const;
+               const char* getPrivilege() const;
+
+               bool isReadable() const;
+
+               bool isReady();
+               const Json::Value& getData();
+
+       protected:
+               void read();
+               void subscribe();
+               void unsubscribe();
+
+       private:
+               void __addTimer(IContextObserver* observer);
+               void __addTimer(IContextObserver* observer, int minOfDay);
+               void __removeTimer(IContextObserver* observer);
+
+               int __setAlarm(int minOfDay);
+               void __unsetAlarm(int alarmId);
+
+               static int __alarmCb(int alarmId, void* cbData);
+
+               struct TimerEntry {
+                       int alarmId;
+                       std::list<IContextObserver*> observers;
+                       TimerEntry() : alarmId(-1) {}
+               };
+
+               std::map<int, TimerEntry> __timers;
+       };
+}
+
+REGISTER_PUBLISHER(CTX_SCHED_URI_PREFIX "event/time", AlarmEvent)
+
+AlarmEvent::AlarmEvent(uid_t uid)
+{
+       _D("Created");
+}
+
+AlarmEvent::~AlarmEvent()
+{
+       unsubscribe();
+
+       _D("Destroyed");
+}
+
+void AlarmEvent::addObserver(IContextObserver* observer, void* userData)
+{
+       __observers.emplace_back(observer, userData);
+
+       __addTimer(observer);
+}
+
+void AlarmEvent::removeObserver(IContextObserver* observer)
+{
+       __observers.remove_if(
+                       [&](const ObserverInfo& info)->bool {
+                               return (info.observer == observer);
+                       });
+
+       __removeTimer(observer);
+}
+
+const char* AlarmEvent::getUri() const
+{
+       // This is not an officially supported context item
+       return CTX_SCHED_URI_PREFIX "event/time";
+}
+
+const char* AlarmEvent::getPrivilege() const
+{
+       return "http://tizen.org/privilege/alarm.set";
+}
+
+bool AlarmEvent::isReadable() const
+{
+       return false;
+}
+
+bool AlarmEvent::isReady()
+{
+       return true;
+}
+
+const Json::Value& AlarmEvent::getData()
+{
+       static const char* weekDays[] = {
+               VALUE(SUN), VALUE(MON), VALUE(TUE), VALUE(WED), VALUE(THU), VALUE(FRI), VALUE(SAT)
+       };
+
+       time_t rawtime;
+       struct tm timeInfo;
+
+       time(&rawtime);
+       tzset();
+       localtime_r(&rawtime, &timeInfo);
+
+       int dayOfMonth = timeInfo.tm_mday;
+       int minuteOfDay = timeInfo.tm_hour * 60 + timeInfo.tm_min;
+       const char* weekDay = weekDays[timeInfo.tm_wday];
+
+       __data[NAME(DAY_OF_MONTH)] = dayOfMonth;
+       __data[NAME(DAY_OF_WEEK)] = weekDay;
+       __data[NAME(TIME_OF_DAY)] = minuteOfDay;
+
+       return __data;
+}
+
+void AlarmEvent::read()
+{
+}
+
+void AlarmEvent::subscribe()
+{
+}
+
+void AlarmEvent::unsubscribe()
+{
+}
+
+void AlarmEvent::__addTimer(IContextObserver* observer)
+{
+       _D("Add Observer: %p", observer);
+
+       JobState* jobState = dynamic_cast<JobState*>(observer);
+       IF_FAIL_VOID_TAG(jobState, _W, "Casting failed");
+
+       OnDemandJobInfo* jobInfo = static_cast<OnDemandJobInfo*>(jobState->getJobInfo());
+
+       for (auto& trg : jobInfo->getTriggers()) {
+               if (trg->getUri() != getUri()) continue;
+
+               IntegerAttribute* attr = dynamic_cast<IntegerAttribute*>(trg->getAttribute(NAME(TIME_OF_DAY)));
+               if (!attr) continue;
+
+               for (auto& t : attr->getTargets()) {
+                       __addTimer(observer, t);
+               }
+       }
+}
+
+void AlarmEvent::__addTimer(IContextObserver* observer, int minOfDay)
+{
+       _D("Add Observer: %p, Time: %d", observer, minOfDay);
+
+       TimerEntry& entry = __timers[minOfDay];
+
+       if (entry.alarmId < 0)
+               entry.alarmId = __setAlarm(minOfDay);
+
+       entry.observers.push_back(observer);
+}
+
+void AlarmEvent::__removeTimer(IContextObserver* observer)
+{
+       _D("Remove Observer: %p", observer);
+
+       for (auto& it : __timers) {
+               TimerEntry& entry = it.second;
+               entry.observers.remove(observer);
+               if (entry.observers.empty()) {
+                       __unsetAlarm(entry.alarmId);
+                       entry.alarmId = -1;
+               }
+       }
+}
+
+int AlarmEvent::__setAlarm(int minOfDay)
+{
+       time_t rawTime;
+       struct tm timeInfo;
+
+       time(&rawTime);
+       tzset();
+       localtime_r(&rawTime, &timeInfo);
+
+       time_t now = timeInfo.tm_hour * 3600 + timeInfo.tm_min * 60 + timeInfo.tm_sec;
+       time_t diff = minOfDay * 60 - now;
+       if (diff < 0)
+               diff += ONE_DAY;
+
+       int alarmId = -1;
+       alarmmgr_add_alarm_withcb(ALARM_TYPE_VOLATILE, diff, ONE_DAY, __alarmCb, this, &alarmId);
+       _D("Alarm-%d at %d (S-%d)", alarmId, minOfDay, static_cast<int>(diff));
+
+       return alarmId;
+}
+
+void AlarmEvent::__unsetAlarm(int alarmId)
+{
+       _D("Unset Alarm-%d", alarmId);
+
+       alarmmgr_remove_alarm(alarmId);
+}
+
+int AlarmEvent::__alarmCb(int alarmId, void* cbData)
+{
+       AlarmEvent* pubs = static_cast<AlarmEvent*>(cbData);
+       pubs->notifyObservers();
+       return 0;
+}
index b7a36d9..950db58 100644 (file)
@@ -109,6 +109,11 @@ Attribute::Type IntegerAttribute::getType() const
        return Attribute::Type::INTEGER;
 }
 
+const std::set<int>& IntegerAttribute::getTargets()
+{
+       return __targets;
+}
+
 IntegerAttribute& IntegerAttribute::setClosedLowerBound(int bound)
 {
        __closedLowerBound = std::max(__closedLowerBound, bound);
index 9835132..0340683 100644 (file)
@@ -63,6 +63,8 @@ namespace ctx {
 
                Attribute::Type getType() const;
 
+               const std::set<int>& getTargets();
+
                IntegerAttribute& setClosedLowerBound(int bound);
                IntegerAttribute& setClosedUpperBound(int bound);
                IntegerAttribute& setOpenLowerBound(int bound);