1 /*
2  * Copyright (C) 2019 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.wm;
18 
19 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
20 
21 import android.app.ActivityManager.ProcessState;
22 import android.util.SparseIntArray;
23 
24 import java.io.PrintWriter;
25 
26 /**
27  * This is a partial mirror of {@link @com.android.server.am.ActiveUids}. It is already thread
28  * safe so the heavy service lock is not needed when updating state from activity manager (oom
29  * adjustment) or getting state from window manager (background start check).
30  */
31 class MirrorActiveUids {
32     /** Uid -> process state. */
33     private final SparseIntArray mUidStates = new SparseIntArray();
34 
35     /** Uid -> number of non-app visible windows belong to the uid. */
36     private final SparseIntArray mNumNonAppVisibleWindowMap = new SparseIntArray();
37 
onUidActive(int uid, int procState)38     synchronized void onUidActive(int uid, int procState) {
39         mUidStates.put(uid, procState);
40     }
41 
onUidInactive(int uid)42     synchronized void onUidInactive(int uid) {
43         mUidStates.delete(uid);
44     }
45 
onUidProcStateChanged(int uid, int procState)46     synchronized void onUidProcStateChanged(int uid, int procState) {
47         final int index = mUidStates.indexOfKey(uid);
48         if (index >= 0) {
49             mUidStates.setValueAt(index, procState);
50         }
51     }
52 
getUidState(int uid)53     synchronized @ProcessState int getUidState(int uid) {
54         return mUidStates.get(uid, PROCESS_STATE_NONEXISTENT);
55     }
56 
57     /** Called when the surface of non-application (exclude toast) window is shown or hidden. */
onNonAppSurfaceVisibilityChanged(int uid, boolean visible)58     synchronized void onNonAppSurfaceVisibilityChanged(int uid, boolean visible) {
59         final int index = mNumNonAppVisibleWindowMap.indexOfKey(uid);
60         if (index >= 0) {
61             final int num = mNumNonAppVisibleWindowMap.valueAt(index) + (visible ? 1 : -1);
62             if (num > 0) {
63                 mNumNonAppVisibleWindowMap.setValueAt(index, num);
64             } else {
65                 mNumNonAppVisibleWindowMap.removeAt(index);
66             }
67         } else if (visible) {
68             mNumNonAppVisibleWindowMap.append(uid, 1);
69         }
70     }
71 
72     /**
73      * Returns {@code true} if the uid has any non-application (exclude toast) window currently
74      * visible to the user. The application window visibility of a uid can be found from
75      * {@link VisibleActivityProcessTracker}.
76      */
hasNonAppVisibleWindow(int uid)77     synchronized boolean hasNonAppVisibleWindow(int uid) {
78         return mNumNonAppVisibleWindowMap.get(uid) > 0;
79     }
80 
dump(PrintWriter pw, String prefix)81     synchronized void dump(PrintWriter pw, String prefix) {
82         pw.print(prefix + "NumNonAppVisibleWindowUidMap:[");
83         for (int i = mNumNonAppVisibleWindowMap.size() - 1; i >= 0; i--) {
84             pw.print(" " + mNumNonAppVisibleWindowMap.keyAt(i) + ":"
85                     + mNumNonAppVisibleWindowMap.valueAt(i));
86         }
87         pw.println("]");
88     }
89 }
90