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