1ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki/* 2ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * Copyright (C) 2017 The Android Open Source Project 3ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * 4ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * Licensed under the Apache License, Version 2.0 (the "License"); 5ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * you may not use this file except in compliance with the License. 6ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * You may obtain a copy of the License at 7ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * 8ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * http://www.apache.org/licenses/LICENSE-2.0 9ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * 10ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * Unless required by applicable law or agreed to in writing, software 11ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * distributed under the License is distributed on an "AS IS" BASIS, 12ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * See the License for the specific language governing permissions and 14ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * limitations under the License. 15ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki */ 16ce643a309e8d414395ec36188523d10eb64d6618Makoto Onukipackage com.android.server.power.batterysaver; 17ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 18ce643a309e8d414395ec36188523d10eb64d6618Makoto Onukiimport android.util.ArrayMap; 19ce643a309e8d414395ec36188523d10eb64d6618Makoto Onukiimport android.util.Slog; 20ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 21ce643a309e8d414395ec36188523d10eb64d6618Makoto Onukiimport com.android.internal.annotations.GuardedBy; 22ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 23ce643a309e8d414395ec36188523d10eb64d6618Makoto Onukiimport java.util.Map; 24ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 25ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 26ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki/** 27ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * Helper to parse a list of "core-number:frequency" pairs concatenated with / as a separator, 28ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * and convert them into a map of "filename -> value" that should be written to 29ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * /sys/.../scaling_max_freq. 30ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * 31ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * Example input: "0:1900800/4:2500000", which will be converted into: 32ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq" "1900800" 33ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * "/sys/devices/system/cpu/cpu4/cpufreq/scaling_max_freq" "2500000" 34ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * 35ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * Test: 36ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/power/batterysaver/CpuFrequenciesTest.java 37ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki */ 38ce643a309e8d414395ec36188523d10eb64d6618Makoto Onukipublic class CpuFrequencies { 39ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki private static final String TAG = "CpuFrequencies"; 40ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 41ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki private final Object mLock = new Object(); 42ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 43ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki @GuardedBy("mLock") 44ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki private final ArrayMap<Integer, Long> mCoreAndFrequencies = new ArrayMap<>(); 45ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 46ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki public CpuFrequencies() { 47ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki } 48ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 49ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki /** 50ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * Parse a string. 51ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki */ 52ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki public CpuFrequencies parseString(String cpuNumberAndFrequencies) { 53ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki synchronized (mLock) { 54ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki mCoreAndFrequencies.clear(); 55ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki try { 56ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki for (String pair : cpuNumberAndFrequencies.split("/")) { 57afd6ff30816afc545cde4191d4eb56527ce207d6Makoto Onuki pair = pair.trim(); 58afd6ff30816afc545cde4191d4eb56527ce207d6Makoto Onuki if (pair.length() == 0) { 59afd6ff30816afc545cde4191d4eb56527ce207d6Makoto Onuki continue; 60afd6ff30816afc545cde4191d4eb56527ce207d6Makoto Onuki } 61ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki final String[] coreAndFreq = pair.split(":", 2); 62ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 63ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki if (coreAndFreq.length != 2) { 64ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki throw new IllegalArgumentException("Wrong format"); 65ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki } 66ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki final int core = Integer.parseInt(coreAndFreq[0]); 67ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki final long freq = Long.parseLong(coreAndFreq[1]); 68ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 69ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki mCoreAndFrequencies.put(core, freq); 70ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki } 71ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki } catch (IllegalArgumentException e) { 72afd6ff30816afc545cde4191d4eb56527ce207d6Makoto Onuki Slog.wtf(TAG, "Invalid configuration: '" + cpuNumberAndFrequencies + "'"); 73ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki } 74ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki } 75ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki return this; 76ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki } 77ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 78ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki /** 79ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * Return a new map containing the filename-value pairs. 80ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki */ 81ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki public ArrayMap<String, String> toSysFileMap() { 82ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki final ArrayMap<String, String> map = new ArrayMap<>(); 83ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki addToSysFileMap(map); 84ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki return map; 85ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki } 86ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 87ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki /** 88ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki * Add the filename-value pairs to an existing map. 89ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki */ 90ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki public void addToSysFileMap(Map<String, String> map) { 91ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki synchronized (mLock) { 92ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki final int size = mCoreAndFrequencies.size(); 93ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 94ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki for (int i = 0; i < size; i++) { 95ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki final int core = mCoreAndFrequencies.keyAt(i); 96ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki final long freq = mCoreAndFrequencies.valueAt(i); 97ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 98ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki final String file = "/sys/devices/system/cpu/cpu" + Integer.toString(core) + 99ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki "/cpufreq/scaling_max_freq"; 100ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki 101ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki map.put(file, Long.toString(freq)); 102ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki } 103ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki } 104ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki } 105ce643a309e8d414395ec36188523d10eb64d6618Makoto Onuki} 106