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