1 /* 2 * Copyright (C) 2016 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 package com.android.car; 17 18 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO; 19 20 import android.car.builtin.app.ActivityManagerHelper; 21 import android.car.builtin.app.ActivityManagerHelper.ProcessObserverCallback; 22 import android.car.builtin.util.Slogf; 23 import android.content.Context; 24 import android.os.Handler; 25 import android.os.HandlerThread; 26 import android.os.Looper; 27 import android.os.Message; 28 import android.util.ArrayMap; 29 import android.util.ArraySet; 30 import android.util.Log; 31 32 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 33 import com.android.car.internal.util.IndentingPrintWriter; 34 import com.android.internal.annotations.GuardedBy; 35 36 import java.lang.ref.WeakReference; 37 import java.util.Arrays; 38 import java.util.Map; 39 import java.util.Set; 40 41 /** 42 * Service to monitor AMS for new Activity or Service launching. 43 */ 44 public class SystemActivityMonitoringService implements CarServiceBase { 45 private static final int INVALID_STACK_ID = -1; 46 private final Context mContext; 47 private final ProcessObserverCallback mProcessObserver = new ProcessObserver(); 48 49 private final HandlerThread mMonitorHandlerThread = CarServiceUtils.getHandlerThread( 50 getClass().getSimpleName()); 51 private final ActivityMonitorHandler mHandler = new ActivityMonitorHandler( 52 mMonitorHandlerThread.getLooper(), this); 53 54 private final Object mLock = new Object(); 55 56 @GuardedBy("mLock") 57 private final Map<Integer, Set<Integer>> mForegroundUidPids = new ArrayMap<>(); 58 SystemActivityMonitoringService(Context context)59 public SystemActivityMonitoringService(Context context) { 60 mContext = context; 61 } 62 63 @Override init()64 public void init() { 65 // Monitoring both listeners are necessary as there are cases where one listener cannot 66 // monitor activity change. 67 ActivityManagerHelper.registerProcessObserverCallback(mProcessObserver); 68 } 69 70 @Override release()71 public void release() { 72 ActivityManagerHelper.unregisterProcessObserverCallback(mProcessObserver); 73 } 74 75 @Override 76 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) dump(IndentingPrintWriter writer)77 public void dump(IndentingPrintWriter writer) { 78 writer.println("*SystemActivityMonitoringService*"); 79 writer.println(" Top Tasks per display:"); 80 synchronized (mLock) { 81 writer.println(" Foreground uid-pids:"); 82 for (Integer key : mForegroundUidPids.keySet()) { 83 Set<Integer> pids = mForegroundUidPids.get(key); 84 if (pids == null) { 85 continue; 86 } 87 writer.println("uid:" + key + ", pids:" + Arrays.toString(pids.toArray())); 88 } 89 } 90 } 91 isInForeground(int pid, int uid)92 public boolean isInForeground(int pid, int uid) { 93 synchronized (mLock) { 94 Set<Integer> pids = mForegroundUidPids.get(uid); 95 if (pids == null) { 96 return false; 97 } 98 if (pids.contains(pid)) { 99 return true; 100 } 101 } 102 return false; 103 } 104 handleForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities)105 private void handleForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) { 106 synchronized (mLock) { 107 if (foregroundActivities) { 108 Set<Integer> pids = mForegroundUidPids.get(uid); 109 if (pids == null) { 110 pids = new ArraySet<Integer>(); 111 mForegroundUidPids.put(uid, pids); 112 } 113 pids.add(pid); 114 } else { 115 doHandlePidGoneLocked(pid, uid); 116 } 117 } 118 } 119 handleProcessDied(int pid, int uid)120 private void handleProcessDied(int pid, int uid) { 121 synchronized (mLock) { 122 doHandlePidGoneLocked(pid, uid); 123 } 124 } 125 126 @GuardedBy("mLock") doHandlePidGoneLocked(int pid, int uid)127 private void doHandlePidGoneLocked(int pid, int uid) { 128 Set<Integer> pids = mForegroundUidPids.get(uid); 129 if (pids != null) { 130 pids.remove(pid); 131 if (pids.isEmpty()) { 132 mForegroundUidPids.remove(uid); 133 } 134 } 135 } 136 137 private class ProcessObserver extends ProcessObserverCallback { 138 @Override onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities)139 public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) { 140 if (Slogf.isLoggable(CarLog.TAG_AM, Log.INFO)) { 141 Slogf.i(CarLog.TAG_AM, 142 String.format("onForegroundActivitiesChanged uid %d pid %d fg %b", 143 uid, pid, foregroundActivities)); 144 } 145 mHandler.requestForegroundActivitiesChanged(pid, uid, foregroundActivities); 146 } 147 148 @Override onProcessDied(int pid, int uid)149 public void onProcessDied(int pid, int uid) { 150 mHandler.requestProcessDied(pid, uid); 151 } 152 } 153 154 private static final class ActivityMonitorHandler extends Handler { 155 private static final String TAG = ActivityMonitorHandler.class.getSimpleName(); 156 157 private static final int MSG_FOREGROUND_ACTIVITIES_CHANGED = 1; 158 private static final int MSG_PROCESS_DIED = 2; 159 160 private final WeakReference<SystemActivityMonitoringService> mService; 161 ActivityMonitorHandler(Looper looper, SystemActivityMonitoringService service)162 private ActivityMonitorHandler(Looper looper, SystemActivityMonitoringService service) { 163 super(looper); 164 mService = new WeakReference<SystemActivityMonitoringService>(service); 165 } 166 requestForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities)167 private void requestForegroundActivitiesChanged(int pid, int uid, 168 boolean foregroundActivities) { 169 Message msg = obtainMessage(MSG_FOREGROUND_ACTIVITIES_CHANGED, pid, uid, 170 Boolean.valueOf(foregroundActivities)); 171 sendMessage(msg); 172 } 173 requestProcessDied(int pid, int uid)174 private void requestProcessDied(int pid, int uid) { 175 Message msg = obtainMessage(MSG_PROCESS_DIED, pid, uid); 176 sendMessage(msg); 177 } 178 179 @Override handleMessage(Message msg)180 public void handleMessage(Message msg) { 181 SystemActivityMonitoringService service = mService.get(); 182 if (service == null) { 183 Slogf.i(TAG, "handleMessage null service"); 184 return; 185 } 186 switch (msg.what) { 187 case MSG_FOREGROUND_ACTIVITIES_CHANGED: 188 service.handleForegroundActivitiesChanged(msg.arg1, msg.arg2, 189 (Boolean) msg.obj); 190 break; 191 case MSG_PROCESS_DIED: 192 service.handleProcessDied(msg.arg1, msg.arg2); 193 break; 194 } 195 } 196 } 197 } 198