• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.content.pm.VersionedPackage;
21 import android.util.ArrayMap;
22 
23 import com.android.internal.annotations.GuardedBy;
24 import com.android.internal.app.procstats.ProcessStats;
25 
26 import java.io.PrintWriter;
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.function.BiConsumer;
30 import java.util.function.Consumer;
31 import java.util.function.Function;
32 
33 /**
34  * List of packages running in the process, self locked.
35  */
36 final class PackageList {
37     private final ProcessRecord mProcess;
38 
39     private final ArrayMap<String, ProcessStats.ProcessStateHolder> mPkgList = new ArrayMap<>();
40 
PackageList(final ProcessRecord app)41     PackageList(final ProcessRecord app) {
42         mProcess = app;
43     }
44 
put(String key, ProcessStats.ProcessStateHolder value)45     ProcessStats.ProcessStateHolder put(String key, ProcessStats.ProcessStateHolder value) {
46         synchronized (this) {
47             mProcess.getWindowProcessController().addPackage(key);
48             return mPkgList.put(key, value);
49         }
50     }
51 
clear()52     void clear() {
53         synchronized (this) {
54             mPkgList.clear();
55             mProcess.getWindowProcessController().clearPackageList();
56         }
57     }
58 
size()59     int size() {
60         synchronized (this) {
61             return mPkgList.size();
62         }
63     }
64 
containsKey(Object key)65     boolean containsKey(Object key) {
66         synchronized (this) {
67             return mPkgList.containsKey(key);
68         }
69     }
70 
get(String pkgName)71     ProcessStats.ProcessStateHolder get(String pkgName) {
72         synchronized (this) {
73             return mPkgList.get(pkgName);
74         }
75     }
76 
forEachPackage(@onNull Consumer<String> callback)77     void forEachPackage(@NonNull Consumer<String> callback) {
78         synchronized (this) {
79             for (int i = 0, size = mPkgList.size(); i < size; i++) {
80                 callback.accept(mPkgList.keyAt(i));
81             }
82         }
83     }
84 
forEachPackage(@onNull BiConsumer<String, ProcessStats.ProcessStateHolder> callback)85     void forEachPackage(@NonNull BiConsumer<String, ProcessStats.ProcessStateHolder> callback) {
86         synchronized (this) {
87             for (int i = 0, size = mPkgList.size(); i < size; i++) {
88                 callback.accept(mPkgList.keyAt(i), mPkgList.valueAt(i));
89             }
90         }
91     }
92 
93     /**
94      * Search in the package list, invoke the given {@code callback} with each of the package names
95      * in that list; if the callback returns a non-null object, halt the search, return that
96      * object as the return value of this search function.
97      *
98      * @param callback The callback interface to accept the current package name; if it returns
99      *                 a non-null object, the search will be halted and this object will be used
100      *                 as the return value of this search function.
101      */
searchEachPackage(@onNull Function<String, R> callback)102     <R> R searchEachPackage(@NonNull Function<String, R> callback) {
103         synchronized (this) {
104             for (int i = 0, size = mPkgList.size(); i < size; i++) {
105                 R r = callback.apply(mPkgList.keyAt(i));
106                 if (r != null) {
107                     return r;
108                 }
109             }
110         }
111         return null;
112     }
113 
forEachPackageProcessStats(@onNull Consumer<ProcessStats.ProcessStateHolder> callback)114     void forEachPackageProcessStats(@NonNull Consumer<ProcessStats.ProcessStateHolder> callback) {
115         synchronized (this) {
116             for (int i = 0, size = mPkgList.size(); i < size; i++) {
117                 callback.accept(mPkgList.valueAt(i));
118             }
119         }
120     }
121 
122     @GuardedBy("this")
getPackageListLocked()123     ArrayMap<String, ProcessStats.ProcessStateHolder> getPackageListLocked() {
124         return mPkgList;
125     }
126 
getPackageList()127     String[] getPackageList() {
128         synchronized (this) {
129             int size = mPkgList.size();
130             if (size == 0) {
131                 return null;
132             }
133             final String[] list = new String[size];
134             for (int i = 0; i < size; i++) {
135                 list[i] = mPkgList.keyAt(i);
136             }
137             return list;
138         }
139     }
140 
getPackageListWithVersionCode()141     List<VersionedPackage> getPackageListWithVersionCode() {
142         synchronized (this) {
143             int size = mPkgList.size();
144             if (size == 0) {
145                 return null;
146             }
147             List<VersionedPackage> list = new ArrayList<>();
148             for (int i = 0; i < size; i++) {
149                 list.add(new VersionedPackage(mPkgList.keyAt(i), mPkgList.valueAt(i).appVersion));
150             }
151             return list;
152         }
153     }
154 
dump(PrintWriter pw, String prefix)155     void dump(PrintWriter pw, String prefix) {
156         synchronized (this) {
157             pw.print(prefix); pw.print("packageList={");
158             for (int i = 0, size = mPkgList.size(); i < size; i++) {
159                 if (i > 0) pw.print(", ");
160                 pw.print(mPkgList.keyAt(i));
161             }
162             pw.println("}");
163         }
164     }
165 }
166