blob: da69986cd59f84813d8cc8c2d877f7e15ae90467 [file] [log] [blame]
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001/*
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
17package com.android.server.om;
18
19import static android.app.AppGlobals.getPackageManager;
20import static android.content.Intent.ACTION_PACKAGE_ADDED;
21import static android.content.Intent.ACTION_PACKAGE_CHANGED;
22import static android.content.Intent.ACTION_PACKAGE_REMOVED;
Adam Lesinskiada8deb2017-05-12 13:50:42 -070023import static android.content.Intent.ACTION_USER_ADDED;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010024import static android.content.Intent.ACTION_USER_REMOVED;
25import static android.content.pm.PackageManager.SIGNATURE_MATCH;
Mårten Kongstadacfcdc72018-12-03 14:59:51 +010026import static android.os.Trace.TRACE_TAG_RRO;
27import static android.os.Trace.traceBegin;
28import static android.os.Trace.traceEnd;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010029
30import android.annotation.NonNull;
31import android.annotation.Nullable;
32import android.app.ActivityManager;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010033import android.app.IActivityManager;
34import android.content.BroadcastReceiver;
35import android.content.Context;
36import android.content.Intent;
37import android.content.IntentFilter;
38import android.content.om.IOverlayManager;
39import android.content.om.OverlayInfo;
40import android.content.pm.IPackageManager;
41import android.content.pm.PackageInfo;
42import android.content.pm.PackageManagerInternal;
43import android.content.pm.UserInfo;
44import android.net.Uri;
45import android.os.Binder;
46import android.os.Environment;
47import android.os.IBinder;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010048import android.os.RemoteException;
49import android.os.ResultReceiver;
50import android.os.ShellCallback;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080051import android.os.SystemProperties;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010052import android.os.UserHandle;
Adam Lesinskiada8deb2017-05-12 13:50:42 -070053import android.os.UserManager;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080054import android.text.TextUtils;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010055import android.util.ArrayMap;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080056import android.util.ArraySet;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010057import android.util.AtomicFile;
58import android.util.Slog;
59import android.util.SparseArray;
60
61import com.android.server.FgThread;
62import com.android.server.IoThread;
63import com.android.server.LocalServices;
64import com.android.server.SystemService;
65import com.android.server.pm.Installer;
66import com.android.server.pm.UserManagerService;
67
Adam Lesinski7b031812018-02-22 13:32:53 -080068import libcore.util.EmptyArray;
69
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010070import org.xmlpull.v1.XmlPullParserException;
71
72import java.io.File;
73import java.io.FileDescriptor;
74import java.io.FileInputStream;
75import java.io.FileOutputStream;
76import java.io.IOException;
77import java.io.PrintWriter;
78import java.util.ArrayList;
Adam Lesinskid11c5512017-04-11 12:01:10 -070079import java.util.Arrays;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010080import java.util.Collections;
81import java.util.HashMap;
82import java.util.List;
83import java.util.Map;
84import java.util.concurrent.atomic.AtomicBoolean;
85
86/**
87 * Service to manage asset overlays.
88 *
89 * <p>Asset overlays are additional resources that come from apks loaded
90 * alongside the system and app apks. This service, the OverlayManagerService
91 * (OMS), tracks which installed overlays to use and provides methods to change
92 * this. Changes propagate to running applications as part of the Activity
93 * lifecycle. This allows Activities to reread their resources at a well
94 * defined point.</p>
95 *
96 * <p>By itself, the OMS will not change what overlays should be active.
97 * Instead, it is only responsible for making sure that overlays *can* be used
98 * from a technical and security point of view and to activate overlays in
99 * response to external requests. The responsibility to toggle overlays on and
100 * off lies within components that implement different use-cases such as themes
101 * or dynamic customization.</p>
102 *
103 * <p>The OMS receives input from three sources:</p>
104 *
105 * <ul>
106 * <li>Callbacks from the SystemService class, specifically when the
107 * Android framework is booting and when the end user switches Android
108 * users.</li>
109 *
110 * <li>Intents from the PackageManagerService (PMS). Overlays are regular
111 * apks, and whenever a package is installed (or removed, or has a
112 * component enabled or disabled), the PMS broadcasts this as an intent.
113 * When the OMS receives one of these intents, it updates its internal
114 * representation of the available overlays and, if there was a visible
115 * change, triggers an asset refresh in the affected apps.</li>
116 *
117 * <li>External requests via the {@link IOverlayManager AIDL interface}.
118 * The interface allows clients to read information about the currently
119 * available overlays, change whether an overlay should be used or not, and
120 * change the relative order in which overlay packages are loaded.
121 * Read-access is granted if the request targets the same Android user as
122 * the caller runs as, or if the caller holds the
123 * INTERACT_ACROSS_USERS_FULL permission. Write-access is granted if the
124 * caller is granted read-access and additionaly holds the
125 * CHANGE_OVERLAY_PACKAGES permission.</li>
126 * </ul>
127 *
128 * <p>The AIDL interface works with String package names, int user IDs, and
129 * {@link OverlayInfo} objects. OverlayInfo instances are used to track a
130 * specific pair of target and overlay packages and include information such as
131 * the current state of the overlay. OverlayInfo objects are immutable.</p>
132 *
133 * <p>Internally, OverlayInfo objects are maintained by the
134 * OverlayManagerSettings class. The OMS and its helper classes are notified of
135 * changes to the settings by the OverlayManagerSettings.ChangeListener
136 * callback interface. The file /data/system/overlays.xml is used to persist
137 * the settings.</p>
138 *
139 * <p>Creation and deletion of idmap files are handled by the IdmapManager
140 * class.</p>
141 *
142 * <p>The following is an overview of OMS and its related classes. Note how box
143 * (2) does the heavy lifting, box (1) interacts with the Android framework,
144 * and box (3) replaces box (1) during unit testing.</p>
145 *
146 * <pre>
147 * Android framework
148 * | ^
149 * . . . | . . . . | . . . .
150 * . | | .
151 * . AIDL, broadcasts .
152 * . intents | .
153 * . | | . . . . . . . . . . . .
154 * . v | . .
155 * . OverlayManagerService . OverlayManagerTests .
156 * . \ . / .
157 * . (1) \ . / (3) .
158 * . . . . . . . . . . \ . . . / . . . . . . . . .
159 * . \ / .
160 * . (2) \ / .
161 * . OverlayManagerServiceImpl .
162 * . | | .
163 * . | | .
164 * . OverlayManagerSettings IdmapManager .
165 * . .
166 * . . . . . . . . . . . . . . . . . . . . . .
167 * </pre>
168 *
Mårten Kongstad1370c052018-05-03 10:48:35 +0200169 * <p>To test the OMS, execute:
170 * <code>
171 * atest FrameworksServicesTests:com.android.server.om # internal tests
172 * atest OverlayDeviceTests OverlayHostTests # public API tests
173 * </code>
174 * </p>
175 *
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100176 * <p>Finally, here is a list of keywords used in the OMS context.</p>
177 *
178 * <ul>
179 * <li><b>target [package]</b> -- A regular apk that may have its resource
180 * pool extended by zero or more overlay packages.</li>
181 *
182 * <li><b>overlay [package]</b> -- An apk that provides additional
183 * resources to another apk.</li>
184 *
185 * <li><b>OMS</b> -- The OverlayManagerService, i.e. this class.</li>
186 *
187 * <li><b>approved</b> -- An overlay is approved if the OMS has verified
188 * that it can be used technically speaking (its target package is
189 * installed, at least one resource name in both packages match, the
190 * idmap was created, etc) and that it is secure to do so. External
191 * clients can not change this state.</li>
192 *
193 * <li><b>not approved</b> -- The opposite of approved.</li>
194 *
195 * <li><b>enabled</b> -- An overlay currently in active use and thus part
196 * of resource lookups. This requires the overlay to be approved. Only
197 * external clients can change this state.</li>
198 *
199 * <li><b>disabled</b> -- The opposite of enabled.</li>
200 *
201 * <li><b>idmap</b> -- A mapping of resource IDs between target and overlay
202 * used during resource lookup. Also the name of the binary that creates
203 * the mapping.</li>
204 * </ul>
205 */
206public final class OverlayManagerService extends SystemService {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100207 static final String TAG = "OverlayManager";
208
209 static final boolean DEBUG = false;
210
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800211 /**
212 * The system property that specifies the default overlays to apply.
213 * This is a semicolon separated list of package names.
214 *
215 * Ex: com.android.vendor.overlay_one;com.android.vendor.overlay_two
216 */
217 private static final String DEFAULT_OVERLAYS_PROP = "ro.boot.vendor.overlay.theme";
218
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100219 private final Object mLock = new Object();
220
221 private final AtomicFile mSettingsFile;
222
223 private final PackageManagerHelper mPackageManager;
224
225 private final UserManagerService mUserManager;
226
227 private final OverlayManagerSettings mSettings;
228
229 private final OverlayManagerServiceImpl mImpl;
230
231 private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
232
233 public OverlayManagerService(@NonNull final Context context,
234 @NonNull final Installer installer) {
235 super(context);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100236 try {
237 traceBegin(TRACE_TAG_RRO, "OMS#OverlayManagerService");
238 mSettingsFile = new AtomicFile(
239 new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
240 mPackageManager = new PackageManagerHelper();
241 mUserManager = UserManagerService.getInstance();
Winsone0818bf2019-03-01 12:10:09 -0800242 IdmapManager im = new IdmapManager(installer, mPackageManager);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100243 mSettings = new OverlayManagerSettings();
244 mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
245 getDefaultOverlayPackages(), new OverlayChangeListener());
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100246
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100247 final IntentFilter packageFilter = new IntentFilter();
248 packageFilter.addAction(ACTION_PACKAGE_ADDED);
249 packageFilter.addAction(ACTION_PACKAGE_CHANGED);
250 packageFilter.addAction(ACTION_PACKAGE_REMOVED);
251 packageFilter.addDataScheme("package");
252 getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
253 packageFilter, null, null);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100254
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100255 final IntentFilter userFilter = new IntentFilter();
256 userFilter.addAction(ACTION_USER_ADDED);
257 userFilter.addAction(ACTION_USER_REMOVED);
258 getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
259 userFilter, null, null);
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700260
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100261 restoreSettings();
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100262
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100263 initIfNeeded();
264 onSwitchUser(UserHandle.USER_SYSTEM);
Mårten Kongstadcd78e0f2018-05-23 10:41:35 +0200265
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100266 publishBinderService(Context.OVERLAY_SERVICE, mService);
267 publishLocalService(OverlayManagerService.class, this);
268 } finally {
269 traceEnd(TRACE_TAG_RRO);
270 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100271 }
272
273 @Override
274 public void onStart() {
275 // Intentionally left empty.
276 }
277
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700278 private void initIfNeeded() {
279 final UserManager um = getContext().getSystemService(UserManager.class);
280 final List<UserInfo> users = um.getUsers(true /*excludeDying*/);
281 synchronized (mLock) {
282 final int userCount = users.size();
283 for (int i = 0; i < userCount; i++) {
284 final UserInfo userInfo = users.get(i);
285 if (!userInfo.supportsSwitchTo() && userInfo.id != UserHandle.USER_SYSTEM) {
286 // Initialize any users that can't be switched to, as there state would
287 // never be setup in onSwitchUser(). We will switch to the system user right
288 // after this, and its state will be setup there.
289 final List<String> targets = mImpl.updateOverlaysForUser(users.get(i).id);
290 updateOverlayPaths(users.get(i).id, targets);
291 }
292 }
293 }
294 }
295
Fyodor Kupolov94ab1a62017-03-06 14:28:20 -0800296 @Override
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100297 public void onSwitchUser(final int newUserId) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100298 try {
299 traceBegin(TRACE_TAG_RRO, "OMS#onSwitchUser " + newUserId);
300 // ensure overlays in the settings are up-to-date, and propagate
301 // any asset changes to the rest of the system
302 synchronized (mLock) {
303 final List<String> targets = mImpl.updateOverlaysForUser(newUserId);
304 updateAssets(newUserId, targets);
305 }
306 schedulePersistSettings();
307 } finally {
308 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100309 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100310 }
311
Adam Lesinski7b031812018-02-22 13:32:53 -0800312 private static String[] getDefaultOverlayPackages() {
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800313 final String str = SystemProperties.get(DEFAULT_OVERLAYS_PROP);
314 if (TextUtils.isEmpty(str)) {
Adam Lesinski7b031812018-02-22 13:32:53 -0800315 return EmptyArray.STRING;
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800316 }
317
318 final ArraySet<String> defaultPackages = new ArraySet<>();
319 for (String packageName : str.split(";")) {
320 if (!TextUtils.isEmpty(packageName)) {
321 defaultPackages.add(packageName);
322 }
323 }
Adam Lesinski7b031812018-02-22 13:32:53 -0800324 return defaultPackages.toArray(new String[defaultPackages.size()]);
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800325 }
326
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100327 private final class PackageReceiver extends BroadcastReceiver {
328 @Override
329 public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
Youngha Park14d8d682018-08-02 15:43:38 +0900330 final String action = intent.getAction();
331 if (action == null) {
332 Slog.e(TAG, "Cannot handle package broadcast with null action");
333 return;
334 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100335 final Uri data = intent.getData();
336 if (data == null) {
337 Slog.e(TAG, "Cannot handle package broadcast with null data");
338 return;
339 }
340 final String packageName = data.getSchemeSpecificPart();
341
342 final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
343
344 final int[] userIds;
345 final int extraUid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL);
346 if (extraUid == UserHandle.USER_NULL) {
347 userIds = mUserManager.getUserIds();
348 } else {
349 userIds = new int[] { UserHandle.getUserId(extraUid) };
350 }
351
Youngha Park14d8d682018-08-02 15:43:38 +0900352 switch (action) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100353 case ACTION_PACKAGE_ADDED:
354 if (replacing) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100355 onPackageReplaced(packageName, userIds);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100356 } else {
357 onPackageAdded(packageName, userIds);
358 }
359 break;
360 case ACTION_PACKAGE_CHANGED:
361 onPackageChanged(packageName, userIds);
362 break;
363 case ACTION_PACKAGE_REMOVED:
364 if (replacing) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100365 onPackageReplacing(packageName, userIds);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100366 } else {
367 onPackageRemoved(packageName, userIds);
368 }
369 break;
370 default:
371 // do nothing
372 break;
373 }
374 }
375
376 private void onPackageAdded(@NonNull final String packageName,
377 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100378 try {
379 traceBegin(TRACE_TAG_RRO, "OMS#onPackageAdded " + packageName);
380 for (final int userId : userIds) {
381 synchronized (mLock) {
382 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
383 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100384 if (pi != null && !pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100385 mPackageManager.cachePackageInfo(packageName, userId, pi);
386 if (pi.isOverlayPackage()) {
387 mImpl.onOverlayPackageAdded(packageName, userId);
388 } else {
389 mImpl.onTargetPackageAdded(packageName, userId);
390 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100391 }
392 }
393 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100394 } finally {
395 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100396 }
397 }
398
399 private void onPackageChanged(@NonNull final String packageName,
400 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100401 try {
402 traceBegin(TRACE_TAG_RRO, "OMS#onPackageChanged " + packageName);
403 for (int userId : userIds) {
404 synchronized (mLock) {
405 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
406 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100407 if (pi != null && pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100408 mPackageManager.cachePackageInfo(packageName, userId, pi);
409 if (pi.isOverlayPackage()) {
410 mImpl.onOverlayPackageChanged(packageName, userId);
411 } else {
412 mImpl.onTargetPackageChanged(packageName, userId);
413 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100414 }
415 }
416 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100417 } finally {
418 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100419 }
420 }
421
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100422 private void onPackageReplacing(@NonNull final String packageName,
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100423 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100424 try {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100425 traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplacing " + packageName);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100426 for (int userId : userIds) {
427 synchronized (mLock) {
428 mPackageManager.forgetPackageInfo(packageName, userId);
429 final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
430 if (oi != null) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100431 mImpl.onOverlayPackageReplacing(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100432 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100433 }
434 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100435 } finally {
436 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100437 }
438 }
439
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100440 private void onPackageReplaced(@NonNull final String packageName,
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100441 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100442 try {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100443 traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplaced " + packageName);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100444 for (int userId : userIds) {
445 synchronized (mLock) {
446 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
447 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100448 if (pi != null && !pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100449 mPackageManager.cachePackageInfo(packageName, userId, pi);
450 if (pi.isOverlayPackage()) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100451 mImpl.onOverlayPackageReplaced(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100452 } else {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100453 mImpl.onTargetPackageReplaced(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100454 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100455 }
456 }
457 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100458 } finally {
459 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100460 }
461 }
462
463 private void onPackageRemoved(@NonNull final String packageName,
464 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100465 try {
466 traceBegin(TRACE_TAG_RRO, "OMS#onPackageRemoved " + packageName);
467 for (int userId : userIds) {
468 synchronized (mLock) {
469 mPackageManager.forgetPackageInfo(packageName, userId);
470 final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
471 if (oi != null) {
472 mImpl.onOverlayPackageRemoved(packageName, userId);
473 } else {
474 mImpl.onTargetPackageRemoved(packageName, userId);
475 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100476 }
477 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100478 } finally {
479 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100480 }
481 }
482 }
483
484 private final class UserReceiver extends BroadcastReceiver {
485 @Override
486 public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700487 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100488 switch (intent.getAction()) {
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700489 case ACTION_USER_ADDED:
490 if (userId != UserHandle.USER_NULL) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100491 try {
492 traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_ADDED");
493 final ArrayList<String> targets;
494 synchronized (mLock) {
495 targets = mImpl.updateOverlaysForUser(userId);
496 }
497 updateOverlayPaths(userId, targets);
498 } finally {
499 traceEnd(TRACE_TAG_RRO);
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700500 }
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700501 }
502 break;
503
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100504 case ACTION_USER_REMOVED:
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100505 if (userId != UserHandle.USER_NULL) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100506 try {
507 traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_REMOVED");
508 synchronized (mLock) {
509 mImpl.onUserRemoved(userId);
510 mPackageManager.forgetAllPackageInfos(userId);
511 }
512 } finally {
513 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100514 }
515 }
516 break;
517 default:
518 // do nothing
519 break;
520 }
521 }
522 }
523
524 private final IBinder mService = new IOverlayManager.Stub() {
525 @Override
Adam Lesinskic745f422017-04-05 16:31:30 -0700526 public Map<String, List<OverlayInfo>> getAllOverlays(int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100527 try {
528 traceBegin(TRACE_TAG_RRO, "OMS#getAllOverlays " + userId);
529 userId = handleIncomingUser(userId, "getAllOverlays");
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100530
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100531 synchronized (mLock) {
532 return mImpl.getOverlaysForUser(userId);
533 }
534 } finally {
535 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100536 }
537 }
538
539 @Override
540 public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName,
541 int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100542 try {
543 traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfosForTarget " + targetPackageName);
544 userId = handleIncomingUser(userId, "getOverlayInfosForTarget");
545 if (targetPackageName == null) {
546 return Collections.emptyList();
547 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100548
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100549 synchronized (mLock) {
550 return mImpl.getOverlayInfosForTarget(targetPackageName, userId);
551 }
552 } finally {
553 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100554 }
555 }
556
557 @Override
558 public OverlayInfo getOverlayInfo(@Nullable final String packageName,
559 int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100560 try {
561 traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfo " + packageName);
562 userId = handleIncomingUser(userId, "getOverlayInfo");
563 if (packageName == null) {
564 return null;
565 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100566
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100567 synchronized (mLock) {
568 return mImpl.getOverlayInfo(packageName, userId);
569 }
570 } finally {
571 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100572 }
573 }
574
575 @Override
576 public boolean setEnabled(@Nullable final String packageName, final boolean enable,
577 int userId) throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100578 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100579 traceBegin(TRACE_TAG_RRO, "OMS#setEnabled " + packageName + " " + enable);
580 enforceChangeOverlayPackagesPermission("setEnabled");
581 userId = handleIncomingUser(userId, "setEnabled");
582 if (packageName == null) {
583 return false;
584 }
585
586 final long ident = Binder.clearCallingIdentity();
587 try {
588 synchronized (mLock) {
589 return mImpl.setEnabled(packageName, enable, userId);
590 }
591 } finally {
592 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100593 }
594 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100595 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100596 }
597 }
598
599 @Override
Jason Monk929ed8d2017-03-07 16:01:20 -0500600 public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable,
601 int userId) throws RemoteException {
Jason Monk929ed8d2017-03-07 16:01:20 -0500602 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100603 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusive " + packageName + " " + enable);
604 enforceChangeOverlayPackagesPermission("setEnabledExclusive");
605 userId = handleIncomingUser(userId, "setEnabledExclusive");
606 if (packageName == null || !enable) {
607 return false;
608 }
609
610 final long ident = Binder.clearCallingIdentity();
611 try {
612 synchronized (mLock) {
613 return mImpl.setEnabledExclusive(packageName, false /* withinCategory */,
614 userId);
615 }
616 } finally {
617 Binder.restoreCallingIdentity(ident);
Adrian Roosc84df772018-01-19 21:20:22 +0100618 }
619 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100620 traceEnd(TRACE_TAG_RRO);
Adrian Roosc84df772018-01-19 21:20:22 +0100621 }
622 }
623
624 @Override
625 public boolean setEnabledExclusiveInCategory(@Nullable String packageName, int userId)
626 throws RemoteException {
Adrian Roosc84df772018-01-19 21:20:22 +0100627 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100628 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusiveInCategory " + packageName);
629 enforceChangeOverlayPackagesPermission("setEnabledExclusiveInCategory");
630 userId = handleIncomingUser(userId, "setEnabledExclusiveInCategory");
631 if (packageName == null) {
632 return false;
633 }
634
635 final long ident = Binder.clearCallingIdentity();
636 try {
637 synchronized (mLock) {
638 return mImpl.setEnabledExclusive(packageName, true /* withinCategory */,
639 userId);
640 }
641 } finally {
642 Binder.restoreCallingIdentity(ident);
Jason Monk929ed8d2017-03-07 16:01:20 -0500643 }
644 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100645 traceEnd(TRACE_TAG_RRO);
Jason Monk929ed8d2017-03-07 16:01:20 -0500646 }
647 }
648
649 @Override
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100650 public boolean setPriority(@Nullable final String packageName,
651 @Nullable final String parentPackageName, int userId) throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100652 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100653 traceBegin(TRACE_TAG_RRO, "OMS#setPriority " + packageName + " "
654 + parentPackageName);
655 enforceChangeOverlayPackagesPermission("setPriority");
656 userId = handleIncomingUser(userId, "setPriority");
657 if (packageName == null || parentPackageName == null) {
658 return false;
659 }
660
661 final long ident = Binder.clearCallingIdentity();
662 try {
663 synchronized (mLock) {
664 return mImpl.setPriority(packageName, parentPackageName, userId);
665 }
666 } finally {
667 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100668 }
669 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100670 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100671 }
672 }
673
674 @Override
675 public boolean setHighestPriority(@Nullable final String packageName, int userId)
676 throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100677 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100678 traceBegin(TRACE_TAG_RRO, "OMS#setHighestPriority " + packageName);
679 enforceChangeOverlayPackagesPermission("setHighestPriority");
680 userId = handleIncomingUser(userId, "setHighestPriority");
681 if (packageName == null) {
682 return false;
683 }
684
685 final long ident = Binder.clearCallingIdentity();
686 try {
687 synchronized (mLock) {
688 return mImpl.setHighestPriority(packageName, userId);
689 }
690 } finally {
691 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100692 }
693 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100694 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100695 }
696 }
697
698 @Override
699 public boolean setLowestPriority(@Nullable final String packageName, int userId)
700 throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100701 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100702 traceBegin(TRACE_TAG_RRO, "OMS#setLowestPriority " + packageName);
703 enforceChangeOverlayPackagesPermission("setLowestPriority");
704 userId = handleIncomingUser(userId, "setLowestPriority");
705 if (packageName == null) {
706 return false;
707 }
708
709 final long ident = Binder.clearCallingIdentity();
710 try {
711 synchronized (mLock) {
712 return mImpl.setLowestPriority(packageName, userId);
713 }
714 } finally {
715 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100716 }
717 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100718 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100719 }
720 }
721
722 @Override
Winson Chung43f311e2019-04-29 12:57:21 -0700723 public String[] getDefaultOverlayPackages() throws RemoteException {
724 try {
725 traceBegin(TRACE_TAG_RRO, "OMS#getDefaultOverlayPackages");
726 getContext().enforceCallingOrSelfPermission(
727 android.Manifest.permission.MODIFY_THEME_OVERLAY, null);
728
729 final long ident = Binder.clearCallingIdentity();
730 try {
731 synchronized (mLock) {
732 return mImpl.getDefaultOverlayPackages();
733 }
734 } finally {
735 Binder.restoreCallingIdentity(ident);
736 }
737 } finally {
738 traceEnd(TRACE_TAG_RRO);
739 }
740 }
741
742 @Override
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100743 public void onShellCommand(@NonNull final FileDescriptor in,
744 @NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
745 @NonNull final String[] args, @NonNull final ShellCallback callback,
746 @NonNull final ResultReceiver resultReceiver) {
747 (new OverlayManagerShellCommand(this)).exec(
748 this, in, out, err, args, callback, resultReceiver);
749 }
750
751 @Override
Mårten Kongstada465aec2019-04-12 12:32:41 +0200752 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
753 final DumpState dumpState = new DumpState();
754 dumpState.setUserId(UserHandle.getUserId(Binder.getCallingUid()));
755
756 int opti = 0;
757 while (opti < args.length) {
758 final String opt = args[opti];
759 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
760 break;
761 }
762 opti++;
763
764 if ("-h".equals(opt)) {
765 pw.println("dump [-h] [--verbose] [--user USER_ID] [[FIELD] PACKAGE]");
766 pw.println(" Print debugging information about the overlay manager.");
767 pw.println(" With optional parameter PACKAGE, limit output to the specified");
768 pw.println(" package. With optional parameter FIELD, limit output to");
769 pw.println(" the value of that SettingsItem field. Field names are");
770 pw.println(" case insensitive and out.println the m prefix can be omitted,");
771 pw.println(" so the following are equivalent: mState, mstate, State, state.");
772 return;
773 } else if ("--user".equals(opt)) {
774 opti++;
775 if (opti >= args.length) {
776 pw.println("Error: user missing argument");
777 return;
778 }
779 try {
780 dumpState.setUserId(Integer.parseInt(args[opti]));
781 } catch (NumberFormatException e) {
782 pw.println("Error: user argument is not a number: " + args[opti]);
783 return;
784 }
785 } else if ("--verbose".equals(opt)) {
786 dumpState.setVerbose(true);
787 } else {
788 pw.println("Unknown argument: " + opt + "; use -h for help");
789 }
790 }
791 if (opti < args.length) {
792 final String arg = args[opti];
793 opti++;
794 switch (arg) {
795 case "packagename":
796 case "userid":
797 case "targetpackagename":
798 case "targetoverlayablename":
799 case "basecodepath":
800 case "state":
801 case "isenabled":
802 case "isstatic":
803 case "priority":
804 case "category":
805 dumpState.setField(arg);
806 break;
807 default:
808 dumpState.setPackageName(arg);
809 break;
810 }
811 }
812 if (dumpState.getPackageName() == null && opti < args.length) {
813 dumpState.setPackageName(args[opti]);
814 opti++;
815 }
816
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100817 enforceDumpPermission("dump");
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100818 synchronized (mLock) {
Mårten Kongstada465aec2019-04-12 12:32:41 +0200819 mImpl.dump(pw, dumpState);
820 if (dumpState.getPackageName() == null) {
821 mPackageManager.dump(pw, dumpState);
822 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100823 }
824 }
825
826 /**
827 * Ensure that the caller has permission to interact with the given userId.
828 * If the calling user is not the same as the provided user, the caller needs
829 * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or
830 * root).
831 *
832 * @param userId the user to interact with
833 * @param message message for any SecurityException
834 */
835 private int handleIncomingUser(final int userId, @NonNull final String message) {
836 return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
837 Binder.getCallingUid(), userId, false, true, message, null);
838 }
839
840 /**
841 * Enforce that the caller holds the CHANGE_OVERLAY_PACKAGES permission (or is
842 * system or root).
843 *
844 * @param message used as message if SecurityException is thrown
845 * @throws SecurityException if the permission check fails
846 */
847 private void enforceChangeOverlayPackagesPermission(@NonNull final String message) {
Winson Chungddaf3512019-03-18 13:02:44 -0700848 getContext().enforceCallingOrSelfPermission(
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100849 android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, message);
850 }
851
852 /**
853 * Enforce that the caller holds the DUMP permission (or is system or root).
854 *
855 * @param message used as message if SecurityException is thrown
856 * @throws SecurityException if the permission check fails
857 */
858 private void enforceDumpPermission(@NonNull final String message) {
Winson Chungddaf3512019-03-18 13:02:44 -0700859 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, message);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100860 }
861 };
862
Adam Lesinskic745f422017-04-05 16:31:30 -0700863 private final class OverlayChangeListener
864 implements OverlayManagerServiceImpl.OverlayChangeListener {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100865 @Override
Mårten Kongstad497945c2018-04-27 09:56:13 +0200866 public void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100867 schedulePersistSettings();
Adam Lesinskic745f422017-04-05 16:31:30 -0700868 FgThread.getHandler().post(() -> {
Mårten Kongstad497945c2018-04-27 09:56:13 +0200869 updateAssets(userId, targetPackageName);
870
871 final Intent intent = new Intent(Intent.ACTION_OVERLAY_CHANGED,
872 Uri.fromParts("package", targetPackageName, null));
873 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
874
875 if (DEBUG) {
876 Slog.d(TAG, "send broadcast " + intent);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100877 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700878
Mårten Kongstad497945c2018-04-27 09:56:13 +0200879 try {
880 ActivityManager.getService().broadcastIntent(null, intent, null, null, 0,
881 null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false,
882 userId);
883 } catch (RemoteException e) {
884 // Intentionally left empty.
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100885 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700886 });
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100887 }
888 }
889
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700890 /**
891 * Updates the target packages' set of enabled overlays in PackageManager.
892 */
893 private void updateOverlayPaths(int userId, List<String> targetPackageNames) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100894 try {
895 traceBegin(TRACE_TAG_RRO, "OMS#updateOverlayPaths " + targetPackageNames);
896 if (DEBUG) {
897 Slog.d(TAG, "Updating overlay assets");
898 }
899 final PackageManagerInternal pm =
900 LocalServices.getService(PackageManagerInternal.class);
901 final boolean updateFrameworkRes = targetPackageNames.contains("android");
902 if (updateFrameworkRes) {
903 targetPackageNames = pm.getTargetPackageNames(userId);
904 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200905
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100906 final Map<String, List<String>> pendingChanges =
907 new ArrayMap<>(targetPackageNames.size());
908 synchronized (mLock) {
909 final List<String> frameworkOverlays =
910 mImpl.getEnabledOverlayPackageNames("android", userId);
911 final int n = targetPackageNames.size();
912 for (int i = 0; i < n; i++) {
913 final String targetPackageName = targetPackageNames.get(i);
914 List<String> list = new ArrayList<>();
915 if (!"android".equals(targetPackageName)) {
916 list.addAll(frameworkOverlays);
917 }
918 list.addAll(mImpl.getEnabledOverlayPackageNames(targetPackageName, userId));
919 pendingChanges.put(targetPackageName, list);
920 }
921 }
922
Mårten Kongstad38988342018-12-04 10:28:01 +0100923 final int n = targetPackageNames.size();
924 for (int i = 0; i < n; i++) {
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200925 final String targetPackageName = targetPackageNames.get(i);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100926 if (DEBUG) {
927 Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=["
928 + TextUtils.join(",", pendingChanges.get(targetPackageName))
929 + "] userId=" + userId);
Todd Kennedy560830c2017-06-16 13:55:13 -0700930 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200931
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100932 if (!pm.setEnabledOverlayPackages(
933 userId, targetPackageName, pendingChanges.get(targetPackageName))) {
934 Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d",
935 targetPackageName, userId));
936 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700937 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100938 } finally {
939 traceEnd(TRACE_TAG_RRO);
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200940 }
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700941 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200942
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700943 private void updateAssets(final int userId, final String targetPackageName) {
944 updateAssets(userId, Collections.singletonList(targetPackageName));
945 }
946
947 private void updateAssets(final int userId, List<String> targetPackageNames) {
948 updateOverlayPaths(userId, targetPackageNames);
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200949 final IActivityManager am = ActivityManager.getService();
950 try {
951 am.scheduleApplicationInfoChanged(targetPackageNames, userId);
952 } catch (RemoteException e) {
953 // Intentionally left empty.
954 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100955 }
956
957 private void schedulePersistSettings() {
958 if (mPersistSettingsScheduled.getAndSet(true)) {
959 return;
960 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700961 IoThread.getHandler().post(() -> {
962 mPersistSettingsScheduled.set(false);
963 if (DEBUG) {
964 Slog.d(TAG, "Writing overlay settings");
965 }
966 synchronized (mLock) {
967 FileOutputStream stream = null;
968 try {
969 stream = mSettingsFile.startWrite();
970 mSettings.persist(stream);
971 mSettingsFile.finishWrite(stream);
972 } catch (IOException | XmlPullParserException e) {
973 mSettingsFile.failWrite(stream);
974 Slog.e(TAG, "failed to persist overlay state", e);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100975 }
976 }
977 });
978 }
979
980 private void restoreSettings() {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100981 try {
982 traceBegin(TRACE_TAG_RRO, "OMS#restoreSettings");
983 synchronized (mLock) {
984 if (!mSettingsFile.getBaseFile().exists()) {
985 return;
Adam Lesinskid11c5512017-04-11 12:01:10 -0700986 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100987 try (FileInputStream stream = mSettingsFile.openRead()) {
988 mSettings.restore(stream);
Adam Lesinskid11c5512017-04-11 12:01:10 -0700989
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100990 // We might have data for dying users if the device was
991 // restarted before we received USER_REMOVED. Remove data for
992 // users that will not exist after the system is ready.
993
994 final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/);
995 final int[] liveUserIds = new int[liveUsers.size()];
996 for (int i = 0; i < liveUsers.size(); i++) {
997 liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier();
Adam Lesinskid11c5512017-04-11 12:01:10 -0700998 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100999 Arrays.sort(liveUserIds);
1000
1001 for (int userId : mSettings.getUsers()) {
1002 if (Arrays.binarySearch(liveUserIds, userId) < 0) {
1003 mSettings.removeUser(userId);
1004 }
1005 }
1006 } catch (IOException | XmlPullParserException e) {
1007 Slog.e(TAG, "failed to restore overlay state", e);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001008 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001009 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001010 } finally {
1011 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001012 }
1013 }
1014
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001015 private static final class PackageManagerHelper implements
1016 OverlayManagerServiceImpl.PackageManagerHelper {
1017
1018 private final IPackageManager mPackageManager;
1019 private final PackageManagerInternal mPackageManagerInternal;
1020
1021 // Use a cache for performance and for consistency within OMS: because
1022 // additional PACKAGE_* intents may be delivered while we process an
1023 // intent, querying the PackageManagerService for the actual current
1024 // state may lead to contradictions within OMS. Better then to lag
1025 // behind until all pending intents have been processed.
1026 private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>();
1027
1028 PackageManagerHelper() {
1029 mPackageManager = getPackageManager();
1030 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
1031 }
1032
1033 public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId,
1034 final boolean useCache) {
1035 if (useCache) {
1036 final PackageInfo cachedPi = getCachedPackageInfo(packageName, userId);
1037 if (cachedPi != null) {
1038 return cachedPi;
1039 }
1040 }
1041 try {
1042 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0, userId);
1043 if (useCache && pi != null) {
1044 cachePackageInfo(packageName, userId, pi);
1045 }
1046 return pi;
1047 } catch (RemoteException e) {
1048 // Intentionally left empty.
1049 }
1050 return null;
1051 }
1052
1053 @Override
1054 public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId) {
1055 return getPackageInfo(packageName, userId, true);
1056 }
1057
1058 @Override
1059 public boolean signaturesMatching(@NonNull final String packageName1,
1060 @NonNull final String packageName2, final int userId) {
1061 // The package manager does not support different versions of packages
1062 // to be installed for different users: ignore userId for now.
1063 try {
Adam Lesinskic745f422017-04-05 16:31:30 -07001064 return mPackageManager.checkSignatures(
1065 packageName1, packageName2) == SIGNATURE_MATCH;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001066 } catch (RemoteException e) {
1067 // Intentionally left blank
1068 }
1069 return false;
1070 }
1071
1072 @Override
1073 public List<PackageInfo> getOverlayPackages(final int userId) {
1074 return mPackageManagerInternal.getOverlayPackages(userId);
1075 }
1076
1077 public PackageInfo getCachedPackageInfo(@NonNull final String packageName,
1078 final int userId) {
1079 final HashMap<String, PackageInfo> map = mCache.get(userId);
1080 return map == null ? null : map.get(packageName);
1081 }
1082
1083 public void cachePackageInfo(@NonNull final String packageName, final int userId,
1084 @NonNull final PackageInfo pi) {
1085 HashMap<String, PackageInfo> map = mCache.get(userId);
1086 if (map == null) {
1087 map = new HashMap<>();
1088 mCache.put(userId, map);
1089 }
1090 map.put(packageName, pi);
1091 }
1092
1093 public void forgetPackageInfo(@NonNull final String packageName, final int userId) {
1094 final HashMap<String, PackageInfo> map = mCache.get(userId);
1095 if (map == null) {
1096 return;
1097 }
1098 map.remove(packageName);
1099 if (map.isEmpty()) {
1100 mCache.delete(userId);
1101 }
1102 }
1103
1104 public void forgetAllPackageInfos(final int userId) {
1105 mCache.delete(userId);
1106 }
1107
1108 private static final String TAB1 = " ";
1109 private static final String TAB2 = TAB1 + TAB1;
1110
Mårten Kongstada465aec2019-04-12 12:32:41 +02001111 public void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001112 pw.println("PackageInfo cache");
1113
Mårten Kongstada465aec2019-04-12 12:32:41 +02001114 if (!dumpState.isVerbose()) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001115 int count = 0;
Mårten Kongstad38988342018-12-04 10:28:01 +01001116 final int n = mCache.size();
1117 for (int i = 0; i < n; i++) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001118 final int userId = mCache.keyAt(i);
1119 count += mCache.get(userId).size();
1120 }
1121 pw.println(TAB1 + count + " package(s)");
1122 return;
1123 }
1124
1125 if (mCache.size() == 0) {
1126 pw.println(TAB1 + "<empty>");
1127 return;
1128 }
1129
Mårten Kongstad38988342018-12-04 10:28:01 +01001130 final int n = mCache.size();
1131 for (int i = 0; i < n; i++) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001132 final int userId = mCache.keyAt(i);
1133 pw.println(TAB1 + "User " + userId);
1134 final HashMap<String, PackageInfo> map = mCache.get(userId);
1135 for (Map.Entry<String, PackageInfo> entry : map.entrySet()) {
1136 pw.println(TAB2 + entry.getKey() + ": " + entry.getValue());
1137 }
1138 }
1139 }
1140 }
1141}