Update change log and spec for wrt-plugins-tizen_0.4.65
[platform/framework/web/wrt-plugins-tizen.git] / src / Power / PowerManager.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 #include "PowerManager.h"
19 #include <cstring>
20 #include <power.h>
21 #include <pmapi.h>
22 #include <device.h>
23 #include <algorithm>
24 #include <PlatformException.h>
25 #include <JSUtil.h>
26 #include <vconf.h>
27 #include <Logger.h>
28 #include <unistd.h>
29
30 using namespace DeviceAPI::Common;
31 using namespace std;
32
33 namespace DeviceAPI {
34 namespace Power {
35
36 PowerResource::PowerResource(const char *resource)
37 {
38     if( strcmp(resource,"SCREEN") == 0 )
39         mType = SCREEN;
40     else if( strcmp(resource,"CPU") == 0 )
41        mType = CPU;
42     else
43        throw TypeMismatchException("value is not PowerResource type");
44 };
45
46 const std::string PowerResource::toString(){
47     static const char *table[] = {"SCREEN", "CPU"};
48     return std::string(table[mType]);
49 }
50
51
52 PowerState::PowerState(const char *str)
53 {
54     static const char *table[] = { "SCREEN_OFF", "SCREEN_DIM", "SCREEN_NORMAL", "SCREEN_BRIGHT", "CPU_AWAKE"};
55     static state state_table[] = { SCREENOFF, SCREENDIM, SCREENNORMAL, SCREENBRIGHT, CPUAWAKE };
56     for(unsigned int i =0; i < sizeof(table)/sizeof(char*) ; i++){
57         if( strcmp(str, table[i]) == 0 ){
58             mState = state_table[i];
59             return;
60         }
61     }
62     throw TypeMismatchException("value is not PowerState type");
63 };
64
65 PowerState::PowerState(state in):mState(in){
66 }
67
68 const std::string PowerState::toString(){
69     static const char *table[] = { "SCREEN_OFF", "SCREEN_DIM", "SCREEN_NORMAL", "SCREEN_BRIGHT", "CPU_AWAKE"};
70     return std::string(table[mState]);
71 }
72
73
74 void PowerManager::onPlatformStateChangedCB(power_state_e state, void *user_data){
75     PowerManager* object = static_cast<PowerManager*>(user_data);
76     if(object == NULL){
77         LoggerE("User data is NULL");
78         return;
79     }
80     PowerState current(PowerState::SCREENOFF);
81     switch( state ){
82         case POWER_STATE_NORMAL :
83             current.mState = object->mBrightStateEnable ? PowerState::SCREENBRIGHT : PowerState::SCREENNORMAL;
84             break;
85         case POWER_STATE_SCREEN_DIM :
86             current.mState = PowerState::SCREENDIM;
87             break;
88         case POWER_STATE_SCREEN_OFF :
89             current.mState = PowerState::SCREENOFF;
90             break;
91     }
92     object->broadcastScreenState(current);
93 }
94
95
96 void PowerManager::request(PowerResource resource, PowerState state){
97     if( resource == PowerResource::SCREEN && state == PowerState::CPUAWAKE)
98         throw InvalidValuesException("invalid PowerState");
99     if( resource == PowerResource::CPU && state != PowerState::CPUAWAKE)
100         throw InvalidValuesException("invalid PowerState");
101
102     int ret=0;
103     switch( state ){
104         case PowerState::SCREENDIM :
105         case PowerState::SCREENNORMAL :
106         case PowerState::CPUAWAKE :
107         {
108             int native_state = POWER_STATE_SCREEN_OFF;
109             if( state == PowerState::SCREENDIM )
110                 native_state = POWER_STATE_SCREEN_DIM;
111             else if( state == PowerState::SCREENNORMAL )
112                 native_state = POWER_STATE_NORMAL;
113             else
114                 native_state = POWER_STATE_SCREEN_OFF;
115
116             ret = power_lock_state( (power_state_e)native_state , 0);
117             if( POWER_ERROR_NONE!=ret ){
118                 LoggerE("power_lock_state(%d) error %d",native_state, ret);
119                 throw UnknownException("power_lock_state error");
120             }
121             break;
122         }
123         case PowerState::SCREENBRIGHT :
124         {
125             int maxBrightness;
126             ret = device_get_max_brightness(0, &maxBrightness);
127             if( DEVICE_ERROR_NONE!=ret) {
128                 LoggerE("Platform error while getting max brightness: %d", ret);
129                 throw UnknownException("Platform error while getting max brightness");
130             }
131
132             setPlatformBrightness( maxBrightness );
133
134             LOGI("Succeeded setting the brightness to a max level: %d", maxBrightness);
135             ret = power_lock_state(POWER_STATE_NORMAL, 0);
136             if( POWER_ERROR_NONE!=ret ){
137                 LoggerE("Platform error while locking state %d", ret);
138                 throw UnknownException("Platform error while locking state");
139             }
140
141             mBrightStateEnable = true;
142             power_state_e platform_state = power_get_state();
143             if( platform_state ==  POWER_STATE_NORMAL)
144                 broadcastScreenState(PowerState::SCREENBRIGHT);
145             break;
146         }
147         case PowerState::SCREENOFF:
148             LoggerE("SCREEN_OFF state cannot be requested");
149             throw InvalidValuesException("SCREEN_OFF state cannot be requested");
150
151         default :
152             throw UnknownException("Platform error while locking state");
153     }
154 }
155
156 void PowerManager::release(PowerResource resource){
157     int ret;
158     if( PowerResource::SCREEN == resource ) {
159         ret = power_unlock_state(POWER_STATE_SCREEN_DIM);
160         if( POWER_ERROR_NONE!=ret )
161             LOGI("Platform return value from dim unlock: %d", ret);
162
163         ret = power_unlock_state(POWER_STATE_NORMAL);
164         if( POWER_ERROR_NONE!=ret )
165             LOGI("Platform return value from dim unlock: %d", ret);
166
167         if( mBrightStateEnable ){
168             ret = device_set_brightness_from_settings(0);
169             if( DEVICE_ERROR_NONE!=ret){
170                 LoggerE("Platform error while setting restore brightness %d", ret);
171                 throw UnknownException("Platform error while setting restore brightness");
172             }
173         }
174
175         mBrightStateEnable = false;
176         power_state_e platform_state = power_get_state();
177         if( platform_state ==  POWER_STATE_NORMAL)
178             broadcastScreenState(PowerState::SCREENNORMAL);
179
180     } else if( PowerResource::CPU == resource ) {
181         ret = power_unlock_state(POWER_STATE_SCREEN_OFF);
182         if( POWER_ERROR_NONE!=ret )
183             LOGI("Platform return value from off unlock: %d", ret);
184     }
185 }
186
187 double PowerManager::getScreenBrightness(){
188     int brightness;
189     brightness = getPlatformBrightness();
190     LOGI("Brightness value: %d", brightness);
191     return brightness/100.0;
192 }
193
194 void PowerManager::setScreenBrightness(double brightness){
195     int ret;
196     if( brightness > 1 || brightness < 0 )
197         throw InvalidValuesException("brightness should be 0 <= brightness <= 1");
198     int maxBrightness;
199     ret = device_get_max_brightness(0, &maxBrightness);
200     if( ret != 0 ){
201         LoggerE("Platform error while setting restore brightness: %d", ret);
202         throw UnknownException("Platform error while getting max brightness");
203     }
204     int nativeBrightness = (int)(brightness*maxBrightness);
205
206     if (nativeBrightness == 0)
207         nativeBrightness = 1;
208
209     setPlatformBrightness(nativeBrightness);
210     LOGI("Set the brightness value: %d", nativeBrightness);
211 }
212
213 bool PowerManager::isScreenOn(){
214     power_state_e state = power_get_state();
215     if(POWER_STATE_SCREEN_OFF==state)
216         return false;
217     else
218         return true;
219 }
220
221 void PowerManager::setScreenState(bool onoff){
222     int ret = 0;
223     if( onoff )
224         ret = pm_change_state(LCD_NORMAL);
225     else
226         ret = pm_change_state(LCD_OFF);
227
228     if( ret<0 ){
229         LoggerE("Platform error while changing screen state %d", ret);
230         throw UnknownException("Platform error while changing screen state");
231     }
232
233     int timeout=100;
234     while(timeout--){
235         if( isScreenOn() == onoff )
236             break;
237         usleep(100000);
238     }
239
240 }
241
242 void PowerManager::restoreScreenBrightness(){
243     int ret;
244     ret = device_set_brightness_from_settings(0);
245     if( DEVICE_ERROR_NONE!=ret){
246         LoggerE("Platform error while restoring brightness %d", ret);
247         throw UnknownException("Platform error while restoring brightness");
248     }
249 }
250
251 PowerManager* PowerManager::getInstance(){
252     static PowerManager instance;
253     return &instance;
254 }
255
256 void PowerManager::addScreenStateChangedCallback(Common::CallbackUserData * callback){
257     list<CallbackUserData*>::iterator itr;
258     itr = find(mListener.begin(), mListener.end(), callback);
259     if( itr == mListener.end() )
260         mListener.push_back(callback);
261 }
262
263 void PowerManager::removeScreenStateChangedCallback(Common::CallbackUserData * callback){
264     mListener.remove(callback);
265 }
266
267 void PowerManager::setPlatformBrightness(int brightness){
268
269
270     if( mCurrentState.mState == PowerState::SCREENDIM ){
271         mCurrentBrightness = brightness;
272         LOGI("Current state is not normal state the value is saved in cache: %d", brightness);
273         mShouldBeReadFromCache = true;
274         return;
275     }else
276         mShouldBeReadFromCache = false;
277
278     int ret = device_set_brightness(0, brightness);
279     if( ret != 0){
280         LoggerE("Platform error while setting %d brightness: %d", brightness, ret);
281         throw UnknownException("Platform error while setting brightness.");
282     }
283     mCurrentBrightness = brightness;
284 }
285
286 int PowerManager::getPlatformBrightness(){
287     int currentPowerState = 1;
288     int brightness = 0;
289     int isCustomMode = 0;
290     int isAutoBrightness = 0;
291     int ret = 0;
292
293     vconf_get_int(VCONFKEY_PM_STATE, &currentPowerState);
294     if( currentPowerState == VCONFKEY_PM_STATE_NORMAL){
295         vconf_get_int(VCONFKEY_PM_CURRENT_BRIGHTNESS, &brightness);
296         LOGD("[PM_STATE_NORMAL] return VCONFKEY_PM_CURRENT_BRIGHTNESS %d", brightness);
297         return brightness;
298     }
299
300     vconf_get_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, &isCustomMode);
301     if( (isCustomMode && mCurrentBrightness != -1) || mShouldBeReadFromCache ){
302         LOGD("return custom brightness %d", mCurrentBrightness);
303         return mCurrentBrightness;
304     }
305
306     vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &isAutoBrightness);
307     if( isAutoBrightness == 1 ){
308         ret = vconf_get_int(VCONFKEY_SETAPPL_PREFIX"/automatic_brightness_level" /*prevent RSA build error*/, &brightness);
309         if( ret != 0 ) //RSA binary has no AUTOMATIC_BRIGHTNESS
310             vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, &brightness);
311     }else{
312         vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, &brightness);
313     }
314     LOGD("BRIGHTNESS(%s) %d", isAutoBrightness == 1 ? "auto" : "fix" , brightness);
315
316     return brightness;
317 }
318
319
320 void PowerManager::restoreSettedBrightness(){
321     int isCustomMode = 0;
322     vconf_get_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, &isCustomMode);
323     if( isCustomMode || mShouldBeReadFromCache ){
324         if( mCurrentBrightness == -1 ){
325             // brightness was changed in other process
326             restoreScreenBrightness();
327         }else{
328             setPlatformBrightness(mCurrentBrightness);
329         }
330     }
331     mShouldBeReadFromCache = false;
332 }
333
334 void PowerManager::broadcastScreenState(PowerState current){
335     if( mCurrentState == current)
336         return;
337
338     PowerState PreviousState = mCurrentState;
339     mCurrentState = current;
340
341     if( mCurrentState.mState == PowerState::SCREENNORMAL && PreviousState.mState == PowerState::SCREENDIM ){
342         //restore ScreenBrightness
343         try{
344             restoreSettedBrightness();
345         }
346         catch( const BasePlatformException& err){
347             LoggerE("Error restore custom brightness %s", err.getMessage().c_str());
348         }
349     }
350     if( mCurrentState.mState == PowerState::SCREENNORMAL && PreviousState.mState == PowerState::SCREENOFF){
351         mShouldBeReadFromCache = false;
352     }
353
354     list<CallbackUserData*> tmplist(mListener);
355     list<CallbackUserData*>::iterator itr = tmplist.begin();
356
357     while( itr != tmplist.end() ){
358         CallbackUserData *callback = *itr;
359         if( callback != NULL ){
360             JSValueRef previousState = JSUtil::toJSValueRef(callback->getContext(), PreviousState.toString());
361             JSValueRef currentState = JSUtil::toJSValueRef(callback->getContext(), mCurrentState.toString());
362             JSValueRef args[2] = { previousState, currentState };
363             callback->callSuccessCallback(2, args);
364         }
365         ++itr;
366     }
367 }
368
369
370 PowerManager::PowerManager():mCurrentState(PowerState::SCREENNORMAL),mBrightStateEnable(false),mCurrentBrightness(-1),mShouldBeReadFromCache(false){
371     power_state_e platform_state = power_get_state();
372     switch( platform_state ){
373         case POWER_STATE_NORMAL :
374             mCurrentState.mState = PowerState::SCREENNORMAL;
375             break;
376         case POWER_STATE_SCREEN_DIM :
377             mCurrentState.mState = PowerState::SCREENDIM;
378             break;
379         case POWER_STATE_SCREEN_OFF :
380             mCurrentState.mState = PowerState::SCREENOFF;
381             break;
382     }
383     power_set_changed_cb(PowerManager::onPlatformStateChangedCB, this);
384 }
385 PowerManager::~PowerManager(){
386     power_unset_changed_cb();
387 }
388
389 } //Power
390 } //DeviceAPI
391