Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a0e196a authored by Joe Onorato's avatar Joe Onorato Committed by Android (Google) Code Review
Browse files

Merge changes Ibc9ada6f,I2c5fce16

* changes:
  Power model calculation based on batterystats data.
  Parse the raw batterystats into an ActivityReport object.
parents 8faacd38 795bfbaa
Loading
Loading
Loading
Loading
+92 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source 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 com.android.powermodel;

import java.util.Collection;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.google.common.collect.ImmutableList;

/**
 * ActivityReport contains the summary of the activity that consumes power
 * as reported by batterystats or statsd.
 */
public class ActivityReport {
    private AppList<AppActivity> mApps;

    public ImmutableList<AppActivity> getAllApps() {
        return mApps.getAllApps();
    }

    public ImmutableList<AppActivity> getRegularApps() {
        return mApps.getRegularApps();
    }

    public List<AppActivity> findApp(String pkg) {
        return mApps.findApp(pkg);
    }

    public AppActivity findApp(SpecialApp specialApp) {
        return mApps.findApp(specialApp);
    }

    /**
     * Find a component in the GLOBAL app.
     * <p>
     * Returns null if either the global app doesn't exist (bad data?) or the component
     * doesn't exist in the global app.
     */
    public ComponentActivity findGlobalComponent(Component component) {
         final AppActivity global = mApps.findApp(SpecialApp.GLOBAL);
         if (global == null) {
             return null;
         }
         return global.getComponentActivity(component);
    }

    public static class Builder {
        private AppList.Builder<AppActivity,AppActivity.Builder> mApps = new AppList.Builder();

        public Builder() {
        }

        public ActivityReport build() {
            final ActivityReport result = new ActivityReport();
            result.mApps = mApps.build();
            return result;
        }

        public void addActivity(Component component, Collection<ComponentActivity> activities) {
            for (final ComponentActivity activity: activities) {
                addActivity(component, activity);
            }
        }

        public void addActivity(Component component, ComponentActivity activity) {
            AppActivity.Builder app = mApps.get(activity.attribution);
            if (app == null) {
                app = new AppActivity.Builder();
                app.setAttribution(activity.attribution);
                mApps.put(activity.attribution, app);
            }
            app.addComponentActivity(component, activity);
        }
    }
}
+80 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source 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 com.android.powermodel;

import java.util.HashMap;

import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

public class AppActivity extends AppInfo {

    private ImmutableMap<Component, ComponentActivity> mComponents;
    // TODO: power rails
    // private ImmutableMap<Component, PowerRailActivity> mRails;

    private AppActivity() {
    }

    /**
     * Returns the {@link ComponentActivity} for the {@link Component} provided,
     * or null if this AppActivity does not have that component.
     * @more
     * If there is no ComponentActivity for a particular Component, then
     * there was no usage associated with that app for the app in question.
     */
    public ComponentActivity getComponentActivity(Component component) {
        return mComponents.get(component);
    }

    public ImmutableSet<Component> getComponents() {
        return mComponents.keySet();
    }

    public ImmutableMap<Component,ComponentActivity> getComponentActivities() {
        return mComponents;
    }

    // TODO: power rails
    // public ComponentActivity getPowerRail(Component component) {
    //     return mComponents.get(component);
    // }
    //
    // public Set<Component> getPowerRails() {
    //     return mComponents.keySet();
    // }

    public static class Builder extends AppInfo.Builder<AppActivity> {
        private HashMap<Component, ComponentActivity> mComponents = new HashMap();
        // TODO power rails.
        
        public Builder() {
        }

        public AppActivity build() {
            final AppActivity result = new AppActivity();
            init(result);
            result.mComponents = ImmutableMap.copyOf(mComponents);
            return result;
        }

        public void addComponentActivity(Component component, ComponentActivity activity) {
            mComponents.put(component, activity);
        }
    }
}
+56 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source 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 com.android.powermodel;

class AppInfo {
    private AttributionKey mAttribution;

    protected AppInfo() {
    }

    public boolean hasPackage(String pkg) {
        return mAttribution.hasPackage(pkg);
    }

    public AttributionKey getAttribution() {
        return mAttribution;
    }

    abstract static class Builder<APP extends AppInfo> {
        private AttributionKey mAttribution;

