blob: 83bea9dd1efce55796bcbde3b6560b40ed078dc5 [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;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010065import com.android.server.pm.UserManagerService;
66
Adam Lesinski7b031812018-02-22 13:32:53 -080067import libcore.util.EmptyArray;
68
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010069import org.xmlpull.v1.XmlPullParserException;
70
71import java.io.File;
72import java.io.FileDescriptor;
73import java.io.FileInputStream;
74import java.io.FileOutputStream;
75import java.io.IOException;
76import java.io.PrintWriter;
77import java.util.ArrayList;
Adam Lesinskid11c5512017-04-11 12:01:10 -070078import java.util.Arrays;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010079import java.util.Collections;
80import java.util.HashMap;
81import java.util.List;
82import java.util.Map;
83import java.util.concurrent.atomic.AtomicBoolean;
84
85/**
86 * Service to manage asset overlays.
87 *
88 * <p>Asset overlays are additional resources that come from apks loaded
89 * alongside the system and app apks. This service, the OverlayManagerService
90 * (OMS), tracks which installed overlays to use and provides methods to change
91 * this. Changes propagate to running applications as part of the Activity
92 * lifecycle. This allows Activities to reread their resources at a well
93 * defined point.</p>
94 *
95 * <p>By itself, the OMS will not change what overlays should be active.
96 * Instead, it is only responsible for making sure that overlays *can* be used
97 * from a technical and security point of view and to activate overlays in
98 * response to external requests. The responsibility to toggle overlays on and
99 * off lies within components that implement different use-cases such as themes
100 * or dynamic customization.</p>
101 *
102 * <p>The OMS receives input from three sources:</p>
103 *
104 * <ul>
105 * <li>Callbacks from the SystemService class, specifically when the
106 * Android framework is booting and when the end user switches Android
107 * users.</li>
108 *
109 * <li>Intents from the PackageManagerService (PMS). Overlays are regular
110 * apks, and whenever a package is installed (or removed, or has a
111 * component enabled or disabled), the PMS broadcasts this as an intent.
112 * When the OMS receives one of these intents, it updates its internal
113 * representation of the available overlays and, if there was a visible
114 * change, triggers an asset refresh in the affected apps.</li>
115 *
116 * <li>External requests via the {@link IOverlayManager AIDL interface}.
117 * The interface allows clients to read information about the currently
118 * available overlays, change whether an overlay should be used or not, and
119 * change the relative order in which overlay packages are loaded.
120 * Read-access is granted if the request targets the same Android user as
121 * the caller runs as, or if the caller holds the
122 * INTERACT_ACROSS_USERS_FULL permission. Write-access is granted if the
123 * caller is granted read-access and additionaly holds the
124 * CHANGE_OVERLAY_PACKAGES permission.</li>
125 * </ul>
126 *
127 * <p>The AIDL interface works with String package names, int user IDs, and
128 * {@link OverlayInfo} objects. OverlayInfo instances are used to track a
129 * specific pair of target and overlay packages and include information such as
130 * the current state of the overlay. OverlayInfo objects are immutable.</p>
131 *
132 * <p>Internally, OverlayInfo objects are maintained by the
133 * OverlayManagerSettings class. The OMS and its helper classes are notified of
134 * changes to the settings by the OverlayManagerSettings.ChangeListener
135 * callback interface. The file /data/system/overlays.xml is used to persist
136 * the settings.</p>
137 *
138 * <p>Creation and deletion of idmap files are handled by the IdmapManager
139 * class.</p>
140 *
141 * <p>The following is an overview of OMS and its related classes. Note how box
142 * (2) does the heavy lifting, box (1) interacts with the Android framework,
143 * and box (3) replaces box (1) during unit testing.</p>
144 *
145 * <pre>
146 * Android framework
147 * | ^
148 * . . . | . . . . | . . . .
149 * . | | .
150 * . AIDL, broadcasts .
151 * . intents | .
152 * . | | . . . . . . . . . . . .
153 * . v | . .
154 * . OverlayManagerService . OverlayManagerTests .
155 * . \ . / .
156 * . (1) \ . / (3) .
157 * . . . . . . . . . . \ . . . / . . . . . . . . .
158 * . \ / .
159 * . (2) \ / .
160 * . OverlayManagerServiceImpl .
161 * . | | .
162 * . | | .
163 * . OverlayManagerSettings IdmapManager .
164 * . .
165 * . . . . . . . . . . . . . . . . . . . . . .
166 * </pre>
167 *
Mårten Kongstad1370c052018-05-03 10:48:35 +0200168 * <p>To test the OMS, execute:
169 * <code>
170 * atest FrameworksServicesTests:com.android.server.om # internal tests
171 * atest OverlayDeviceTests OverlayHostTests # public API tests
172 * </code>
173 * </p>
174 *
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100175 * <p>Finally, here is a list of keywords used in the OMS context.</p>
176 *
177 * <ul>
178 * <li><b>target [package]</b> -- A regular apk that may have its resource
179 * pool extended by zero or more overlay packages.</li>
180 *
181 * <li><b>overlay [package]</b> -- An apk that provides additional
182 * resources to another apk.</li>
183 *
184 * <li><b>OMS</b> -- The OverlayManagerService, i.e. this class.</li>
185 *
186 * <li><b>approved</b> -- An overlay is approved if the OMS has verified
187 * that it can be used technically speaking (its target package is
188 * installed, at least one resource name in both packages match, the
189 * idmap was created, etc) and that it is secure to do so. External
190 * clients can not change this state.</li>
191 *
192 * <li><b>not approved</b> -- The opposite of approved.</li>
193 *
194 * <li><b>enabled</b> -- An overlay currently in active use and thus part
195 * of resource lookups. This requires the overlay to be approved. Only
196 * external clients can change this state.</li>
197 *
198 * <li><b>disabled</b> -- The opposite of enabled.</li>
199 *
200 * <li><b>idmap</b> -- A mapping of resource IDs between target and overlay
201 * used during resource lookup. Also the name of the binary that creates
202 * the mapping.</li>
203 * </ul>
204 */
205public final class OverlayManagerService extends SystemService {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100206 static final String TAG = "OverlayManager";
207
208 static final boolean DEBUG = false;
209
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800210 /**
211 * The system property that specifies the default overlays to apply.
212 * This is a semicolon separated list of package names.
213 *
214 * Ex: com.android.vendor.overlay_one;com.android.vendor.overlay_two
215 */
216 private static final String DEFAULT_OVERLAYS_PROP = "ro.boot.vendor.overlay.theme";
217
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100218 private final Object mLock = new Object();
219
220 private final AtomicFile mSettingsFile;
221
222 private final PackageManagerHelper mPackageManager;
223
224 private final UserManagerService mUserManager;
225
226 private final OverlayManagerSettings mSettings;
227
228 private final OverlayManagerServiceImpl mImpl;
229
230 private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
231
Mårten Kongstad77b53b22019-10-01 08:29:21 +0200232 public OverlayManagerService(@NonNull final Context context) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100233 super(context);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100234 try {
235 traceBegin(TRACE_TAG_RRO, "OMS#OverlayManagerService");
236 mSettingsFile = new AtomicFile(
237 new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
238 mPackageManager = new PackageManagerHelper();
239 mUserManager = UserManagerService.getInstance();
Mårten Kongstad77b53b22019-10-01 08:29:21 +0200240 IdmapManager im = new IdmapManager(mPackageManager);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100241 mSettings = new OverlayManagerSettings();
242 mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
243 getDefaultOverlayPackages(), new OverlayChangeListener());
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100244
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100245 final IntentFilter packageFilter = new IntentFilter();
246 packageFilter.addAction(ACTION_PACKAGE_ADDED);
247 packageFilter.addAction(ACTION_PACKAGE_CHANGED);
248 packageFilter.addAction(ACTION_PACKAGE_REMOVED);
249 packageFilter.addDataScheme("package");
250 getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
251 packageFilter, null, null);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100252
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100253 final IntentFilter userFilter = new IntentFilter();
254 userFilter.addAction(ACTION_USER_ADDED);
255 userFilter.addAction(ACTION_USER_REMOVED);
256 getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
257 userFilter, null, null);
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700258
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100259 restoreSettings();
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100260
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100261 initIfNeeded();
262 onSwitchUser(UserHandle.USER_SYSTEM);
Mårten Kongstadcd78e0f2018-05-23 10:41:35 +0200263
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100264 publishBinderService(Context.OVERLAY_SERVICE, mService);
265 publishLocalService(OverlayManagerService.class, this);
266 } finally {
267 traceEnd(TRACE_TAG_RRO);
268 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100269 }
270
271 @Override
272 public void onStart() {
273 // Intentionally left empty.
274 }
275
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700276 private void initIfNeeded() {
277 final UserManager um = getContext().getSystemService(UserManager.class);
278 final List<UserInfo> users = um.getUsers(true /*excludeDying*/);
279 synchronized (mLock) {
280 final int userCount = users.size();
281 for (int i = 0; i < userCount; i++) {
282 final UserInfo userInfo = users.get(i);
283 if (!userInfo.supportsSwitchTo() && userInfo.id != UserHandle.USER_SYSTEM) {
284 // Initialize any users that can't be switched to, as there state would
285 // never be setup in onSwitchUser(). We will switch to the system user right
286 // after this, and its state will be setup there.
287 final List<String> targets = mImpl.updateOverlaysForUser(users.get(i).id);
288 updateOverlayPaths(users.get(i).id, targets);
289 }
290 }
291 }
292 }
293
Fyodor Kupolov94ab1a62017-03-06 14:28:20 -0800294 @Override
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100295 public void onSwitchUser(final int newUserId) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100296 try {
297 traceBegin(TRACE_TAG_RRO, "OMS#onSwitchUser " + newUserId);
298 // ensure overlays in the settings are up-to-date, and propagate
299 // any asset changes to the rest of the system
300 synchronized (mLock) {
301 final List<String> targets = mImpl.updateOverlaysForUser(newUserId);
302 updateAssets(newUserId, targets);
303 }
304 schedulePersistSettings();
305 } finally {
306 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100307 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100308 }
309
Adam Lesinski7b031812018-02-22 13:32:53 -0800310 private static String[] getDefaultOverlayPackages() {
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800311 final String str = SystemProperties.get(DEFAULT_OVERLAYS_PROP);
312 if (TextUtils.isEmpty(str)) {
Adam Lesinski7b031812018-02-22 13:32:53 -0800313 return EmptyArray.STRING;
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800314 }
315
316 final ArraySet<String> defaultPackages = new ArraySet<>();
317 for (String packageName : str.split(";")) {
318 if (!TextUtils.isEmpty(packageName)) {
319 defaultPackages.add(packageName);
320 }
321 }
Adam Lesinski7b031812018-02-22 13:32:53 -0800322 return defaultPackages.toArray(new String[defaultPackages.size()]);
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800323 }
324
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100325 private final class PackageReceiver extends BroadcastReceiver {
326 @Override
327 public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
Youngha Park14d8d682018-08-02 15:43:38 +0900328 final String action = intent.getAction();
329 if (action == null) {
330 Slog.e(TAG, "Cannot handle package broadcast with null action");
331 return;
332 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100333 final Uri data = intent.getData();
334 if (data == null) {
335 Slog.e(TAG, "Cannot handle package broadcast with null data");
336 return;
337 }
338 final String packageName = data.getSchemeSpecificPart();
339
340 final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
341
342 final int[] userIds;
343 final int extraUid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL);
344 if (extraUid == UserHandle.USER_NULL) {
345 userIds = mUserManager.getUserIds();
346 } else {
347 userIds = new int[] { UserHandle.getUserId(extraUid) };
348 }
349
Youngha Park14d8d682018-08-02 15:43:38 +0900350 switch (action) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100351 case ACTION_PACKAGE_ADDED:
352 if (replacing) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100353 onPackageReplaced(packageName, userIds);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100354 } else {
355 onPackageAdded(packageName, userIds);
356 }
357 break;
358 case ACTION_PACKAGE_CHANGED:
359 onPackageChanged(packageName, userIds);
360 break;
361 case ACTION_PACKAGE_REMOVED:
362 if (replacing) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100363 onPackageReplacing(packageName, userIds);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100364 } else {
365 onPackageRemoved(packageName, userIds);
366 }
367 break;
368 default:
369 // do nothing
370 break;
371 }
372 }
373
374 private void onPackageAdded(@NonNull final String packageName,
375 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100376 try {
377 traceBegin(TRACE_TAG_RRO, "OMS#onPackageAdded " + packageName);
378 for (final int userId : userIds) {
379 synchronized (mLock) {
380 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
381 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100382 if (pi != null && !pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100383 mPackageManager.cachePackageInfo(packageName, userId, pi);
384 if (pi.isOverlayPackage()) {
385 mImpl.onOverlayPackageAdded(packageName, userId);
386 } else {
387 mImpl.onTargetPackageAdded(packageName, userId);
388 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100389 }
390 }
391 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100392 } finally {
393 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100394 }
395 }
396
397 private void onPackageChanged(@NonNull final String packageName,
398 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100399 try {
400 traceBegin(TRACE_TAG_RRO, "OMS#onPackageChanged " + packageName);
401 for (int userId : userIds) {
402 synchronized (mLock) {
403 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
404 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100405 if (pi != null && pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100406 mPackageManager.cachePackageInfo(packageName, userId, pi);
407 if (pi.isOverlayPackage()) {
408 mImpl.onOverlayPackageChanged(packageName, userId);
409 } else {
410 mImpl.onTargetPackageChanged(packageName, userId);
411 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100412 }
413 }
414 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100415 } finally {
416 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100417 }
418 }
419
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100420 private void onPackageReplacing(@NonNull final String packageName,
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100421 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100422 try {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100423 traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplacing " + packageName);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100424 for (int userId : userIds) {
425 synchronized (mLock) {
426 mPackageManager.forgetPackageInfo(packageName, userId);
427 final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
428 if (oi != null) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100429 mImpl.onOverlayPackageReplacing(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100430 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100431 }
432 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100433 } finally {
434 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100435 }
436 }
437
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100438 private void onPackageReplaced(@NonNull final String packageName,
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100439 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100440 try {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100441 traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplaced " + packageName);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100442 for (int userId : userIds) {
443 synchronized (mLock) {
444 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
445 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100446 if (pi != null && !pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100447 mPackageManager.cachePackageInfo(packageName, userId, pi);
448 if (pi.isOverlayPackage()) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100449 mImpl.onOverlayPackageReplaced(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100450 } else {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100451 mImpl.onTargetPackageReplaced(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100452 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100453 }
454 }
455 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100456 } finally {
457 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100458 }
459 }
460
461 private void onPackageRemoved(@NonNull final String packageName,
462 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100463 try {
464 traceBegin(TRACE_TAG_RRO, "OMS#onPackageRemoved " + packageName);
465 for (int userId : userIds) {
466 synchronized (mLock) {
467 mPackageManager.forgetPackageInfo(packageName, userId);
468 final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
469 if (oi != null) {
470 mImpl.onOverlayPackageRemoved(packageName, userId);
471 } else {
472 mImpl.onTargetPackageRemoved(packageName, userId);
473 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100474 }
475 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100476 } finally {
477 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100478 }
479 }
480 }
481
482 private final class UserReceiver extends BroadcastReceiver {
483 @Override
484 public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700485 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100486 switch (intent.getAction()) {
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700487 case ACTION_USER_ADDED:
488 if (userId != UserHandle.USER_NULL) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100489 try {
490 traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_ADDED");
491 final ArrayList<String> targets;
492 synchronized (mLock) {
493 targets = mImpl.updateOverlaysForUser(userId);
494 }
495 updateOverlayPaths(userId, targets);
496 } finally {
497 traceEnd(TRACE_TAG_RRO);
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700498 }
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700499 }
500 break;
501
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100502 case ACTION_USER_REMOVED:
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100503 if (userId != UserHandle.USER_NULL) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100504 try {
505 traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_REMOVED");
506 synchronized (mLock) {
507 mImpl.onUserRemoved(userId);
508 mPackageManager.forgetAllPackageInfos(userId);
509 }
510 } finally {
511 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100512 }
513 }
514 break;
515 default:
516 // do nothing
517 break;
518 }
519 }
520 }
521
522 private final IBinder mService = new IOverlayManager.Stub() {
523 @Override
Adam Lesinskic745f422017-04-05 16:31:30 -0700524 public Map<String, List<OverlayInfo>> getAllOverlays(int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100525 try {
526 traceBegin(TRACE_TAG_RRO, "OMS#getAllOverlays " + userId);
527 userId = handleIncomingUser(userId, "getAllOverlays");
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100528
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100529 synchronized (mLock) {
530 return mImpl.getOverlaysForUser(userId);
531 }
532 } finally {
533 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100534 }
535 }
536
537 @Override
538 public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName,
539 int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100540 try {
541 traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfosForTarget " + targetPackageName);
542 userId = handleIncomingUser(userId, "getOverlayInfosForTarget");
543 if (targetPackageName == null) {
544 return Collections.emptyList();
545 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100546
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100547 synchronized (mLock) {
548 return mImpl.getOverlayInfosForTarget(targetPackageName, userId);
549 }
550 } finally {
551 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100552 }
553 }
554
555 @Override
556 public OverlayInfo getOverlayInfo(@Nullable final String packageName,
557 int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100558 try {
559 traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfo " + packageName);
560 userId = handleIncomingUser(userId, "getOverlayInfo");
561 if (packageName == null) {
562 return null;
563 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100564
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100565 synchronized (mLock) {
566 return mImpl.getOverlayInfo(packageName, userId);
567 }
568 } finally {
569 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100570 }
571 }
572
573 @Override
574 public boolean setEnabled(@Nullable final String packageName, final boolean enable,
575 int userId) throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100576 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100577 traceBegin(TRACE_TAG_RRO, "OMS#setEnabled " + packageName + " " + enable);
578 enforceChangeOverlayPackagesPermission("setEnabled");
579 userId = handleIncomingUser(userId, "setEnabled");
580 if (packageName == null) {
581 return false;
582 }
583
584 final long ident = Binder.clearCallingIdentity();
585 try {
586 synchronized (mLock) {
587 return mImpl.setEnabled(packageName, enable, userId);
588 }
589 } finally {
590 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100591 }
592 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100593 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100594 }
595 }
596
597 @Override
Jason Monk929ed8d2017-03-07 16:01:20 -0500598 public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable,
599 int userId) throws RemoteException {
Jason Monk929ed8d2017-03-07 16:01:20 -0500600 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100601 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusive " + packageName + " " + enable);
602 enforceChangeOverlayPackagesPermission("setEnabledExclusive");
603 userId = handleIncomingUser(userId, "setEnabledExclusive");
604 if (packageName == null || !enable) {
605 return false;
606 }
607
608 final long ident = Binder.clearCallingIdentity();
609 try {
610 synchronized (mLock) {
611 return mImpl.setEnabledExclusive(packageName, false /* withinCategory */,
612 userId);
613 }
614 } finally {
615 Binder.restoreCallingIdentity(ident);
Adrian Roosc84df772018-01-19 21:20:22 +0100616 }
617 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100618 traceEnd(TRACE_TAG_RRO);
Adrian Roosc84df772018-01-19 21:20:22 +0100619 }
620 }
621
622 @Override
623 public boolean setEnabledExclusiveInCategory(@Nullable String packageName, int userId)
624 throws RemoteException {
Adrian Roosc84df772018-01-19 21:20:22 +0100625 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100626 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusiveInCategory " + packageName);
627 enforceChangeOverlayPackagesPermission("setEnabledExclusiveInCategory");
628 userId = handleIncomingUser(userId, "setEnabledExclusiveInCategory");
629 if (packageName == null) {
630 return false;
631 }
632
633 final long ident = Binder.clearCallingIdentity();
634 try {
635 synchronized (mLock) {
636 return mImpl.setEnabledExclusive(packageName, true /* withinCategory */,
637 userId);
638 }
639 } finally {
640 Binder.restoreCallingIdentity(ident);
Jason Monk929ed8d2017-03-07 16:01:20 -0500641 }
642 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100643 traceEnd(TRACE_TAG_RRO);
Jason Monk929ed8d2017-03-07 16:01:20 -0500644 }
645 }
646
647 @Override
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100648 public boolean setPriority(@Nullable final String packageName,
649 @Nullable final String parentPackageName, int userId) throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100650 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100651 traceBegin(TRACE_TAG_RRO, "OMS#setPriority " + packageName + " "
652 + parentPackageName);
653 enforceChangeOverlayPackagesPermission("setPriority");
654 userId = handleIncomingUser(userId, "setPriority");
655 if (packageName == null || parentPackageName == null) {
656 return false;
657 }
658
659 final long ident = Binder.clearCallingIdentity();
660 try {
661 synchronized (mLock) {
662 return mImpl.setPriority(packageName, parentPackageName, userId);
663 }
664 } finally {
665 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100666 }
667 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100668 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100669 }
670 }
671
672 @Override
673 public boolean setHighestPriority(@Nullable final String packageName, int userId)
674 throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100675 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100676 traceBegin(TRACE_TAG_RRO, "OMS#setHighestPriority " + packageName);
677 enforceChangeOverlayPackagesPermission("setHighestPriority");
678 userId = handleIncomingUser(userId, "setHighestPriority");
679 if (packageName == null) {
680 return false;
681 }
682
683 final long ident = Binder.clearCallingIdentity();
684 try {
685 synchronized (mLock) {
686 return mImpl.setHighestPriority(packageName, userId);
687 }
688 } finally {
689 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100690 }
691 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100692 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100693 }
694 }
695
696 @Override
697 public boolean setLowestPriority(@Nullable final String packageName, int userId)
698 throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100699 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100700 traceBegin(TRACE_TAG_RRO, "OMS#setLowestPriority " + packageName);
701 enforceChangeOverlayPackagesPermission("setLowestPriority");
702 userId = handleIncomingUser(userId, "setLowestPriority");
703 if (packageName == null) {
704 return false;
705 }
706
707 final long ident = Binder.clearCallingIdentity();
708 try {
709 synchronized (mLock) {
710 return mImpl.setLowestPriority(packageName, userId);
711 }
712 } finally {
713 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100714 }
715 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100716 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100717 }
718 }
719
720 @Override
Winson Chung43f311e2019-04-29 12:57:21 -0700721 public String[] getDefaultOverlayPackages() throws RemoteException {
722 try {
723 traceBegin(TRACE_TAG_RRO, "OMS#getDefaultOverlayPackages");
724 getContext().enforceCallingOrSelfPermission(
725 android.Manifest.permission.MODIFY_THEME_OVERLAY, null);
726
727 final long ident = Binder.clearCallingIdentity();
728 try {
729 synchronized (mLock) {
730 return mImpl.getDefaultOverlayPackages();
731 }
732 } finally {
733 Binder.restoreCallingIdentity(ident);
734 }
735 } finally {
736 traceEnd(TRACE_TAG_RRO);
737 }
738 }
739
740 @Override
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100741 public void onShellCommand(@NonNull final FileDescriptor in,
742 @NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
743 @NonNull final String[] args, @NonNull final ShellCallback callback,
744 @NonNull final ResultReceiver resultReceiver) {
Mårten Kongstad4ea02d12019-06-14 14:08:18 +0200745 (new OverlayManagerShellCommand(getContext(), this)).exec(
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100746 this, in, out, err, args, callback, resultReceiver);
747 }
748
749 @Override
Mårten Kongstada465aec2019-04-12 12:32:41 +0200750 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
751 final DumpState dumpState = new DumpState();
Ryan Mitchellb7ef06a2019-07-17 17:16:23 -0700752 dumpState.setUserId(UserHandle.USER_ALL);
Mårten Kongstada465aec2019-04-12 12:32:41 +0200753
754 int opti = 0;
755 while (opti < args.length) {
756 final String opt = args[opti];
757 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
758 break;
759 }
760 opti++;
761
762 if ("-h".equals(opt)) {
763 pw.println("dump [-h] [--verbose] [--user USER_ID] [[FIELD] PACKAGE]");
764 pw.println(" Print debugging information about the overlay manager.");
765 pw.println(" With optional parameter PACKAGE, limit output to the specified");
766 pw.println(" package. With optional parameter FIELD, limit output to");
767 pw.println(" the value of that SettingsItem field. Field names are");
768 pw.println(" case insensitive and out.println the m prefix can be omitted,");
769 pw.println(" so the following are equivalent: mState, mstate, State, state.");
770 return;
771 } else if ("--user".equals(opt)) {
Mårten Kongstada465aec2019-04-12 12:32:41 +0200772 if (opti >= args.length) {
773 pw.println("Error: user missing argument");
774 return;
775 }
776 try {
777 dumpState.setUserId(Integer.parseInt(args[opti]));
Ryan Mitchellb7ef06a2019-07-17 17:16:23 -0700778 opti++;
Mårten Kongstada465aec2019-04-12 12:32:41 +0200779 } catch (NumberFormatException e) {
780 pw.println("Error: user argument is not a number: " + args[opti]);
781 return;
782 }
783 } else if ("--verbose".equals(opt)) {
784 dumpState.setVerbose(true);
785 } else {
786 pw.println("Unknown argument: " + opt + "; use -h for help");
787 }
788 }
789 if (opti < args.length) {
790 final String arg = args[opti];
791 opti++;
792 switch (arg) {
793 case "packagename":
794 case "userid":
795 case "targetpackagename":
796 case "targetoverlayablename":
797 case "basecodepath":
798 case "state":
799 case "isenabled":
800 case "isstatic":
801 case "priority":
802 case "category":
803 dumpState.setField(arg);
804 break;
805 default:
806 dumpState.setPackageName(arg);
807 break;
808 }
809 }
810 if (dumpState.getPackageName() == null && opti < args.length) {
811 dumpState.setPackageName(args[opti]);
812 opti++;
813 }
814
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100815 enforceDumpPermission("dump");
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100816 synchronized (mLock) {
Mårten Kongstada465aec2019-04-12 12:32:41 +0200817 mImpl.dump(pw, dumpState);
818 if (dumpState.getPackageName() == null) {
819 mPackageManager.dump(pw, dumpState);
820 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100821 }
822 }
823
824 /**
825 * Ensure that the caller has permission to interact with the given userId.
826 * If the calling user is not the same as the provided user, the caller needs
827 * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or
828 * root).
829 *
830 * @param userId the user to interact with
831 * @param message message for any SecurityException
832 */
833 private int handleIncomingUser(final int userId, @NonNull final String message) {
834 return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
835 Binder.getCallingUid(), userId, false, true, message, null);
836 }
837
838 /**
839 * Enforce that the caller holds the CHANGE_OVERLAY_PACKAGES permission (or is
840 * system or root).
841 *
842 * @param message used as message if SecurityException is thrown
843 * @throws SecurityException if the permission check fails
844 */
845 private void enforceChangeOverlayPackagesPermission(@NonNull final String message) {
Winson Chungddaf3512019-03-18 13:02:44 -0700846 getContext().enforceCallingOrSelfPermission(
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100847 android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, message);
848 }
849
850 /**
851 * Enforce that the caller holds the DUMP permission (or is system or root).
852 *
853 * @param message used as message if SecurityException is thrown
854 * @throws SecurityException if the permission check fails
855 */
856 private void enforceDumpPermission(@NonNull final String message) {
Winson Chungddaf3512019-03-18 13:02:44 -0700857 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, message);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100858 }
859 };
860
Adam Lesinskic745f422017-04-05 16:31:30 -0700861 private final class OverlayChangeListener
862 implements OverlayManagerServiceImpl.OverlayChangeListener {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100863 @Override
Mårten Kongstad497945c2018-04-27 09:56:13 +0200864 public void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100865 schedulePersistSettings();
Adam Lesinskic745f422017-04-05 16:31:30 -0700866 FgThread.getHandler().post(() -> {
Mårten Kongstad497945c2018-04-27 09:56:13 +0200867 updateAssets(userId, targetPackageName);
868
869 final Intent intent = new Intent(Intent.ACTION_OVERLAY_CHANGED,
870 Uri.fromParts("package", targetPackageName, null));
871 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
872
873 if (DEBUG) {
874 Slog.d(TAG, "send broadcast " + intent);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100875 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700876
Mårten Kongstad497945c2018-04-27 09:56:13 +0200877 try {
878 ActivityManager.getService().broadcastIntent(null, intent, null, null, 0,
879 null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false,
880 userId);
881 } catch (RemoteException e) {
882 // Intentionally left empty.
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100883 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700884 });
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100885 }
886 }
887
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700888 /**
889 * Updates the target packages' set of enabled overlays in PackageManager.
890 */
891 private void updateOverlayPaths(int userId, List<String> targetPackageNames) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100892 try {
893 traceBegin(TRACE_TAG_RRO, "OMS#updateOverlayPaths " + targetPackageNames);
894 if (DEBUG) {
895 Slog.d(TAG, "Updating overlay assets");
896 }
897 final PackageManagerInternal pm =
898 LocalServices.getService(PackageManagerInternal.class);
899 final boolean updateFrameworkRes = targetPackageNames.contains("android");
900 if (updateFrameworkRes) {
901 targetPackageNames = pm.getTargetPackageNames(userId);
902 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200903
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100904 final Map<String, List<String>> pendingChanges =
905 new ArrayMap<>(targetPackageNames.size());
906 synchronized (mLock) {
907 final List<String> frameworkOverlays =
908 mImpl.getEnabledOverlayPackageNames("android", userId);
909 final int n = targetPackageNames.size();
910 for (int i = 0; i < n; i++) {
911 final String targetPackageName = targetPackageNames.get(i);
912 List<String> list = new ArrayList<>();
913 if (!"android".equals(targetPackageName)) {
914 list.addAll(frameworkOverlays);
915 }
916 list.addAll(mImpl.getEnabledOverlayPackageNames(targetPackageName, userId));
917 pendingChanges.put(targetPackageName, list);
918 }
919 }
920
Mårten Kongstad38988342018-12-04 10:28:01 +0100921 final int n = targetPackageNames.size();
922 for (int i = 0; i < n; i++) {
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200923 final String targetPackageName = targetPackageNames.get(i);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100924 if (DEBUG) {
925 Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=["
926 + TextUtils.join(",", pendingChanges.get(targetPackageName))
927 + "] userId=" + userId);
Todd Kennedy560830c2017-06-16 13:55:13 -0700928 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200929
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100930 if (!pm.setEnabledOverlayPackages(
931 userId, targetPackageName, pendingChanges.get(targetPackageName))) {
932 Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d",
933 targetPackageName, userId));
934 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700935 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100936 } finally {
937 traceEnd(TRACE_TAG_RRO);
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200938 }
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700939 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200940
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700941 private void updateAssets(final int userId, final String targetPackageName) {
942 updateAssets(userId, Collections.singletonList(targetPackageName));
943 }
944
945 private void updateAssets(final int userId, List<String> targetPackageNames) {
946 updateOverlayPaths(userId, targetPackageNames);
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200947 final IActivityManager am = ActivityManager.getService();
948 try {
949 am.scheduleApplicationInfoChanged(targetPackageNames, userId);
950 } catch (RemoteException e) {
951 // Intentionally left empty.
952 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100953 }
954
955 private void schedulePersistSettings() {
956 if (mPersistSettingsScheduled.getAndSet(true)) {
957 return;
958 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700959 IoThread.getHandler().post(() -> {
960 mPersistSettingsScheduled.set(false);
961 if (DEBUG) {
962 Slog.d(TAG, "Writing overlay settings");
963 }
964 synchronized (mLock) {
965 FileOutputStream stream = null;
966 try {
967 stream = mSettingsFile.startWrite();
968 mSettings.persist(stream);
969 mSettingsFile.finishWrite(stream);
970 } catch (IOException | XmlPullParserException e) {
971 mSettingsFile.failWrite(stream);
972 Slog.e(TAG, "failed to persist overlay state", e);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100973 }
974 }
975 });
976 }
977
978 private void restoreSettings() {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100979 try {
980 traceBegin(TRACE_TAG_RRO, "OMS#restoreSettings");
981 synchronized (mLock) {
982 if (!mSettingsFile.getBaseFile().exists()) {
983 return;
Adam Lesinskid11c5512017-04-11 12:01:10 -0700984 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100985 try (FileInputStream stream = mSettingsFile.openRead()) {
986 mSettings.restore(stream);
Adam Lesinskid11c5512017-04-11 12:01:10 -0700987
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100988 // We might have data for dying users if the device was
989 // restarted before we received USER_REMOVED. Remove data for
990 // users that will not exist after the system is ready.
991
992 final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/);
993 final int[] liveUserIds = new int[liveUsers.size()];
994 for (int i = 0; i < liveUsers.size(); i++) {
995 liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier();
Adam Lesinskid11c5512017-04-11 12:01:10 -0700996 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100997 Arrays.sort(liveUserIds);
998
999 for (int userId : mSettings.getUsers()) {
1000 if (Arrays.binarySearch(liveUserIds, userId) < 0) {
1001 mSettings.removeUser(userId);
1002 }
1003 }
1004 } catch (IOException | XmlPullParserException e) {
1005 Slog.e(TAG, "failed to restore overlay state", e);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001006 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001007 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001008 } finally {
1009 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001010 }
1011 }
1012
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001013 private static final class PackageManagerHelper implements
1014 OverlayManagerServiceImpl.PackageManagerHelper {
1015
1016 private final IPackageManager mPackageManager;
1017 private final PackageManagerInternal mPackageManagerInternal;
1018
1019 // Use a cache for performance and for consistency within OMS: because
1020 // additional PACKAGE_* intents may be delivered while we process an
1021 // intent, querying the PackageManagerService for the actual current
1022 // state may lead to contradictions within OMS. Better then to lag
1023 // behind until all pending intents have been processed.
1024 private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>();
1025
1026 PackageManagerHelper() {
1027 mPackageManager = getPackageManager();
1028 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
1029 }
1030
1031 public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId,
1032 final boolean useCache) {
1033 if (useCache) {
1034 final PackageInfo cachedPi = getCachedPackageInfo(packageName, userId);
1035 if (cachedPi != null) {
1036 return cachedPi;
1037 }
1038 }
1039 try {
1040 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0, userId);
1041 if (useCache && pi != null) {
1042 cachePackageInfo(packageName, userId, pi);
1043 }
1044 return pi;
1045 } catch (RemoteException e) {
1046 // Intentionally left empty.
1047 }
1048 return null;
1049 }
1050
1051 @Override
1052 public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId) {
1053 return getPackageInfo(packageName, userId, true);
1054 }
1055
1056 @Override
1057 public boolean signaturesMatching(@NonNull final String packageName1,
1058 @NonNull final String packageName2, final int userId) {
1059 // The package manager does not support different versions of packages
1060 // to be installed for different users: ignore userId for now.
1061 try {
Adam Lesinskic745f422017-04-05 16:31:30 -07001062 return mPackageManager.checkSignatures(
1063 packageName1, packageName2) == SIGNATURE_MATCH;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001064 } catch (RemoteException e) {
1065 // Intentionally left blank
1066 }
1067 return false;
1068 }
1069
1070 @Override
1071 public List<PackageInfo> getOverlayPackages(final int userId) {
1072 return mPackageManagerInternal.getOverlayPackages(userId);
1073 }
1074
1075 public PackageInfo getCachedPackageInfo(@NonNull final String packageName,
1076 final int userId) {
1077 final HashMap<String, PackageInfo> map = mCache.get(userId);
1078 return map == null ? null : map.get(packageName);
1079 }
1080
1081 public void cachePackageInfo(@NonNull final String packageName, final int userId,
1082 @NonNull final PackageInfo pi) {
1083 HashMap<String, PackageInfo> map = mCache.get(userId);
1084 if (map == null) {
1085 map = new HashMap<>();
1086 mCache.put(userId, map);
1087 }
1088 map.put(packageName, pi);
1089 }
1090
1091 public void forgetPackageInfo(@NonNull final String packageName, final int userId) {
1092 final HashMap<String, PackageInfo> map = mCache.get(userId);
1093 if (map == null) {
1094 return;
1095 }
1096 map.remove(packageName);
1097 if (map.isEmpty()) {
1098 mCache.delete(userId);
1099 }
1100 }
1101
1102 public void forgetAllPackageInfos(final int userId) {
1103 mCache.delete(userId);
1104 }
1105
1106 private static final String TAB1 = " ";
1107 private static final String TAB2 = TAB1 + TAB1;
1108
Mårten Kongstada465aec2019-04-12 12:32:41 +02001109 public void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001110 pw.println("PackageInfo cache");
1111
Mårten Kongstada465aec2019-04-12 12:32:41 +02001112 if (!dumpState.isVerbose()) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001113 int count = 0;
Mårten Kongstad38988342018-12-04 10:28:01 +01001114 final int n = mCache.size();
1115 for (int i = 0; i < n; i++) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001116 final int userId = mCache.keyAt(i);
1117 count += mCache.get(userId).size();
1118 }
1119 pw.println(TAB1 + count + " package(s)");
1120 return;
1121 }
1122
1123 if (mCache.size() == 0) {
1124 pw.println(TAB1 + "<empty>");
1125 return;
1126 }
1127
Mårten Kongstad38988342018-12-04 10:28:01 +01001128 final int n = mCache.size();
1129 for (int i = 0; i < n; i++) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001130 final int userId = mCache.keyAt(i);
1131 pw.println(TAB1 + "User " + userId);
1132 final HashMap<String, PackageInfo> map = mCache.get(userId);
1133 for (Map.Entry<String, PackageInfo> entry : map.entrySet()) {
1134 pw.println(TAB2 + entry.getKey() + ": " + entry.getValue());
1135 }
1136 }
1137 }
1138 }
1139}