Home | History | Annotate | Download | only in power
      1 /*
      2  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  * *    * Redistributions of source code must retain the above copyright
      8  *       notice, this list of conditions and the following disclaimer.
      9  *     * Redistributions in binary form must reproduce the above
     10  *       copyright notice, this list of conditions and the following
     11  *       disclaimer in the documentation and/or other materials provided
     12  *       with the distribution.
     13  *     * Neither the name of The Linux Foundation nor the names of its
     14  *       contributors may be used to endorse or promote products derived
     15  *       from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 #define LOG_NIDEBUG 0
     30 
     31 #include <errno.h>
     32 #include <string.h>
     33 #include <sys/types.h>
     34 #include <sys/stat.h>
     35 #include <fcntl.h>
     36 #include <dlfcn.h>
     37 #include <stdlib.h>
     38 
     39 #define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
     40 #define LOG_TAG "QCOM PowerHAL"
     41 #include <utils/Log.h>
     42 #include <cutils/trace.h>
     43 #include <hardware/hardware.h>
     44 #include <hardware/power.h>
     45 
     46 #include "utils.h"
     47 #include "metadata-defs.h"
     48 #include "hint-data.h"
     49 #include "performance.h"
     50 #include "power-common.h"
     51 #include "powerhintparser.h"
     52 
     53 static int sustained_mode_handle = 0;
     54 static int vr_mode_handle = 0;
     55 static int launch_handle = 0;
     56 static int sustained_performance_mode = 0;
     57 static int vr_mode = 0;
     58 static int launch_mode = 0;
     59 #define CHECK_HANDLE(x) (((x)>0) && ((x)!=-1))
     60 
     61 int is_perf_hint_active(int hint)
     62 {
     63     switch (hint) {
     64         case SUSTAINED_PERF_HINT_ID:
     65             return sustained_performance_mode != 0;
     66         case VR_MODE_HINT_ID:
     67             return vr_mode != 0;
     68         case VR_MODE_SUSTAINED_PERF_HINT_ID:
     69             return vr_mode != 0 && sustained_performance_mode != 0;
     70     }
     71     return 0;
     72 }
     73 
     74 static int process_sustained_perf_hint(void *data)
     75 {
     76     int duration = 0;
     77     int *resource_values = NULL;
     78     int resources = 0;
     79 
     80     if (data && sustained_performance_mode == 0) {
     81         if (vr_mode == 0) { // Sustained mode only.
     82             resource_values = getPowerhint(SUSTAINED_PERF_HINT_ID, &resources);
     83             if (!resource_values) {
     84                 ALOGE("Can't get sustained perf hints from xml ");
     85                 return HINT_NONE;
     86             }
     87             sustained_mode_handle = interaction_with_handle(
     88                 sustained_mode_handle, duration, resources, resource_values);
     89             if (!CHECK_HANDLE(sustained_mode_handle)) {
     90                 ALOGE("Failed interaction_with_handle for sustained_mode_handle");
     91                 return HINT_NONE;
     92             }
     93         } else if (vr_mode == 1) { // Sustained + VR mode.
     94             release_request(vr_mode_handle);
     95             resource_values = getPowerhint(VR_MODE_SUSTAINED_PERF_HINT_ID, &resources);
     96             if (!resource_values) {
     97                 ALOGE("Can't get VR mode sustained perf hints from xml ");
     98                 return HINT_NONE;
     99             }
    100             sustained_mode_handle = interaction_with_handle(
    101                 sustained_mode_handle, duration, resources, resource_values);
    102             if (!CHECK_HANDLE(sustained_mode_handle)) {
    103                 ALOGE("Failed interaction_with_handle for sustained_mode_handle");
    104                 return HINT_NONE;
    105             }
    106         }
    107         sustained_performance_mode = 1;
    108     } else if (sustained_performance_mode == 1) {
    109         release_request(sustained_mode_handle);
    110         if (vr_mode == 1) { // Switch back to VR Mode.
    111             resource_values = getPowerhint(VR_MODE_HINT_ID, &resources);
    112             if (!resource_values) {
    113                 ALOGE("Can't get VR mode perf hints from xml ");
    114                 return HINT_NONE;
    115             }
    116             vr_mode_handle = interaction_with_handle(
    117                 vr_mode_handle, duration, resources, resource_values);
    118             if (!CHECK_HANDLE(vr_mode_handle)) {
    119                 ALOGE("Failed interaction_with_handle for vr_mode_handle");
    120                 return HINT_NONE;
    121             }
    122         }
    123         sustained_performance_mode = 0;
    124     }
    125     return HINT_HANDLED;
    126 }
    127 
    128 static int process_vr_mode_hint(void *data)
    129 {
    130     int duration = 0;
    131     int *resource_values = NULL;
    132     int resources = 0;
    133 
    134     if (data && vr_mode == 0) {
    135         if (sustained_performance_mode == 0) { // VR mode only.
    136             resource_values = getPowerhint(VR_MODE_HINT_ID, &resources);
    137             if (!resource_values) {
    138                 ALOGE("Can't get VR mode perf hints from xml ");
    139                 return HINT_NONE;
    140             }
    141             vr_mode_handle = interaction_with_handle(
    142                 vr_mode_handle, duration, resources, resource_values);
    143             if (!CHECK_HANDLE(vr_mode_handle)) {
    144                 ALOGE("Failed interaction_with_handle for vr_mode_handle");
    145                 return HINT_NONE;
    146             }
    147         } else if (sustained_performance_mode == 1) { // Sustained + VR mode.
    148             release_request(sustained_mode_handle);
    149             resource_values = getPowerhint(VR_MODE_SUSTAINED_PERF_HINT_ID, &resources);
    150             if (!resource_values) {
    151                 ALOGE("Can't get VR mode sustained perf hints from xml ");
    152                 return HINT_NONE;
    153             }
    154             vr_mode_handle = interaction_with_handle(
    155                 vr_mode_handle, duration, resources, resource_values);
    156             if (!CHECK_HANDLE(vr_mode_handle)) {
    157                 ALOGE("Failed interaction_with_handle for vr_mode_handle");
    158                 return HINT_NONE;
    159             }
    160         }
    161         vr_mode = 1;
    162     } else if (vr_mode == 1) {
    163         release_request(vr_mode_handle);
    164         if (sustained_performance_mode == 1) { // Switch back to sustained Mode.
    165             resource_values = getPowerhint(SUSTAINED_PERF_HINT_ID, &resources);
    166             if (!resource_values) {
    167                 ALOGE("Can't get sustained perf hints from xml ");
    168                 return HINT_NONE;
    169             }
    170             sustained_mode_handle = interaction_with_handle(
    171                 sustained_mode_handle, duration, resources, resource_values);
    172             if (!CHECK_HANDLE(sustained_mode_handle)) {
    173                 ALOGE("Failed interaction_with_handle for sustained_mode_handle");
    174                 return HINT_NONE;
    175             }
    176         }
    177         vr_mode = 0;
    178     }
    179 
    180     return HINT_HANDLED;
    181 }
    182 
    183 static int process_boost(int boost_handle, int duration)
    184 {
    185     int *resource_values;
    186     int resources;
    187 
    188     resource_values = getPowerhint(BOOST_HINT_ID, &resources);
    189 
    190     if (resource_values != NULL) {
    191         boost_handle = interaction_with_handle(
    192             boost_handle, duration, resources, resource_values);
    193         if (!CHECK_HANDLE(boost_handle)) {
    194             ALOGE("Failed interaction_with_handle for boost_handle");
    195         }
    196     }
    197 
    198     return boost_handle;
    199 }
    200 
    201 static int process_video_encode_hint(void *data)
    202 {
    203     static int boost_handle = -1;
    204 
    205     if (data) {
    206         // TODO: remove the launch boost based on camera launch time
    207         int duration = 2000; // boosts 2s for starting encoding
    208         boost_handle = process_boost(boost_handle, duration);
    209         ALOGD("LAUNCH ENCODER-ON: %d MS", duration);
    210         int *resource_values = NULL;
    211         int resources = 0;
    212         resource_values = getPowerhint(DEFAULT_VIDEO_ENCODE_HINT_ID, &resources);
    213         if (resource_values != NULL)
    214             perform_hint_action(DEFAULT_VIDEO_ENCODE_HINT_ID, resource_values, resources);
    215         ALOGD("Video Encode hint start");
    216         return HINT_HANDLED;
    217     } else {
    218         undo_hint_action(DEFAULT_VIDEO_ENCODE_HINT_ID);
    219         ALOGD("Video Encode hint stop");
    220         return HINT_HANDLED;
    221     }
    222     return HINT_NONE;
    223 }
    224 
    225 static int process_activity_launch_hint(void *data)
    226 {
    227     // boost will timeout in 1.25s
    228     int duration = 1250;
    229     ATRACE_BEGIN("launch");
    230     if (sustained_performance_mode || vr_mode) {
    231         ATRACE_END();
    232         return HINT_HANDLED;
    233     }
    234 
    235     ALOGD("LAUNCH HINT: %s", data ? "ON" : "OFF");
    236     // restart the launch hint if the framework has not yet released
    237     // this shouldn't happen, but we've seen bugs where it could
    238     if (data) {
    239         launch_handle = process_boost(launch_handle, duration);
    240         if (launch_handle > 0) {
    241             launch_mode = 1;
    242             ALOGD("Activity launch hint handled");
    243             ATRACE_INT("launch_lock", 1);
    244             ATRACE_END();
    245             return HINT_HANDLED;
    246         } else {
    247             ATRACE_END();
    248             return HINT_NONE;
    249         }
    250     } else if (data == NULL  && launch_mode == 1) {
    251         // framework release hints aren't necessarily reliable
    252         // always wait the full duration
    253         // release_request(launch_handle);
    254         ATRACE_INT("launch_lock", 0);
    255         launch_mode = 0;
    256         ATRACE_END();
    257         return HINT_HANDLED;
    258     }
    259     ATRACE_END();
    260     return HINT_NONE;
    261 }
    262 
    263 int power_hint_override(power_hint_t hint, void *data)
    264 {
    265     int ret_val = HINT_NONE;
    266     switch(hint) {
    267         case POWER_HINT_VIDEO_ENCODE:
    268             ret_val = process_video_encode_hint(data);
    269             break;
    270         case POWER_HINT_SUSTAINED_PERFORMANCE:
    271             ret_val = process_sustained_perf_hint(data);
    272             break;
    273         case POWER_HINT_VR_MODE:
    274             ret_val = process_vr_mode_hint(data);
    275             break;
    276         case POWER_HINT_LAUNCH:
    277             ret_val = process_activity_launch_hint(data);
    278             break;
    279         default:
    280             break;
    281     }
    282     return ret_val;
    283 }
    284 
    285 int set_interactive_override(int UNUSED(on))
    286 {
    287     return HINT_HANDLED; /* Don't excecute this code path, not in use */
    288 }
    289