cmsdk: Rework the PerformanceManager

* Added a proper API for this thing
 * Pass objects around with necessary metadata, pre-filtered and sorted
 * Added event log and service dump
 * Simplified locking and adjusted for performance / correctness
 * Clarified/beautified code where possible
 * TODO:
   - Write profile descriptions
   - Finish the UI
   - Clean up javadocs
   - Do something with per-app profiles, maybe

Change-Id: Ie2ef84031e81a18e95dcd62392c7e6939860d933
This commit is contained in:
Steve Kondik
2016-10-12 04:06:33 -07:00
parent 7928707006
commit cd98e0b30b
10 changed files with 690 additions and 135 deletions

View File

@@ -16,6 +16,8 @@
package cyanogenmod.power;
import cyanogenmod.power.PerformanceProfile;
/** @hide */
interface IPerformanceManager {
@@ -27,5 +29,9 @@ interface IPerformanceManager {
int getNumberOfProfiles();
boolean getProfileHasAppProfiles(int profile);
PerformanceProfile[] getPowerProfiles();
PerformanceProfile getPowerProfileById(int profile);
PerformanceProfile getActivePowerProfile();
}

View File

@@ -21,6 +21,11 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import java.util.Arrays;
import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;
import cyanogenmod.app.CMContextConstants;
/**
@@ -177,10 +182,31 @@ public class PerformanceManager {
return changed;
}
/**
* Set the system power profile
*
* @throws IllegalArgumentException if invalid
*/
public boolean setPowerProfile(PerformanceProfile profile) {
if (mNumberOfProfiles < 1) {
throw new IllegalArgumentException("Power profiles not enabled on this system!");
}
boolean changed = false;
try {
if (checkService()) {
changed = sService.setPowerProfile(profile.getId());
}
} catch (RemoteException e) {
throw new IllegalArgumentException(e);
}
return changed;
}
/**
* Gets the current power profile
*
* Returns null if power profiles are not enabled
* Returns -1 if power profiles are not enabled
*/
public int getPowerProfile() {
int ret = -1;
@@ -196,6 +222,43 @@ public class PerformanceManager {
return ret;
}
/**
* Gets the specified power profile
*
* Returns null if power profiles are not enabled or the profile was not found
*/
public PerformanceProfile getPowerProfile(int profile) {
PerformanceProfile ret = null;
if (mNumberOfProfiles > 0) {
try {
if (checkService()) {
ret = sService.getPowerProfileById(profile);
}
} catch (RemoteException e) {
// nothing
}
}
return ret;
}
/**
* Gets the currently active performance profile
*
* Returns null if no profiles are available.
*/
public PerformanceProfile getActivePowerProfile() {
PerformanceProfile ret = null;
if (mNumberOfProfiles > 0) {
try {
if (checkService()) {
ret = sService.getActivePowerProfile();
}
} catch (RemoteException e) {
// nothing
}
}
return ret;
}
/**
* Check if profile has app-specific profiles
*
@@ -206,7 +269,7 @@ public class PerformanceManager {
if (mNumberOfProfiles > 0) {
try {
if (checkService()) {
ret = sService.getProfileHasAppProfiles(profile);
ret = sService.getPowerProfileById(profile).isBoostEnabled();
}
} catch (RemoteException e) {
// nothing
@@ -214,4 +277,26 @@ public class PerformanceManager {
}
return ret;
}
/**
* Gets a set, sorted by weight, of all supported power profiles
*
* Returns an empty set if power profiles are not enabled
*/
public SortedSet<PerformanceProfile> getPowerProfiles() {
final SortedSet<PerformanceProfile> profiles = new TreeSet<PerformanceProfile>();
if (mNumberOfProfiles > 0) {
try {
if (checkService()) {
PerformanceProfile[] p = sService.getPowerProfiles();
if (p != null) {
profiles.addAll(Arrays.asList(p));
}
}
} catch (RemoteException e) {
// nothing
}
}
return Collections.unmodifiableSortedSet(profiles);
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cyanogenmod.power;
parcelable PerformanceProfile;

View File

@@ -0,0 +1,176 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cyanogenmod.power;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
import cyanogenmod.os.Build;
import cyanogenmod.os.Concierge;
/**
* Encapsulates information about an available system power/peformance profile, managed
* by the PerformanceManager.
*/
public class PerformanceProfile implements Parcelable, Comparable<PerformanceProfile> {
private final int mId;
private final float mWeight;
private final String mName;
private final String mDescription;
private final boolean mBoostEnabled;
public PerformanceProfile(int id, float weight, String name, String description,
boolean boostEnabled) {
mId = id;
mWeight = weight;
mName = name;
mDescription = description;
mBoostEnabled = boostEnabled;
}
private PerformanceProfile(Parcel in) {
Concierge.ParcelInfo parcelInfo = Concierge.receiveParcel(in);
int parcelableVersion = parcelInfo.getParcelVersion();
mId = in.readInt();
mWeight = in.readFloat();
mName = in.readString();
mDescription = in.readString();
mBoostEnabled = in.readInt() == 1;
if (parcelableVersion >= Build.CM_VERSION_CODES.GUAVA) {
// nothing yet
}
parcelInfo.complete();
}
/**
* Unique identifier for this profile. Must match values used by the PowerHAL.
*
* @return the id
*/
public int getId() {
return mId;
}
/**
* The profile's weight, from 0 to 1, with 0 being lowest (power save), 1 being
* highest (performance), and 0.5 as the balanced default profile. Other
* values may be seen, depending on the device. This value can be used for
* sorting.
*
* @return weight
*/
public float getWeight() {
return mWeight;
}
/**
* A localized name for the profile, suitable for display.
*
* @return name
*/
public String getName() {
return mName;
}
/**
* A localized description of the profile, suitable for display.
*
* @return description
*/
public String getDescription() {
return mDescription;
}
/**
* Whether or not per-app profiles and boosting will be used when this
* profile is active. Far-end modes (powersave / high performance) do
* not use boosting.
*
* @return true if boosting and per-app optimization will be used
*/
public boolean isBoostEnabled() {
return mBoostEnabled;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
Concierge.ParcelInfo parcelInfo = Concierge.prepareParcel(dest);
dest.writeInt(mId);
dest.writeFloat(mWeight);
dest.writeString(mName);
dest.writeString(mDescription);
dest.writeInt(mBoostEnabled ? 1 : 0);
parcelInfo.complete();
}
public static final Creator<PerformanceProfile> CREATOR = new Creator<PerformanceProfile>() {
@Override
public PerformanceProfile createFromParcel(Parcel in) {
return new PerformanceProfile(in);
}
@Override
public PerformanceProfile[] newArray(int size) {
return new PerformanceProfile[size];
}
};
@Override
public int compareTo(PerformanceProfile other) {
return Float.compare(mWeight, other.mWeight);
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (!getClass().equals(other.getClass())) {
return false;
}
PerformanceProfile o = (PerformanceProfile) other;
return Objects.equals(mId, o.mId);
}
@Override
public int hashCode() {
return Objects.hash(mId);
}
@Override
public String toString() {
return String.format("PerformanceProfile[id=%d, weight=%f, name=%s desc=%s " +
"boostEnabled=%b]", mId, mWeight, mName, mDescription, mBoostEnabled);
}
}