1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.tare; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 22 import java.util.ArrayList; 23 import java.util.Collections; 24 import java.util.Comparator; 25 import java.util.List; 26 27 /** 28 * Interface for the system server to deal with the resource economy subsystem. 29 * 30 * @hide 31 */ 32 public interface EconomyManagerInternal { 33 /** 34 * Used to indicate a future action an app is expected to take. 35 */ 36 final class AnticipatedAction { 37 public final int actionId; 38 public final int numInstantaneousCalls; 39 public final long ongoingDurationMs; 40 private final int mHashCode; 41 42 /** 43 * @param actionId The expected action 44 * @param numInstantaneousCalls How many instantaneous times the action will be performed 45 * @param ongoingDurationMs An estimate of how long the ongoing event will go on for 46 */ AnticipatedAction(@conomicPolicy.AppAction int actionId, int numInstantaneousCalls, long ongoingDurationMs)47 public AnticipatedAction(@EconomicPolicy.AppAction int actionId, 48 int numInstantaneousCalls, long ongoingDurationMs) { 49 this.actionId = actionId; 50 this.numInstantaneousCalls = numInstantaneousCalls; 51 this.ongoingDurationMs = ongoingDurationMs; 52 53 int hash = 0; 54 hash = 31 * hash + actionId; 55 hash = 31 * hash + numInstantaneousCalls; 56 hash = 31 * hash + (int) (ongoingDurationMs ^ (ongoingDurationMs >>> 32)); 57 mHashCode = hash; 58 } 59 60 @Override equals(Object o)61 public boolean equals(Object o) { 62 if (this == o) return true; 63 if (o == null || getClass() != o.getClass()) return false; 64 AnticipatedAction that = (AnticipatedAction) o; 65 return actionId == that.actionId 66 && numInstantaneousCalls == that.numInstantaneousCalls 67 && ongoingDurationMs == that.ongoingDurationMs; 68 } 69 70 @Override hashCode()71 public int hashCode() { 72 return mHashCode; 73 } 74 } 75 76 /** 77 * A collection of {@link AnticipatedAction AnticipatedActions} that will be performed together. 78 */ 79 final class ActionBill { 80 private static final Comparator<AnticipatedAction> 81 sAnticipatedActionComparator = Comparator.comparingInt(aa -> aa.actionId); 82 83 private final List<AnticipatedAction> mAnticipatedActions; 84 private final int mHashCode; 85 ActionBill(@onNull List<AnticipatedAction> anticipatedActions)86 public ActionBill(@NonNull List<AnticipatedAction> anticipatedActions) { 87 List<AnticipatedAction> actions = new ArrayList<>(anticipatedActions); 88 actions.sort(sAnticipatedActionComparator); 89 mAnticipatedActions = Collections.unmodifiableList(actions); 90 91 int hash = 0; 92 for (int i = 0; i < mAnticipatedActions.size(); ++i) { 93 hash = 31 * hash + mAnticipatedActions.get(i).hashCode(); 94 } 95 mHashCode = hash; 96 } 97 getAnticipatedActions()98 List<AnticipatedAction> getAnticipatedActions() { 99 return mAnticipatedActions; 100 } 101 102 @Override equals(Object o)103 public boolean equals(Object o) { 104 if (this == o) return true; 105 if (o == null || getClass() != o.getClass()) return false; 106 ActionBill that = (ActionBill) o; 107 return mAnticipatedActions.equals(that.mAnticipatedActions); 108 } 109 110 @Override hashCode()111 public int hashCode() { 112 return mHashCode; 113 } 114 } 115 116 /** Listener for when an app's ability to afford a bill changes. */ 117 interface AffordabilityChangeListener { onAffordabilityChanged(int userId, @NonNull String pkgName, @NonNull ActionBill bill, boolean canAfford)118 void onAffordabilityChanged(int userId, @NonNull String pkgName, @NonNull ActionBill bill, 119 boolean canAfford); 120 } 121 122 /** Listener for various TARE state changes. */ 123 interface TareStateChangeListener { onTareEnabledStateChanged(boolean isTareEnabled)124 void onTareEnabledStateChanged(boolean isTareEnabled); 125 } 126 127 /** 128 * Return {@code true} if the app is able to pay for the anticipated actions. 129 */ canPayFor(int userId, @NonNull String pkgName, @NonNull ActionBill bill)130 boolean canPayFor(int userId, @NonNull String pkgName, @NonNull ActionBill bill); 131 132 /** 133 * Returns the maximum duration (in milliseconds) that the specified app can afford the bill, 134 * based on current prices. 135 */ getMaxDurationMs(int userId, @NonNull String pkgName, @NonNull ActionBill bill)136 long getMaxDurationMs(int userId, @NonNull String pkgName, @NonNull ActionBill bill); 137 138 /** Returns true if TARE is enabled. */ isEnabled()139 boolean isEnabled(); 140 141 /** 142 * Register an {@link AffordabilityChangeListener} to track when an app's ability to afford the 143 * indicated bill changes. 144 */ registerAffordabilityChangeListener(int userId, @NonNull String pkgName, @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill)145 void registerAffordabilityChangeListener(int userId, @NonNull String pkgName, 146 @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill); 147 148 /** 149 * Unregister a {@link AffordabilityChangeListener} from being notified of any changes to an 150 * app's ability to afford the specified bill. 151 */ unregisterAffordabilityChangeListener(int userId, @NonNull String pkgName, @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill)152 void unregisterAffordabilityChangeListener(int userId, @NonNull String pkgName, 153 @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill); 154 155 /** 156 * Register a {@link TareStateChangeListener} to track when TARE's state changes. 157 */ registerTareStateChangeListener(@onNull TareStateChangeListener listener)158 void registerTareStateChangeListener(@NonNull TareStateChangeListener listener); 159 160 /** 161 * Unregister a {@link TareStateChangeListener} from being notified when TARE's state changes. 162 */ unregisterTareStateChangeListener(@onNull TareStateChangeListener listener)163 void unregisterTareStateChangeListener(@NonNull TareStateChangeListener listener); 164 165 /** 166 * Note that an instantaneous event has occurred. The event must be specified in one of the 167 * EconomicPolicies. 168 * 169 * @param tag An optional tag that can be used to differentiate the same event for the same app. 170 */ noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId, @Nullable String tag)171 void noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId, 172 @Nullable String tag); 173 174 /** 175 * Note that a long-running event is starting. The event must be specified in one of the 176 * EconomicPolicies. You must always call 177 * {@link #noteOngoingEventStopped(int, String, int, String)} to end the event. Ongoing 178 * events will be separated and grouped by event-tag combinations. There must be an equal 179 * number of start() and stop() calls for the same event-tag combination in order for the 180 * tracking to finally stop (ie. ongoing events are ref-counted). 181 * 182 * @param tag An optional tag that can be used to differentiate the same event for the same app. 183 */ noteOngoingEventStarted(int userId, @NonNull String pkgName, int eventId, @Nullable String tag)184 void noteOngoingEventStarted(int userId, @NonNull String pkgName, int eventId, 185 @Nullable String tag); 186 187 /** 188 * Note that a long-running event has stopped. The event must be specified in one of the 189 * EconomicPolicies. Ongoing events are separated and grouped by event-tag combinations. 190 * There must be an equal number of start() and stop() calls for the same event-tag combination 191 * in order for the tracking to finally stop (ie. ongoing events are ref-counted). 192 * 193 * @param tag An optional tag that can be used to differentiate the same event for the same app. 194 */ noteOngoingEventStopped(int userId, @NonNull String pkgName, int eventId, @Nullable String tag)195 void noteOngoingEventStopped(int userId, @NonNull String pkgName, int eventId, 196 @Nullable String tag); 197 } 198