blob: 5f3e50320752f5f6cd740834bb21480ffbd37fae [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;
Mårten Kongstad6d18d772019-10-04 10:50:10 +020020import static android.content.Intent.ACTION_OVERLAY_CHANGED;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010021import static android.content.Intent.ACTION_PACKAGE_ADDED;
22import static android.content.Intent.ACTION_PACKAGE_CHANGED;
23import static android.content.Intent.ACTION_PACKAGE_REMOVED;
Adam Lesinskiada8deb2017-05-12 13:50:42 -070024import static android.content.Intent.ACTION_USER_ADDED;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010025import static android.content.Intent.ACTION_USER_REMOVED;
Mårten Kongstad6d18d772019-10-04 10:50:10 +020026import static android.content.Intent.EXTRA_REASON;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010027import static android.content.pm.PackageManager.SIGNATURE_MATCH;
Mårten Kongstadacfcdc72018-12-03 14:59:51 +010028import static android.os.Trace.TRACE_TAG_RRO;
29import static android.os.Trace.traceBegin;
30import static android.os.Trace.traceEnd;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010031
32import android.annotation.NonNull;
33import android.annotation.Nullable;
34import android.app.ActivityManager;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010035import android.app.IActivityManager;
36import android.content.BroadcastReceiver;
37import android.content.Context;
38import android.content.Intent;
39import android.content.IntentFilter;
40import android.content.om.IOverlayManager;
41import android.content.om.OverlayInfo;
42import android.content.pm.IPackageManager;
43import android.content.pm.PackageInfo;
44import android.content.pm.PackageManagerInternal;
45import android.content.pm.UserInfo;
46import android.net.Uri;
47import android.os.Binder;
48import android.os.Environment;
49import android.os.IBinder;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010050import android.os.RemoteException;
51import android.os.ResultReceiver;
52import android.os.ShellCallback;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080053import android.os.SystemProperties;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010054import android.os.UserHandle;
Adam Lesinskiada8deb2017-05-12 13:50:42 -070055import android.os.UserManager;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080056import android.text.TextUtils;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010057import android.util.ArrayMap;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080058import android.util.ArraySet;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010059import android.util.AtomicFile;
60import android.util.Slog;
61import android.util.SparseArray;
62
63import com.android.server.FgThread;
64import com.android.server.IoThread;
65import com.android.server.LocalServices;
66import com.android.server.SystemService;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010067import com.android.server.pm.UserManagerService;
68
Adam Lesinski7b031812018-02-22 13:32:53 -080069import libcore.util.EmptyArray;
70
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010071import org.xmlpull.v1.XmlPullParserException;
72
73import java.io.File;
74import java.io.FileDescriptor;
75import java.io.FileInputStream;
76import java.io.FileOutputStream;
77import java.io.IOException;
78import java.io.PrintWriter;
79import java.util.ArrayList;
Adam Lesinskid11c5512017-04-11 12:01:10 -070080import java.util.Arrays;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010081import java.util.Collections;
82import java.util.HashMap;
83import java.util.List;
84import java.util.Map;
85import java.util.concurrent.atomic.AtomicBoolean;
86
87/**
88 * Service to manage asset overlays.
89 *
90 * <p>Asset overlays are additional resources that come from apks loaded
91 * alongside the system and app apks. This service, the OverlayManagerService
92 * (OMS), tracks which installed overlays to use and provides methods to change
93 * this. Changes propagate to running applications as part of the Activity
94 * lifecycle. This allows Activities to reread their resources at a well
95 * defined point.</p>
96 *
97 * <p>By itself, the OMS will not change what overlays should be active.
98 * Instead, it is only responsible for making sure that overlays *can* be used
99 * from a technical and security point of view and to activate overlays in
100 * response to external requests. The responsibility to toggle overlays on and
101 * off lies within components that implement different use-cases such as themes
102 * or dynamic customization.</p>
103 *
104 * <p>The OMS receives input from three sources:</p>
105 *
106 * <ul>
107 * <li>Callbacks from the SystemService class, specifically when the
108 * Android framework is booting and when the end user switches Android
109 * users.</li>
110 *
111 * <li>Intents from the PackageManagerService (PMS). Overlays are regular
112 * apks, and whenever a package is installed (or removed, or has a
113 * component enabled or disabled), the PMS broadcasts this as an intent.
114 * When the OMS receives one of these intents, it updates its internal
115 * representation of the available overlays and, if there was a visible
116 * change, triggers an asset refresh in the affected apps.</li>
117 *
118 * <li>External requests via the {@link IOverlayManager AIDL interface}.
119 * The interface allows clients to read information about the currently
120 * available overlays, change whether an overlay should be used or not, and
121 * change the relative order in which overlay packages are loaded.
122 * Read-access is granted if the request targets the same Android user as
123 * the caller runs as, or if the caller holds the
124 * INTERACT_ACROSS_USERS_FULL permission. Write-access is granted if the
125 * caller is granted read-access and additionaly holds the
126 * CHANGE_OVERLAY_PACKAGES permission.</li>
127 * </ul>
128 *
129 * <p>The AIDL interface works with String package names, int user IDs, and
130 * {@link OverlayInfo} objects. OverlayInfo instances are used to track a
131 * specific pair of target and overlay packages and include information such as
132 * the current state of the overlay. OverlayInfo objects are immutable.</p>
133 *
134 * <p>Internally, OverlayInfo objects are maintained by the
135 * OverlayManagerSettings class. The OMS and its helper classes are notified of
136 * changes to the settings by the OverlayManagerSettings.ChangeListener
137 * callback interface. The file /data/system/overlays.xml is used to persist
138 * the settings.</p>
139 *
140 * <p>Creation and deletion of idmap files are handled by the IdmapManager
141 * class.</p>
142 *
143 * <p>The following is an overview of OMS and its related classes. Note how box
144 * (2) does the heavy lifting, box (1) interacts with the Android framework,
145 * and box (3) replaces box (1) during unit testing.</p>
146 *
147 * <pre>
148 * Android framework
149 * | ^
150 * . . . | . . . . | . . . .
151 * . | | .
152 * . AIDL, broadcasts .
153 * . intents | .
154 * . | | . . . . . . . . . . . .
155 * . v | . .
156 * . OverlayManagerService . OverlayManagerTests .
157 * . \ . / .
158 * . (1) \ . / (3) .
159 * . . . . . . . . . . \ . . . / . . . . . . . . .
160 * . \ / .
161 * . (2) \ / .
162 * . OverlayManagerServiceImpl .
163 * . | | .
164 * . | | .
165 * . OverlayManagerSettings IdmapManager .
166 * . .
167 * . . . . . . . . . . . . . . . . . . . . . .
168 * </pre>
169 *
Mårten Kongstad1370c052018-05-03 10:48:35 +0200170 * <p>To test the OMS, execute:
171 * <code>
172 * atest FrameworksServicesTests:com.android.server.om # internal tests
173 * atest OverlayDeviceTests OverlayHostTests # public API tests
174 * </code>
175 * </p>
176 *
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100177 * <p>Finally, here is a list of keywords used in the OMS context.</p>
178 *
179 * <ul>
180 * <li><b>target [package]</b> -- A regular apk that may have its resource
181 * pool extended by zero or more overlay packages.</li>
182 *
183 * <li><b>overlay [package]</b> -- An apk that provides additional
184 * resources to another apk.</li>
185 *
186 * <li><b>OMS</b> -- The OverlayManagerService, i.e. this class.</li>
187 *
188 * <li><b>approved</b> -- An overlay is approved if the OMS has verified
189 * that it can be used technically speaking (its target package is
190 * installed, at least one resource name in both packages match, the
191 * idmap was created, etc) and that it is secure to do so. External
192 * clients can not change this state.</li>
193 *
194 * <li><b>not approved</b> -- The opposite of approved.</li>
195 *
196 * <li><b>enabled</b> -- An overlay currently in active use and thus part
197 * of resource lookups. This requires the overlay to be approved. Only
198 * external clients can change this state.</li>
199 *
200 * <li><b>disabled</b> -- The opposite of enabled.</li>
201 *
202 * <li><b>idmap</b> -- A mapping of resource IDs between target and overlay
203 * used during resource lookup. Also the name of the binary that creates
204 * the mapping.</li>
205 * </ul>
206 */
207public final class OverlayManagerService extends SystemService {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100208 static final String TAG = "OverlayManager";
209
210 static final boolean DEBUG = false;
211
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800212 /**
213 * The system property that specifies the default overlays to apply.
214 * This is a semicolon separated list of package names.
215 *
216 * Ex: com.android.vendor.overlay_one;com.android.vendor.overlay_two
217 */
218 private static final String DEFAULT_OVERLAYS_PROP = "ro.boot.vendor.overlay.theme";
219
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100220 private final Object mLock = new Object();
221
222 private final AtomicFile mSettingsFile;
223
224 private final PackageManagerHelper mPackageManager;
225
226 private final UserManagerService mUserManager;
227
228 private final OverlayManagerSettings mSettings;
229
230 private final OverlayManagerServiceImpl mImpl;
231
232 private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
233
Mårten Kongstad77b53b22019-10-01 08:29:21 +0200234 public OverlayManagerService(@NonNull final Context context) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100235 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();
Mårten Kongstad77b53b22019-10-01 08:29:21 +0200242 IdmapManager im = new IdmapManager(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:
Mårten Kongstad6d18d772019-10-04 10:50:10 +0200361 // ignore the intent if it was sent by the package manager as a result of the
362 // overlay manager having sent ACTION_OVERLAY_CHANGED
363 if (!ACTION_OVERLAY_CHANGED.equals(intent.getStringExtra(EXTRA_REASON))) {
364 onPackageChanged(packageName, userIds);
365 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100366 break;
367 case ACTION_PACKAGE_REMOVED:
368 if (replacing) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100369 onPackageReplacing(packageName, userIds);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100370 } else {
371 onPackageRemoved(packageName, userIds);
372 }
373 break;
374 default:
375 // do nothing
376 break;
377 }
378 }
379
380 private void onPackageAdded(@NonNull final String packageName,
381 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100382 try {
383 traceBegin(TRACE_TAG_RRO, "OMS#onPackageAdded " + packageName);
384 for (final int userId : userIds) {
385 synchronized (mLock) {
386 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
387 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100388 if (pi != null && !pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100389 mPackageManager.cachePackageInfo(packageName, userId, pi);
390 if (pi.isOverlayPackage()) {
391 mImpl.onOverlayPackageAdded(packageName, userId);
392 } else {
393 mImpl.onTargetPackageAdded(packageName, userId);
394 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100395 }
396 }
397 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100398 } finally {
399 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100400 }
401 }
402
403 private void onPackageChanged(@NonNull final String packageName,
404 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100405 try {
406 traceBegin(TRACE_TAG_RRO, "OMS#onPackageChanged " + packageName);
407 for (int userId : userIds) {
408 synchronized (mLock) {
409 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
410 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100411 if (pi != null && pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100412 mPackageManager.cachePackageInfo(packageName, userId, pi);
413 if (pi.isOverlayPackage()) {
414 mImpl.onOverlayPackageChanged(packageName, userId);
415 } else {
416 mImpl.onTargetPackageChanged(packageName, userId);
417 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100418 }
419 }
420 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100421 } finally {
422 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100423 }
424 }
425
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100426 private void onPackageReplacing(@NonNull final String packageName,
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100427 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100428 try {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100429 traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplacing " + packageName);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100430 for (int userId : userIds) {
431 synchronized (mLock) {
432 mPackageManager.forgetPackageInfo(packageName, userId);
433 final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
434 if (oi != null) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100435 mImpl.onOverlayPackageReplacing(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100436 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100437 }
438 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100439 } finally {
440 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100441 }
442 }
443
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100444 private void onPackageReplaced(@NonNull final String packageName,
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100445 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100446 try {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100447 traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplaced " + packageName);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100448 for (int userId : userIds) {
449 synchronized (mLock) {
450 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
451 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100452 if (pi != null && !pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100453 mPackageManager.cachePackageInfo(packageName, userId, pi);
454 if (pi.isOverlayPackage()) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100455 mImpl.onOverlayPackageReplaced(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100456 } else {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100457 mImpl.onTargetPackageReplaced(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100458 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100459 }
460 }
461 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100462 } finally {
463 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100464 }
465 }
466
467 private void onPackageRemoved(@NonNull final String packageName,
468 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100469 try {
470 traceBegin(TRACE_TAG_RRO, "OMS#onPackageRemoved " + packageName);
471 for (int userId : userIds) {
472 synchronized (mLock) {
473 mPackageManager.forgetPackageInfo(packageName, userId);
474 final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
475 if (oi != null) {
476 mImpl.onOverlayPackageRemoved(packageName, userId);
477 } else {
478 mImpl.onTargetPackageRemoved(packageName, userId);
479 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100480 }
481 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100482 } finally {
483 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100484 }
485 }
486 }
487
488 private final class UserReceiver extends BroadcastReceiver {
489 @Override
490 public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700491 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100492 switch (intent.getAction()) {
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700493 case ACTION_USER_ADDED:
494 if (userId != UserHandle.USER_NULL) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100495 try {
496 traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_ADDED");
497 final ArrayList<String> targets;
498 synchronized (mLock) {
499 targets = mImpl.updateOverlaysForUser(userId);
500 }
501 updateOverlayPaths(userId, targets);
502 } finally {
503 traceEnd(TRACE_TAG_RRO);
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700504 }
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700505 }
506 break;
507
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100508 case ACTION_USER_REMOVED:
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100509 if (userId != UserHandle.USER_NULL) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100510 try {
511 traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_REMOVED");
512 synchronized (mLock) {
513 mImpl.onUserRemoved(userId);
514 mPackageManager.forgetAllPackageInfos(userId);
515 }
516 } finally {
517 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100518 }
519 }
520 break;
521 default:
522 // do nothing
523 break;
524 }
525 }
526 }
527
528 private final IBinder mService = new IOverlayManager.Stub() {
529 @Override
Adam Lesinskic745f422017-04-05 16:31:30 -0700530 public Map<String, List<OverlayInfo>> getAllOverlays(int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100531 try {
532 traceBegin(TRACE_TAG_RRO, "OMS#getAllOverlays " + userId);
533 userId = handleIncomingUser(userId, "getAllOverlays");
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100534
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100535 synchronized (mLock) {
536 return mImpl.getOverlaysForUser(userId);
537 }
538 } finally {
539 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100540 }
541 }
542
543 @Override
544 public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName,
545 int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100546 try {
547 traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfosForTarget " + targetPackageName);
548 userId = handleIncomingUser(userId, "getOverlayInfosForTarget");
549 if (targetPackageName == null) {
550 return Collections.emptyList();
551 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100552
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100553 synchronized (mLock) {
554 return mImpl.getOverlayInfosForTarget(targetPackageName, userId);
555 }
556 } finally {
557 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100558 }
559 }
560
561 @Override
562 public OverlayInfo getOverlayInfo(@Nullable final String packageName,
563 int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100564 try {
565 traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfo " + packageName);
566 userId = handleIncomingUser(userId, "getOverlayInfo");
567 if (packageName == null) {
568 return null;
569 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100570
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100571 synchronized (mLock) {
572 return mImpl.getOverlayInfo(packageName, userId);
573 }
574 } finally {
575 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100576 }
577 }
578
579 @Override
580 public boolean setEnabled(@Nullable final String packageName, final boolean enable,
581 int userId) throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100582 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100583 traceBegin(TRACE_TAG_RRO, "OMS#setEnabled " + packageName + " " + enable);
584 enforceChangeOverlayPackagesPermission("setEnabled");
585 userId = handleIncomingUser(userId, "setEnabled");
586 if (packageName == null) {
587 return false;
588 }
589
590 final long ident = Binder.clearCallingIdentity();
591 try {
592 synchronized (mLock) {
593 return mImpl.setEnabled(packageName, enable, userId);
594 }
595 } finally {
596 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100597 }
598 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100599 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100600 }
601 }
602
603 @Override
Jason Monk929ed8d2017-03-07 16:01:20 -0500604 public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable,
605 int userId) throws RemoteException {
Jason Monk929ed8d2017-03-07 16:01:20 -0500606 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100607 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusive " + packageName + " " + enable);
608 enforceChangeOverlayPackagesPermission("setEnabledExclusive");
609 userId = handleIncomingUser(userId, "setEnabledExclusive");
610 if (packageName == null || !enable) {
611 return false;
612 }
613
614 final long ident = Binder.clearCallingIdentity();
615 try {
616 synchronized (mLock) {
617 return mImpl.setEnabledExclusive(packageName, false /* withinCategory */,
618 userId);
619 }
620 } finally {
621 Binder.restoreCallingIdentity(ident);
Adrian Roosc84df772018-01-19 21:20:22 +0100622 }
623 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100624 traceEnd(TRACE_TAG_RRO);
Adrian Roosc84df772018-01-19 21:20:22 +0100625 }
626 }
627
628 @Override
629 public boolean setEnabledExclusiveInCategory(@Nullable String packageName, int userId)
630 throws RemoteException {
Adrian Roosc84df772018-01-19 21:20:22 +0100631 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100632 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusiveInCategory " + packageName);
633 enforceChangeOverlayPackagesPermission("setEnabledExclusiveInCategory");
634 userId = handleIncomingUser(userId, "setEnabledExclusiveInCategory");
635 if (packageName == null) {
636 return false;
637 }
638
639 final long ident = Binder.clearCallingIdentity();
640 try {
641 synchronized (mLock) {
642 return mImpl.setEnabledExclusive(packageName, true /* withinCategory */,
643 userId);
644 }
645 } finally {
646 Binder.restoreCallingIdentity(ident);
Jason Monk929ed8d2017-03-07 16:01:20 -0500647 }
648 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100649 traceEnd(TRACE_TAG_RRO);
Jason Monk929ed8d2017-03-07 16:01:20 -0500650 }
651 }
652
653 @Override
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100654 public boolean setPriority(@Nullable final String packageName,
655 @Nullable final String parentPackageName, int userId) throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100656 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100657 traceBegin(TRACE_TAG_RRO, "OMS#setPriority " + packageName + " "
658 + parentPackageName);
659 enforceChangeOverlayPackagesPermission("setPriority");
660 userId = handleIncomingUser(userId, "setPriority");
661 if (packageName == null || parentPackageName == null) {
662 return false;
663 }
664
665 final long ident = Binder.clearCallingIdentity();
666 try {
667 synchronized (mLock) {
668 return mImpl.setPriority(packageName, parentPackageName, userId);
669 }
670 } finally {
671 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100672 }
673 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100674 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100675 }
676 }
677
678 @Override
679 public boolean setHighestPriority(@Nullable final String packageName, int userId)
680 throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100681 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100682 traceBegin(TRACE_TAG_RRO, "OMS#setHighestPriority " + packageName);
683 enforceChangeOverlayPackagesPermission("setHighestPriority");
684 userId = handleIncomingUser(userId, "setHighestPriority");
685 if (packageName == null) {
686 return false;
687 }
688
689 final long ident = Binder.clearCallingIdentity();
690 try {
691 synchronized (mLock) {
692 return mImpl.setHighestPriority(packageName, userId);
693 }
694 } finally {
695 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100696 }
697 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100698 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100699 }
700 }
701
702 @Override
703 public boolean setLowestPriority(@Nullable final String packageName, int userId)
704 throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100705 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100706 traceBegin(TRACE_TAG_RRO, "OMS#setLowestPriority " + packageName);
707 enforceChangeOverlayPackagesPermission("setLowestPriority");
708 userId = handleIncomingUser(userId, "setLowestPriority");
709 if (packageName == null) {
710 return false;
711 }
712
713 final long ident = Binder.clearCallingIdentity();
714 try {
715 synchronized (mLock) {
716 return mImpl.setLowestPriority(packageName, userId);
717 }
718 } finally {
719 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100720 }
721 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100722 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100723 }
724 }
725
726 @Override
Winson Chung43f311e2019-04-29 12:57:21 -0700727 public String[] getDefaultOverlayPackages() throws RemoteException {
728 try {
729 traceBegin(TRACE_TAG_RRO, "OMS#getDefaultOverlayPackages");
730 getContext().enforceCallingOrSelfPermission(
731 android.Manifest.permission.MODIFY_THEME_OVERLAY, null);
732
733 final long ident = Binder.clearCallingIdentity();
734 try {
735 synchronized (mLock) {
736 return mImpl.getDefaultOverlayPackages();
737 }
738 } finally {
739 Binder.restoreCallingIdentity(ident);
740 }
741 } finally {
742 traceEnd(TRACE_TAG_RRO);
743 }
744 }
745
746 @Override
Ryan Mitchell4043ca72019-06-03 16:11:24 -0700747 public void invalidateCachesForOverlay(@Nullable String packageName, int userId)
748 throws RemoteException {
749 if (packageName == null) {
750 return;
751 }
752
753 enforceChangeOverlayPackagesPermission("invalidateCachesForOverlay");
754 userId = handleIncomingUser(userId, "invalidateCachesForOverlay");
755 final long ident = Binder.clearCallingIdentity();
756 try {
757 synchronized (mLock) {
758 mImpl.removeIdmapForOverlay(packageName, userId);
759 }
760 } finally {
761 Binder.restoreCallingIdentity(ident);
762 }
763 }
764
765 @Override
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100766 public void onShellCommand(@NonNull final FileDescriptor in,
767 @NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
768 @NonNull final String[] args, @NonNull final ShellCallback callback,
769 @NonNull final ResultReceiver resultReceiver) {
Mårten Kongstad4ea02d12019-06-14 14:08:18 +0200770 (new OverlayManagerShellCommand(getContext(), this)).exec(
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100771 this, in, out, err, args, callback, resultReceiver);
772 }
773
774 @Override
Mårten Kongstada465aec2019-04-12 12:32:41 +0200775 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
776 final DumpState dumpState = new DumpState();
Ryan Mitchellb7ef06a2019-07-17 17:16:23 -0700777 dumpState.setUserId(UserHandle.USER_ALL);
Mårten Kongstada465aec2019-04-12 12:32:41 +0200778
779 int opti = 0;
780 while (opti < args.length) {
781 final String opt = args[opti];
782 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
783 break;
784 }
785 opti++;
786
787 if ("-h".equals(opt)) {
788 pw.println("dump [-h] [--verbose] [--user USER_ID] [[FIELD] PACKAGE]");
789 pw.println(" Print debugging information about the overlay manager.");
790 pw.println(" With optional parameter PACKAGE, limit output to the specified");
791 pw.println(" package. With optional parameter FIELD, limit output to");
792 pw.println(" the value of that SettingsItem field. Field names are");
793 pw.println(" case insensitive and out.println the m prefix can be omitted,");
794 pw.println(" so the following are equivalent: mState, mstate, State, state.");
795 return;
796 } else if ("--user".equals(opt)) {
Mårten Kongstada465aec2019-04-12 12:32:41 +0200797 if (opti >= args.length) {
798 pw.println("Error: user missing argument");
799 return;
800 }
801 try {
802 dumpState.setUserId(Integer.parseInt(args[opti]));
Ryan Mitchellb7ef06a2019-07-17 17:16:23 -0700803 opti++;
Mårten Kongstada465aec2019-04-12 12:32:41 +0200804 } catch (NumberFormatException e) {
805 pw.println("Error: user argument is not a number: " + args[opti]);
806 return;
807 }
808 } else if ("--verbose".equals(opt)) {
809 dumpState.setVerbose(true);
810 } else {
811 pw.println("Unknown argument: " + opt + "; use -h for help");
812 }
813 }
814 if (opti < args.length) {
815 final String arg = args[opti];
816 opti++;
817 switch (arg) {
818 case "packagename":
819 case "userid":
820 case "targetpackagename":
821 case "targetoverlayablename":
822 case "basecodepath":
823 case "state":
824 case "isenabled":
825 case "isstatic":
826 case "priority":
827 case "category":
828 dumpState.setField(arg);
829 break;
830 default:
831 dumpState.setPackageName(arg);
832 break;
833 }
834 }
835 if (dumpState.getPackageName() == null && opti < args.length) {
836 dumpState.setPackageName(args[opti]);
837 opti++;
838 }
839
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100840 enforceDumpPermission("dump");
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100841 synchronized (mLock) {
Mårten Kongstada465aec2019-04-12 12:32:41 +0200842 mImpl.dump(pw, dumpState);
843 if (dumpState.getPackageName() == null) {
844 mPackageManager.dump(pw, dumpState);
845 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100846 }
847 }
848
849 /**
850 * Ensure that the caller has permission to interact with the given userId.
851 * If the calling user is not the same as the provided user, the caller needs
852 * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or
853 * root).
854 *
855 * @param userId the user to interact with
856 * @param message message for any SecurityException
857 */
858 private int handleIncomingUser(final int userId, @NonNull final String message) {
859 return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
860 Binder.getCallingUid(), userId, false, true, message, null);
861 }
862
863 /**
864 * Enforce that the caller holds the CHANGE_OVERLAY_PACKAGES permission (or is
865 * system or root).
866 *
867 * @param message used as message if SecurityException is thrown
868 * @throws SecurityException if the permission check fails
869 */
870 private void enforceChangeOverlayPackagesPermission(@NonNull final String message) {
Winson Chungddaf3512019-03-18 13:02:44 -0700871 getContext().enforceCallingOrSelfPermission(
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100872 android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, message);
873 }
874
875 /**
876 * Enforce that the caller holds the DUMP permission (or is system or root).
877 *
878 * @param message used as message if SecurityException is thrown
879 * @throws SecurityException if the permission check fails
880 */
881 private void enforceDumpPermission(@NonNull final String message) {
Winson Chungddaf3512019-03-18 13:02:44 -0700882 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, message);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100883 }
884 };
885
Adam Lesinskic745f422017-04-05 16:31:30 -0700886 private final class OverlayChangeListener
887 implements OverlayManagerServiceImpl.OverlayChangeListener {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100888 @Override
Mårten Kongstad497945c2018-04-27 09:56:13 +0200889 public void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100890 schedulePersistSettings();
Adam Lesinskic745f422017-04-05 16:31:30 -0700891 FgThread.getHandler().post(() -> {
Mårten Kongstad497945c2018-04-27 09:56:13 +0200892 updateAssets(userId, targetPackageName);
893
Mårten Kongstad6d18d772019-10-04 10:50:10 +0200894 final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
Mårten Kongstad497945c2018-04-27 09:56:13 +0200895 Uri.fromParts("package", targetPackageName, null));
896 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
897
898 if (DEBUG) {
899 Slog.d(TAG, "send broadcast " + intent);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100900 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700901
Mårten Kongstad497945c2018-04-27 09:56:13 +0200902 try {
903 ActivityManager.getService().broadcastIntent(null, intent, null, null, 0,
904 null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false,
905 userId);
906 } catch (RemoteException e) {
907 // Intentionally left empty.
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100908 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700909 });
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100910 }
911 }
912
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700913 /**
914 * Updates the target packages' set of enabled overlays in PackageManager.
915 */
916 private void updateOverlayPaths(int userId, List<String> targetPackageNames) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100917 try {
918 traceBegin(TRACE_TAG_RRO, "OMS#updateOverlayPaths " + targetPackageNames);
919 if (DEBUG) {
920 Slog.d(TAG, "Updating overlay assets");
921 }
922 final PackageManagerInternal pm =
923 LocalServices.getService(PackageManagerInternal.class);
924 final boolean updateFrameworkRes = targetPackageNames.contains("android");
925 if (updateFrameworkRes) {
926 targetPackageNames = pm.getTargetPackageNames(userId);
927 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200928
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100929 final Map<String, List<String>> pendingChanges =
930 new ArrayMap<>(targetPackageNames.size());
931 synchronized (mLock) {
932 final List<String> frameworkOverlays =
933 mImpl.getEnabledOverlayPackageNames("android", userId);
934 final int n = targetPackageNames.size();
935 for (int i = 0; i < n; i++) {
936 final String targetPackageName = targetPackageNames.get(i);
937 List<String> list = new ArrayList<>();
938 if (!"android".equals(targetPackageName)) {
939 list.addAll(frameworkOverlays);
940 }
941 list.addAll(mImpl.getEnabledOverlayPackageNames(targetPackageName, userId));
942 pendingChanges.put(targetPackageName, list);
943 }
944 }
945
Mårten Kongstad38988342018-12-04 10:28:01 +0100946 final int n = targetPackageNames.size();
947 for (int i = 0; i < n; i++) {
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200948 final String targetPackageName = targetPackageNames.get(i);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100949 if (DEBUG) {
950 Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=["
951 + TextUtils.join(",", pendingChanges.get(targetPackageName))
952 + "] userId=" + userId);
Todd Kennedy560830c2017-06-16 13:55:13 -0700953 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200954
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100955 if (!pm.setEnabledOverlayPackages(
956 userId, targetPackageName, pendingChanges.get(targetPackageName))) {
957 Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d",
958 targetPackageName, userId));
959 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700960 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100961 } finally {
962 traceEnd(TRACE_TAG_RRO);
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200963 }
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700964 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200965
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700966 private void updateAssets(final int userId, final String targetPackageName) {
967 updateAssets(userId, Collections.singletonList(targetPackageName));
968 }
969
970 private void updateAssets(final int userId, List<String> targetPackageNames) {
971 updateOverlayPaths(userId, targetPackageNames);
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200972 final IActivityManager am = ActivityManager.getService();
973 try {
974 am.scheduleApplicationInfoChanged(targetPackageNames, userId);
975 } catch (RemoteException e) {
976 // Intentionally left empty.
977 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100978 }
979
980 private void schedulePersistSettings() {
981 if (mPersistSettingsScheduled.getAndSet(true)) {
982 return;
983 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700984 IoThread.getHandler().post(() -> {
985 mPersistSettingsScheduled.set(false);
986 if (DEBUG) {
987 Slog.d(TAG, "Writing overlay settings");
988 }
989 synchronized (mLock) {
990 FileOutputStream stream = null;
991 try {
992 stream = mSettingsFile.startWrite();
993 mSettings.persist(stream);
994 mSettingsFile.finishWrite(stream);
995 } catch (IOException | XmlPullParserException e) {
996 mSettingsFile.failWrite(stream);
997 Slog.e(TAG, "failed to persist overlay state", e);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100998 }
999 }
1000 });
1001 }
1002
1003 private void restoreSettings() {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001004 try {
1005 traceBegin(TRACE_TAG_RRO, "OMS#restoreSettings");
1006 synchronized (mLock) {
1007 if (!mSettingsFile.getBaseFile().exists()) {
1008 return;
Adam Lesinskid11c5512017-04-11 12:01:10 -07001009 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001010 try (FileInputStream stream = mSettingsFile.openRead()) {
1011 mSettings.restore(stream);
Adam Lesinskid11c5512017-04-11 12:01:10 -07001012
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001013 // We might have data for dying users if the device was
1014 // restarted before we received USER_REMOVED. Remove data for
1015 // users that will not exist after the system is ready.
1016
1017 final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/);
1018 final int[] liveUserIds = new int[liveUsers.size()];
1019 for (int i = 0; i < liveUsers.size(); i++) {
1020 liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier();
Adam Lesinskid11c5512017-04-11 12:01:10 -07001021 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001022 Arrays.sort(liveUserIds);
1023
1024 for (int userId : mSettings.getUsers()) {
1025 if (Arrays.binarySearch(liveUserIds, userId) < 0) {
1026 mSettings.removeUser(userId);
1027 }
1028 }
1029 } catch (IOException | XmlPullParserException e) {
1030 Slog.e(TAG, "failed to restore overlay state", e);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001031 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001032 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001033 } finally {
1034 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001035 }
1036 }
1037
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001038 private static final class PackageManagerHelper implements
1039 OverlayManagerServiceImpl.PackageManagerHelper {
1040
1041 private final IPackageManager mPackageManager;
1042 private final PackageManagerInternal mPackageManagerInternal;
1043
1044 // Use a cache for performance and for consistency within OMS: because
1045 // additional PACKAGE_* intents may be delivered while we process an
1046 // intent, querying the PackageManagerService for the actual current
1047 // state may lead to contradictions within OMS. Better then to lag
1048 // behind until all pending intents have been processed.
1049 private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>();
1050
1051 PackageManagerHelper() {
1052 mPackageManager = getPackageManager();
1053 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
1054 }
1055
1056 public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId,
1057 final boolean useCache) {
1058 if (useCache) {
1059 final PackageInfo cachedPi = getCachedPackageInfo(packageName, userId);
1060 if (cachedPi != null) {
1061 return cachedPi;
1062 }
1063 }
1064 try {
1065 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0, userId);
1066 if (useCache && pi != null) {
1067 cachePackageInfo(packageName, userId, pi);
1068 }
1069 return pi;
1070 } catch (RemoteException e) {
1071 // Intentionally left empty.
1072 }
1073 return null;
1074 }
1075
1076 @Override
1077 public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId) {
1078 return getPackageInfo(packageName, userId, true);
1079 }
1080
1081 @Override
1082 public boolean signaturesMatching(@NonNull final String packageName1,
1083 @NonNull final String packageName2, final int userId) {
1084 // The package manager does not support different versions of packages
1085 // to be installed for different users: ignore userId for now.
1086 try {
Adam Lesinskic745f422017-04-05 16:31:30 -07001087 return mPackageManager.checkSignatures(
1088 packageName1, packageName2) == SIGNATURE_MATCH;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001089 } catch (RemoteException e) {
1090 // Intentionally left blank
1091 }
1092 return false;
1093 }
1094
1095 @Override
1096 public List<PackageInfo> getOverlayPackages(final int userId) {
1097 return mPackageManagerInternal.getOverlayPackages(userId);
1098 }
1099
1100 public PackageInfo getCachedPackageInfo(@NonNull final String packageName,
1101 final int userId) {
1102 final HashMap<String, PackageInfo> map = mCache.get(userId);
1103 return map == null ? null : map.get(packageName);
1104 }
1105
1106 public void cachePackageInfo(@NonNull final String packageName, final int userId,
1107 @NonNull final PackageInfo pi) {
1108 HashMap<String, PackageInfo> map = mCache.get(userId);
1109 if (map == null) {
1110 map = new HashMap<>();
1111 mCache.put(userId, map);
1112 }
1113 map.put(packageName, pi);
1114 }
1115
1116 public void forgetPackageInfo(@NonNull final String packageName, final int userId) {
1117 final HashMap<String, PackageInfo> map = mCache.get(userId);
1118 if (map == null) {
1119 return;
1120 }
1121 map.remove(packageName);
1122 if (map.isEmpty()) {
1123 mCache.delete(userId);
1124 }
1125 }
1126
1127 public void forgetAllPackageInfos(final int userId) {
1128 mCache.delete(userId);
1129 }
1130
1131 private static final String TAB1 = " ";
1132 private static final String TAB2 = TAB1 + TAB1;
1133
Mårten Kongstada465aec2019-04-12 12:32:41 +02001134 public void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001135 pw.println("PackageInfo cache");
1136
Mårten Kongstada465aec2019-04-12 12:32:41 +02001137 if (!dumpState.isVerbose()) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001138 int count = 0;
Mårten Kongstad38988342018-12-04 10:28:01 +01001139 final int n = mCache.size();
1140 for (int i = 0; i < n; i++) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001141 final int userId = mCache.keyAt(i);
1142 count += mCache.get(userId).size();
1143 }
1144 pw.println(TAB1 + count + " package(s)");
1145 return;
1146 }
1147
1148 if (mCache.size() == 0) {
1149 pw.println(TAB1 + "<empty>");
1150 return;
1151 }
1152
Mårten Kongstad38988342018-12-04 10:28:01 +01001153 final int n = mCache.size();
1154 for (int i = 0; i < n; i++) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001155 final int userId = mCache.keyAt(i);
1156 pw.println(TAB1 + "User " + userId);
1157 final HashMap<String, PackageInfo> map = mCache.get(userId);
1158 for (Map.Entry<String, PackageInfo> entry : map.entrySet()) {
1159 pw.println(TAB2 + entry.getKey() + ": " + entry.getValue());
1160 }
1161 }
1162 }
1163 }
1164}