Update change log and spec for wrt-plugins-tizen_0.4.51
[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     setPlatformBrightness(nativeBrightness);
207     LOGI("Set the brightness value: %d", nativeBrightness);
208 }
209
210 bool PowerManager::isScreenOn(){
211     power_state_e state = power_get_state();
212     if(POWER_STATE_SCREEN_OFF==state)
213         return false;
214     else
215         return true;
216 }
217
218 void PowerManager::setScreenState(bool onoff){
219     int ret = 0;
220     if( onoff )
221         ret = pm_change_state(LCD_NORMAL);
222     else
223         ret = pm_change_state(LCD_OFF);
224
225     if( ret<0 ){
226         LoggerE("Platform error while changing screen state %d", ret);
227         throw UnknownException("Platform error while changing screen state");
228     }
229
230     int timeout=100;
231     while(timeout--){
232         if( isScreenOn() == onoff )
233             break;
234         usleep(100000);
235     }
236
237 }
238
239 void PowerManager::restoreScreenBrightness(){
240     int ret;
241     ret = device_set_brightness_from_settings(0);
242     if( DEVICE_ERROR_NONE!=ret){
243         LoggerE("Platform error while restoring brightness %d", ret);
244         throw UnknownException("Platform error while restoring brightness");
245     }
246 }
247
248 PowerManager* PowerManager::getInstance(){
249     static PowerManager instance;
250     return &instance;
251 }
252
253 void PowerManager::addScreenStateChangedCallback(Common::CallbackUserData * callback){
254     list<CallbackUserData*>::iterator itr;
255     itr = find(mListener.begin(), mListener.end(), callback);
256     if( itr == mListener.end() )
257         mListener.push_back(callback);
258 }
259
260 void PowerManager::removeScreenStateChangedCallback(Common::CallbackUserData * callback){
261     mListener.remove(callback);
262 }
263
264 void PowerManager::setPlatformBrightness(int brightness){
265
266
267     if( mCurrentState.mState == PowerState::SCREENDIM ){
268         mCurrentBrightness = brightness;
269         LOGI("Current state is not normal state the value is saved in cache: %d", brightness);
270         mShouldBeReadFromCache = true;
271         return;
272     }else
273         mShouldBeReadFromCache = false;
274
275     int ret = device_set_brightness(0, brightness);
276     if( ret != 0){
277         LoggerE("Platform error while setting %d brightness: %d", brightness, ret);
278         throw UnknownException("Platform error while setting brightness.");
279     }
280     mCurrentBrightness = brightness;
281 }
282
283 int PowerManager::getPlatformBrightness(){
284     int brightness = 0;
285     int ret = 0;
286
287     int isCustomMode = 0;
288     vconf_get_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, &isCustomMode);
289     if( (isCustomMode && mCurrentBrightness != -1) || mShouldBeReadFromCache ){
290         LOGI("return custom brightness %d", mCurrentBrightness);
291         return mCurrentBrightness;
292     }
293
294     ret = vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, &brightness);
295     if( ret != 0 ){
296         LoggerE("Platform error while getting brightness: %d", ret);
297         throw UnknownException("Platform error while getting brightness");
298     }
299     LoggerE("VCONFKEY_SETAPPL_LCD_BRIGHTNESS %d", brightness);
300
301     return brightness;
302 }
303
304
305 void PowerManager::restoreSettedBrightness(){
306     int isCustomMode = 0;
307     vconf_get_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, &isCustomMode);
308     if( isCustomMode || mShouldBeReadFromCache ){
309         if( mCurrentBrightness == -1 ){
310             // brightness was changed in other process
311             restoreScreenBrightness();
312         }else{
313             setPlatformBrightness(mCurrentBrightness);
314         }
315     }
316     mShouldBeReadFromCache = false;
317 }
318
319 void PowerManager::broadcastScreenState(PowerState current){
320     if( mCurrentState == current)
321         return;
322
323     PowerState PreviousState = mCurrentState;
324     mCurrentState = current;
325
326     if( mCurrentState.mState == PowerState::SCREENNORMAL && PreviousState.mState == PowerState::SCREENDIM ){
327         //restore ScreenBrightness
328         try{
329             restoreSettedBrightness();
330         }
331         catch( const BasePlatformException& err){
332             LoggerE("Error restore custom brightness %s", err.getMessage().c_str());
333         }
334     }
335     if( mCurrentState.mState == PowerState::SCREENNORMAL && PreviousState.mState == PowerState::SCREENOFF){
336         mShouldBeReadFromCache = false;
337     }
338
339     list<CallbackUserData*> tmplist(mListener);
340     list<CallbackUserData*>::iterator itr = tmplist.begin();
341
342     while( itr != tmplist.end() ){
343         CallbackUserData *callback = *itr;
344         if( callback != NULL ){
345             JSValueRef previousState = JSUtil::toJSValueRef(callback->getContext(), PreviousState.toString());
346             JSValueRef currentState = JSUtil::toJSValueRef(callback->getContext(), mCurrentState.toString());
347             JSValueRef args[2] = { previousState, currentState };
348             callback->callSuccessCallback(2, args);
349         }
350         ++itr;
351     }
352 }
353
354
355 PowerManager::PowerManager():mCurrentState(PowerState::SCREENNORMAL),mBrightStateEnable(false),mCurrentBrightness(-1),mShouldBeReadFromCache(false){
356     power_state_e platform_state = power_get_state();
357     switch( platform_state ){
358         case POWER_STATE_NORMAL :
359             mCurrentState.mState = PowerState::SCREENNORMAL;
360             break;
361         case POWER_STATE_SCREEN_DIM :
362             mCurrentState.mState = PowerState::SCREENDIM;
363             break;
364         case POWER_STATE_SCREEN_OFF :
365             mCurrentState.mState = PowerState::SCREENOFF;
366             break;
367     }
368     power_set_changed_cb(PowerManager::onPlatformStateChangedCB, this);
369 }
370 PowerManager::~PowerManager(){
371     power_unset_changed_cb();
372 }
373
374 } //Power
375 } //DeviceAPI
376