        public Builder() {
        }

        public abstract APP build();

        protected void init(AppInfo app) {
            if (mAttribution == null) {
                throw new RuntimeException("setAttribution(AttributionKey attribution) not called");
            }
            app.mAttribution = mAttribution;
        }

        public void setAttribution(AttributionKey attribution) {
            mAttribution = attribution;
        }

        public AttributionKey getAttribution() {
            return mAttribution;
        }
    }
}
+91 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source 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 com.android.powermodel;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;

class AppList<APP extends AppInfo> {
    private ImmutableList<APP> mAllApps;
    private ImmutableList<APP> mRegularApps;
    private ImmutableMap<SpecialApp,APP> mSpecialApps;

    private AppList() {
    }

    public ImmutableList<APP> getAllApps() {
        return mAllApps;
    }

    public ImmutableList<APP> getRegularApps() {
        return mRegularApps;
    }

    public List<APP> findApp(String pkg) {
        List<APP> result = new ArrayList();
        for (APP app: mRegularApps) {
            if (app.hasPackage(pkg)) {
                result.add(app);
            }
        }
        return result;
    }

    public APP findApp(SpecialApp specialApp) {
        return mSpecialApps.get(specialApp);
    }

    public static class Builder<APP extends AppInfo, BUILDER extends AppInfo.Builder<APP>> {
        private final HashMap<AttributionKey,BUILDER> mApps = new HashMap();

        public Builder() {
        }

        public AppList<APP> build() {
            final AppList<APP> result = new AppList();
            final ArrayList<APP> allApps = new ArrayList();
            final ArrayList<APP> regularApps = new ArrayList();
            final HashMap<SpecialApp,APP> specialApps = new HashMap();
            for (AppInfo.Builder<APP> app: mApps.values()) {
                final AttributionKey attribution = app.getAttribution();
                final APP appActivity = app.build();
                allApps.add(appActivity);
                if (attribution.isSpecialApp()) {
                    specialApps.put(attribution.getSpecialApp(), appActivity);
                } else {
                    regularApps.add(appActivity);
                }
            }
            result.mAllApps = ImmutableList.copyOf(allApps);
            result.mRegularApps = ImmutableList.copyOf(regularApps);
            result.mSpecialApps = ImmutableMap.copyOf(specialApps);
            return result;
        }

        public BUILDER get(AttributionKey attribution) {
            return mApps.get(attribution);
        }

        public BUILDER put(AttributionKey attribution, BUILDER app) {
            return mApps.put(attribution, app);
        }
    }
}
+86 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source 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 com.android.powermodel;

import java.util.HashMap;
import java.util.Set;

import com.google.common.collect.ImmutableMap;

public class AppPower extends AppInfo {
    private ImmutableMap<Component, ComponentPower> mComponents;

    private double mAppPowerMah;


    private AppPower() {
    }

    /**
     * Returns the {@link ComponentPower} for the {@link Component} provided,
     * or null if this AppPower does not have that component.
     * @more
     * If the component was in the power profile for this device, there
     * will be a component for it, even if there was no power used
     * by that component. In that case, the
     * {@link ComponentPower.getUsage() ComponentPower.getUsage()}
     * method will return 0.
     */
    public ComponentPower getComponentPower(Component component) {
        return mComponents.get(component);
    }

    public Set<Component> getComponents() {
        return mComponents.keySet();
    }

    /**
     * Return the total power used by this app.
     */
    public double getAppPowerMah() {
        return mAppPowerMah;
    }

    /**
     * Builder class for {@link AppPower}
     */
    public static class Builder extends AppInfo.Builder<AppPower> {
        private HashMap<Component, ComponentPower> mComponents = new HashMap();

        public Builder() {
        }

        public AppPower build() {
            final AppPower result = new AppPower();
            init(result);
            result.mComponents = ImmutableMap.copyOf(mComponents);

            // Add up the components
            double appPowerMah = 0;
            for (final ComponentPower componentPower: mComponents.values()) {
                appPowerMah += componentPower.powerMah;
            }
            result.mAppPowerMah = appPowerMah;

            return result;
        }

        public void addComponentPower(Component component, ComponentPower componentPower) {
            mComponents.put(component, componentPower);
        }
    }
}
Loading