1 /* 2 * Copyright (C) 2022 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.am; 18 19 import android.annotation.NonNull; 20 import android.annotation.UserIdInt; 21 import android.app.ActivityManager; 22 import android.content.Context; 23 import android.os.PowerExemptionManager; 24 import android.os.PowerExemptionManager.ReasonCode; 25 import android.os.SystemClock; 26 import android.os.UserHandle; 27 import android.provider.DeviceConfig; 28 import android.util.ArrayMap; 29 import android.util.ArraySet; 30 import android.util.SparseArray; 31 32 import com.android.internal.annotations.GuardedBy; 33 import com.android.internal.annotations.VisibleForTesting; 34 import com.android.server.am.BaseAppStateEvents.MaxTrackingDurationConfig; 35 import com.android.server.am.BaseAppStateEventsTracker.BaseAppStateEventsPolicy; 36 37 import java.io.PrintWriter; 38 import java.lang.reflect.Constructor; 39 import java.util.LinkedList; 40 41 /** 42 * Base class to track certain state event of apps. 43 */ 44 abstract class BaseAppStateEventsTracker 45 <T extends BaseAppStateEventsPolicy, U extends BaseAppStateEvents> 46 extends BaseAppStateTracker<T> implements BaseAppStateEvents.Factory<U> { 47 static final boolean DEBUG_BASE_APP_STATE_EVENTS_TRACKER = false; 48 49 @GuardedBy("mLock") 50 final UidProcessMap<U> mPkgEvents = new UidProcessMap<>(); 51 52 @GuardedBy("mLock") 53 final ArraySet<Integer> mTopUids = new ArraySet<>(); 54 BaseAppStateEventsTracker(Context context, AppRestrictionController controller, Constructor<? extends Injector<T>> injector, Object outerContext)55 BaseAppStateEventsTracker(Context context, AppRestrictionController controller, 56 Constructor<? extends Injector<T>> injector, Object outerContext) { 57 super(context, controller, injector, outerContext); 58 } 59 60 @VisibleForTesting reset()61 void reset() { 62 synchronized (mLock) { 63 mPkgEvents.clear(); 64 mTopUids.clear(); 65 } 66 } 67 68 @GuardedBy("mLock") getUidEventsLocked(int uid)69 U getUidEventsLocked(int uid) { 70 U events = null; 71 final ArrayMap<String, U> map = mPkgEvents.getMap().get(uid); 72 if (map == null) { 73 return null; 74 } 75 for (int i = map.size() - 1; i >= 0; i--) { 76 final U event = map.valueAt(i); 77 if (event != null) { 78 if (events == null) { 79 events = createAppStateEvents(uid, event.mPackageName); 80 } 81 events.add(event); 82 } 83 } 84 return events; 85 } 86 trim(long earliest)87 void trim(long earliest) { 88 synchronized (mLock) { 89 trimLocked(earliest); 90 } 91 } 92 93 @GuardedBy("mLock") trimLocked(long earliest)94 void trimLocked(long earliest) { 95 final SparseArray<ArrayMap<String, U>> map = mPkgEvents.getMap(); 96 for (int i = map.size() - 1; i >= 0; i--) { 97 final ArrayMap<String, U> val = map.valueAt(i); 98 for (int j = val.size() - 1; j >= 0; j--) { 99 final U v = val.valueAt(j); 100 v.trim(earliest); 101 if (v.isEmpty()) { 102 val.removeAt(j); 103 } 104 } 105 if (val.size() == 0) { 106 map.removeAt(i); 107 } 108 } 109 } 110 isUidOnTop(int uid)111 boolean isUidOnTop(int uid) { 112 synchronized (mLock) { 113 return mTopUids.contains(uid); 114 } 115 } 116 117 @GuardedBy("mLock") onUntrackingUidLocked(int uid)118 void onUntrackingUidLocked(int uid) { 119 } 120 121 @Override onUidProcStateChanged(final int uid, final int procState)122 void onUidProcStateChanged(final int uid, final int procState) { 123 synchronized (mLock) { 124 if (mPkgEvents.getMap().indexOfKey(uid) < 0) { 125 // If we're not tracking its events, ignore its UID state changes. 126 return; 127 } 128 onUidProcStateChangedUncheckedLocked(uid, procState); 129 } 130 } 131 132 @GuardedBy("mLock") onUidProcStateChangedUncheckedLocked(final int uid, final int procState)133 void onUidProcStateChangedUncheckedLocked(final int uid, final int procState) { 134 if (procState < ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { 135 mTopUids.add(uid); 136 } else { 137 mTopUids.remove(uid); 138 } 139 } 140 141 @Override onUidGone(final int uid)142 void onUidGone(final int uid) { 143 synchronized (mLock) { 144 mTopUids.remove(uid); 145 } 146 } 147 148 @Override onUidRemoved(final int uid)149 void onUidRemoved(final int uid) { 150 synchronized (mLock) { 151 mPkgEvents.getMap().remove(uid); 152 onUntrackingUidLocked(uid); 153 } 154 } 155 156 @Override onUserRemoved(final @UserIdInt int userId)157 void onUserRemoved(final @UserIdInt int userId) { 158 synchronized (mLock) { 159 final SparseArray<ArrayMap<String, U>> map = mPkgEvents.getMap(); 160 for (int i = map.size() - 1; i >= 0; i--) { 161 final int uid = map.keyAt(i); 162 if (UserHandle.getUserId(uid) == userId) { 163 map.removeAt(i); 164 onUntrackingUidLocked(uid); 165 } 166 } 167 } 168 } 169 170 @Override dump(PrintWriter pw, String prefix)171 void dump(PrintWriter pw, String prefix) { 172 final T policy = mInjector.getPolicy(); 173 synchronized (mLock) { 174 final long now = SystemClock.elapsedRealtime(); 175 final SparseArray<ArrayMap<String, U>> map = mPkgEvents.getMap(); 176 for (int i = map.size() - 1; i >= 0; i--) { 177 final int uid = map.keyAt(i); 178 final ArrayMap<String, U> val = map.valueAt(i); 179 for (int j = val.size() - 1; j >= 0; j--) { 180 final String packageName = val.keyAt(j); 181 final U events = val.valueAt(j); 182 dumpEventHeaderLocked(pw, prefix, packageName, uid, events, policy); 183 dumpEventLocked(pw, prefix, events, now); 184 } 185 } 186 } 187 dumpOthers(pw, prefix); 188 policy.dump(pw, prefix); 189 } 190 dumpOthers(PrintWriter pw, String prefix)191 void dumpOthers(PrintWriter pw, String prefix) { 192 } 193 194 @GuardedBy("mLock") dumpEventHeaderLocked(PrintWriter pw, String prefix, String packageName, int uid, U events, T policy)195 void dumpEventHeaderLocked(PrintWriter pw, String prefix, String packageName, int uid, U events, 196 T policy) { 197 pw.print(prefix); 198 pw.print("* "); 199 pw.print(packageName); 200 pw.print('/'); 201 pw.print(UserHandle.formatUid(uid)); 202 pw.print(" exemption="); 203 pw.println(policy.getExemptionReasonString(packageName, uid, events.mExemptReason)); 204 } 205 206 @GuardedBy("mLock") dumpEventLocked(PrintWriter pw, String prefix, U events, long now)207 void dumpEventLocked(PrintWriter pw, String prefix, U events, long now) { 208 events.dump(pw, " " + prefix, now); 209 } 210 211 abstract static class BaseAppStateEventsPolicy<V extends BaseAppStateEventsTracker> 212 extends BaseAppStatePolicy<V> implements MaxTrackingDurationConfig { 213 /** 214 * The key to the maximum duration we'd keep tracking, events earlier than that 215 * will be discarded. 216 */ 217 final @NonNull String mKeyMaxTrackingDuration; 218 219 /** 220 * The default to the {@link #mMaxTrackingDuration}. 221 */ 222 final long mDefaultMaxTrackingDuration; 223 224 /** 225 * The maximum duration we'd keep tracking, events earlier than that will be discarded. 226 */ 227 volatile long mMaxTrackingDuration; 228 BaseAppStateEventsPolicy(@onNull Injector<?> injector, @NonNull V tracker, @NonNull String keyTrackerEnabled, boolean defaultTrackerEnabled, @NonNull String keyMaxTrackingDuration, long defaultMaxTrackingDuration)229 BaseAppStateEventsPolicy(@NonNull Injector<?> injector, @NonNull V tracker, 230 @NonNull String keyTrackerEnabled, boolean defaultTrackerEnabled, 231 @NonNull String keyMaxTrackingDuration, long defaultMaxTrackingDuration) { 232 super(injector, tracker, keyTrackerEnabled, defaultTrackerEnabled); 233 mKeyMaxTrackingDuration = keyMaxTrackingDuration; 234 mDefaultMaxTrackingDuration = defaultMaxTrackingDuration; 235 } 236 237 @Override onPropertiesChanged(String name)238 public void onPropertiesChanged(String name) { 239 if (mKeyMaxTrackingDuration.equals(name)) { 240 updateMaxTrackingDuration(); 241 } else { 242 super.onPropertiesChanged(name); 243 } 244 } 245 246 @Override onSystemReady()247 public void onSystemReady() { 248 super.onSystemReady(); 249 updateMaxTrackingDuration(); 250 } 251 252 /** 253 * Called when the maximum duration we'd keep tracking has been changed. 254 */ onMaxTrackingDurationChanged(long maxDuration)255 public abstract void onMaxTrackingDurationChanged(long maxDuration); 256 updateMaxTrackingDuration()257 void updateMaxTrackingDuration() { 258 long max = DeviceConfig.getLong( 259 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 260 mKeyMaxTrackingDuration, mDefaultMaxTrackingDuration); 261 if (max != mMaxTrackingDuration) { 262 mMaxTrackingDuration = max; 263 onMaxTrackingDurationChanged(max); 264 } 265 } 266 267 @Override getMaxTrackingDuration()268 public long getMaxTrackingDuration() { 269 return mMaxTrackingDuration; 270 } 271 getExemptionReasonString(String packageName, int uid, @ReasonCode int reason)272 String getExemptionReasonString(String packageName, int uid, @ReasonCode int reason) { 273 return PowerExemptionManager.reasonCodeToString(reason); 274 } 275 276 @Override dump(PrintWriter pw, String prefix)277 void dump(PrintWriter pw, String prefix) { 278 super.dump(pw, prefix); 279 if (isEnabled()) { 280 pw.print(prefix); 281 pw.print(mKeyMaxTrackingDuration); 282 pw.print('='); 283 pw.println(mMaxTrackingDuration); 284 } 285 } 286 } 287 288 /** 289 * Simple event table, with only one track of events. 290 */ 291 static class SimplePackageEvents extends BaseAppStateTimeEvents { 292 static final int DEFAULT_INDEX = 0; 293 SimplePackageEvents(int uid, String packageName, MaxTrackingDurationConfig maxTrackingDurationConfig)294 SimplePackageEvents(int uid, String packageName, 295 MaxTrackingDurationConfig maxTrackingDurationConfig) { 296 super(uid, packageName, 1, TAG, maxTrackingDurationConfig); 297 mEvents[DEFAULT_INDEX] = new LinkedList<Long>(); 298 } 299 getTotalEvents(long now)300 long getTotalEvents(long now) { 301 return getTotalEvents(now, DEFAULT_INDEX); 302 } 303 getTotalEventsSince(long since, long now)304 long getTotalEventsSince(long since, long now) { 305 return getTotalEventsSince(since, now, DEFAULT_INDEX); 306 } 307 308 @Override formatEventTypeLabel(int index)309 String formatEventTypeLabel(int index) { 310 return ""; 311 } 312 } 313 } 314