blob: 63de61c9782f7bbace433d4a789782136cb8337e [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;
Winsond9d17362019-10-02 12:41:29 -070042import android.content.om.OverlayableInfo;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010043import android.content.pm.IPackageManager;
44import android.content.pm.PackageInfo;
45import android.content.pm.PackageManagerInternal;
46import android.content.pm.UserInfo;
Winsond9d17362019-10-02 12:41:29 -070047import android.content.res.ApkAssets;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010048import android.net.Uri;
49import android.os.Binder;
50import android.os.Environment;
51import android.os.IBinder;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010052import android.os.RemoteException;
53import android.os.ResultReceiver;
54import android.os.ShellCallback;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080055import android.os.SystemProperties;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010056import android.os.UserHandle;
Adam Lesinskiada8deb2017-05-12 13:50:42 -070057import android.os.UserManager;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080058import android.text.TextUtils;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010059import android.util.ArrayMap;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080060import android.util.ArraySet;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010061import android.util.AtomicFile;
62import android.util.Slog;
63import android.util.SparseArray;
64
65import com.android.server.FgThread;
66import com.android.server.IoThread;
67import com.android.server.LocalServices;
Winsond9d17362019-10-02 12:41:29 -070068import com.android.server.SystemConfig;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010069import com.android.server.SystemService;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010070import com.android.server.pm.UserManagerService;
71
Adam Lesinski7b031812018-02-22 13:32:53 -080072import libcore.util.EmptyArray;
73
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010074import org.xmlpull.v1.XmlPullParserException;
75
76import java.io.File;
77import java.io.FileDescriptor;
78import java.io.FileInputStream;
79import java.io.FileOutputStream;
80import java.io.IOException;
81import java.io.PrintWriter;
82import java.util.ArrayList;
Adam Lesinskid11c5512017-04-11 12:01:10 -070083import java.util.Arrays;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010084import java.util.Collections;
85import java.util.HashMap;
86import java.util.List;
87import java.util.Map;
88import java.util.concurrent.atomic.AtomicBoolean;
89
90/**
91 * Service to manage asset overlays.
92 *
93 * <p>Asset overlays are additional resources that come from apks loaded
94 * alongside the system and app apks. This service, the OverlayManagerService
95 * (OMS), tracks which installed overlays to use and provides methods to change
96 * this. Changes propagate to running applications as part of the Activity
97 * lifecycle. This allows Activities to reread their resources at a well
98 * defined point.</p>
99 *
100 * <p>By itself, the OMS will not change what overlays should be active.
101 * Instead, it is only responsible for making sure that overlays *can* be used
102 * from a technical and security point of view and to activate overlays in
103 * response to external requests. The responsibility to toggle overlays on and
104 * off lies within components that implement different use-cases such as themes
105 * or dynamic customization.</p>
106 *
107 * <p>The OMS receives input from three sources:</p>
108 *
109 * <ul>
110 * <li>Callbacks from the SystemService class, specifically when the
111 * Android framework is booting and when the end user switches Android
112 * users.</li>
113 *
114 * <li>Intents from the PackageManagerService (PMS). Overlays are regular
115 * apks, and whenever a package is installed (or removed, or has a
116 * component enabled or disabled), the PMS broadcasts this as an intent.
117 * When the OMS receives one of these intents, it updates its internal
118 * representation of the available overlays and, if there was a visible
119 * change, triggers an asset refresh in the affected apps.</li>
120 *
121 * <li>External requests via the {@link IOverlayManager AIDL interface}.
122 * The interface allows clients to read information about the currently
123 * available overlays, change whether an overlay should be used or not, and
124 * change the relative order in which overlay packages are loaded.
125 * Read-access is granted if the request targets the same Android user as
126 * the caller runs as, or if the caller holds the
127 * INTERACT_ACROSS_USERS_FULL permission. Write-access is granted if the
128 * caller is granted read-access and additionaly holds the
129 * CHANGE_OVERLAY_PACKAGES permission.</li>
130 * </ul>
131 *
132 * <p>The AIDL interface works with String package names, int user IDs, and
133 * {@link OverlayInfo} objects. OverlayInfo instances are used to track a
134 * specific pair of target and overlay packages and include information such as
135 * the current state of the overlay. OverlayInfo objects are immutable.</p>
136 *
137 * <p>Internally, OverlayInfo objects are maintained by the
138 * OverlayManagerSettings class. The OMS and its helper classes are notified of
139 * changes to the settings by the OverlayManagerSettings.ChangeListener
140 * callback interface. The file /data/system/overlays.xml is used to persist
141 * the settings.</p>
142 *
143 * <p>Creation and deletion of idmap files are handled by the IdmapManager
144 * class.</p>
145 *
146 * <p>The following is an overview of OMS and its related classes. Note how box
147 * (2) does the heavy lifting, box (1) interacts with the Android framework,
148 * and box (3) replaces box (1) during unit testing.</p>
149 *
150 * <pre>
151 * Android framework
152 * | ^
153 * . . . | . . . . | . . . .
154 * . | | .
155 * . AIDL, broadcasts .
156 * . intents | .
157 * . | | . . . . . . . . . . . .
158 * . v | . .
159 * . OverlayManagerService . OverlayManagerTests .
160 * . \ . / .
161 * . (1) \ . / (3) .
162 * . . . . . . . . . . \ . . . / . . . . . . . . .
163 * . \ / .
164 * . (2) \ / .
165 * . OverlayManagerServiceImpl .
166 * . | | .
167 * . | | .
168 * . OverlayManagerSettings IdmapManager .
169 * . .
170 * . . . . . . . . . . . . . . . . . . . . . .
171 * </pre>
172 *
Mårten Kongstad1370c052018-05-03 10:48:35 +0200173 * <p>To test the OMS, execute:
174 * <code>
175 * atest FrameworksServicesTests:com.android.server.om # internal tests
176 * atest OverlayDeviceTests OverlayHostTests # public API tests
177 * </code>
178 * </p>
179 *
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100180 * <p>Finally, here is a list of keywords used in the OMS context.</p>
181 *
182 * <ul>
183 * <li><b>target [package]</b> -- A regular apk that may have its resource
184 * pool extended by zero or more overlay packages.</li>
185 *
186 * <li><b>overlay [package]</b> -- An apk that provides additional
187 * resources to another apk.</li>
188 *
189 * <li><b>OMS</b> -- The OverlayManagerService, i.e. this class.</li>
190 *
191 * <li><b>approved</b> -- An overlay is approved if the OMS has verified
192 * that it can be used technically speaking (its target package is
193 * installed, at least one resource name in both packages match, the
194 * idmap was created, etc) and that it is secure to do so. External
195 * clients can not change this state.</li>
196 *
197 * <li><b>not approved</b> -- The opposite of approved.</li>
198 *
199 * <li><b>enabled</b> -- An overlay currently in active use and thus part
200 * of resource lookups. This requires the overlay to be approved. Only
201 * external clients can change this state.</li>
202 *
203 * <li><b>disabled</b> -- The opposite of enabled.</li>
204 *
205 * <li><b>idmap</b> -- A mapping of resource IDs between target and overlay
206 * used during resource lookup. Also the name of the binary that creates
207 * the mapping.</li>
208 * </ul>
209 */
210public final class OverlayManagerService extends SystemService {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100211 static final String TAG = "OverlayManager";
212
213 static final boolean DEBUG = false;
214
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800215 /**
216 * The system property that specifies the default overlays to apply.
217 * This is a semicolon separated list of package names.
218 *
219 * Ex: com.android.vendor.overlay_one;com.android.vendor.overlay_two
220 */
221 private static final String DEFAULT_OVERLAYS_PROP = "ro.boot.vendor.overlay.theme";
222
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100223 private final Object mLock = new Object();
224
225 private final AtomicFile mSettingsFile;
226
227 private final PackageManagerHelper mPackageManager;
228
229 private final UserManagerService mUserManager;
230
231 private final OverlayManagerSettings mSettings;
232
233 private final OverlayManagerServiceImpl mImpl;
234
Winsond9d17362019-10-02 12:41:29 -0700235 private final OverlayActorEnforcer mActorEnforcer;
236
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100237 private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
238
Mårten Kongstad77b53b22019-10-01 08:29:21 +0200239 public OverlayManagerService(@NonNull final Context context) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100240 super(context);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100241 try {
242 traceBegin(TRACE_TAG_RRO, "OMS#OverlayManagerService");
243 mSettingsFile = new AtomicFile(
244 new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
Winsond9d17362019-10-02 12:41:29 -0700245 mPackageManager = new PackageManagerHelper(context);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100246 mUserManager = UserManagerService.getInstance();
Mårten Kongstad77b53b22019-10-01 08:29:21 +0200247 IdmapManager im = new IdmapManager(mPackageManager);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100248 mSettings = new OverlayManagerSettings();
249 mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
250 getDefaultOverlayPackages(), new OverlayChangeListener());
Winsond9d17362019-10-02 12:41:29 -0700251 mActorEnforcer = new OverlayActorEnforcer(mPackageManager);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100252
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100253 final IntentFilter packageFilter = new IntentFilter();
254 packageFilter.addAction(ACTION_PACKAGE_ADDED);
255 packageFilter.addAction(ACTION_PACKAGE_CHANGED);
256 packageFilter.addAction(ACTION_PACKAGE_REMOVED);
257 packageFilter.addDataScheme("package");
258 getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
259 packageFilter, null, null);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100260
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100261 final IntentFilter userFilter = new IntentFilter();
262 userFilter.addAction(ACTION_USER_ADDED);
263 userFilter.addAction(ACTION_USER_REMOVED);
264 getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
265 userFilter, null, null);
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700266
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100267 restoreSettings();
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100268
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100269 initIfNeeded();
270 onSwitchUser(UserHandle.USER_SYSTEM);
Mårten Kongstadcd78e0f2018-05-23 10:41:35 +0200271
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100272 publishBinderService(Context.OVERLAY_SERVICE, mService);
273 publishLocalService(OverlayManagerService.class, this);
274 } finally {
275 traceEnd(TRACE_TAG_RRO);
276 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100277 }
278
279 @Override
280 public void onStart() {
281 // Intentionally left empty.
282 }
283
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700284 private void initIfNeeded() {
285 final UserManager um = getContext().getSystemService(UserManager.class);
286 final List<UserInfo> users = um.getUsers(true /*excludeDying*/);
287 synchronized (mLock) {
288 final int userCount = users.size();
289 for (int i = 0; i < userCount; i++) {
290 final UserInfo userInfo = users.get(i);
291 if (!userInfo.supportsSwitchTo() && userInfo.id != UserHandle.USER_SYSTEM) {
292 // Initialize any users that can't be switched to, as there state would
293 // never be setup in onSwitchUser(). We will switch to the system user right
294 // after this, and its state will be setup there.
295 final List<String> targets = mImpl.updateOverlaysForUser(users.get(i).id);
296 updateOverlayPaths(users.get(i).id, targets);
297 }
298 }
299 }
300 }
301
Fyodor Kupolov94ab1a62017-03-06 14:28:20 -0800302 @Override
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100303 public void onSwitchUser(final int newUserId) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100304 try {
305 traceBegin(TRACE_TAG_RRO, "OMS#onSwitchUser " + newUserId);
306 // ensure overlays in the settings are up-to-date, and propagate
307 // any asset changes to the rest of the system
308 synchronized (mLock) {
309 final List<String> targets = mImpl.updateOverlaysForUser(newUserId);
310 updateAssets(newUserId, targets);
311 }
312 schedulePersistSettings();
313 } finally {
314 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100315 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100316 }
317
Adam Lesinski7b031812018-02-22 13:32:53 -0800318 private static String[] getDefaultOverlayPackages() {
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800319 final String str = SystemProperties.get(DEFAULT_OVERLAYS_PROP);
320 if (TextUtils.isEmpty(str)) {
Adam Lesinski7b031812018-02-22 13:32:53 -0800321 return EmptyArray.STRING;
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800322 }
323
324 final ArraySet<String> defaultPackages = new ArraySet<>();
325 for (String packageName : str.split(";")) {
326 if (!TextUtils.isEmpty(packageName)) {
327 defaultPackages.add(packageName);
328 }
329 }
Adam Lesinski7b031812018-02-22 13:32:53 -0800330 return defaultPackages.toArray(new String[defaultPackages.size()]);
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800331 }
332
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100333 private final class PackageReceiver extends BroadcastReceiver {
334 @Override
335 public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
Youngha Park14d8d682018-08-02 15:43:38 +0900336 final String action = intent.getAction();
337 if (action == null) {
338 Slog.e(TAG, "Cannot handle package broadcast with null action");
339 return;
340 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100341 final Uri data = intent.getData();
342 if (data == null) {
343 Slog.e(TAG, "Cannot handle package broadcast with null data");
344 return;
345 }
346 final String packageName = data.getSchemeSpecificPart();
347
348 final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
349
350 final int[] userIds;
351 final int extraUid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL);
352 if (extraUid == UserHandle.USER_NULL) {
353 userIds = mUserManager.getUserIds();
354 } else {
355 userIds = new int[] { UserHandle.getUserId(extraUid) };
356 }
357
Youngha Park14d8d682018-08-02 15:43:38 +0900358 switch (action) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100359 case ACTION_PACKAGE_ADDED:
360 if (replacing) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100361 onPackageReplaced(packageName, userIds);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100362 } else {
363 onPackageAdded(packageName, userIds);
364 }
365 break;
366 case ACTION_PACKAGE_CHANGED:
Mårten Kongstad6d18d772019-10-04 10:50:10 +0200367 // ignore the intent if it was sent by the package manager as a result of the
368 // overlay manager having sent ACTION_OVERLAY_CHANGED
369 if (!ACTION_OVERLAY_CHANGED.equals(intent.getStringExtra(EXTRA_REASON))) {
370 onPackageChanged(packageName, userIds);
371 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100372 break;
373 case ACTION_PACKAGE_REMOVED:
374 if (replacing) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100375 onPackageReplacing(packageName, userIds);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100376 } else {
377 onPackageRemoved(packageName, userIds);
378 }
379 break;
380 default:
381 // do nothing
382 break;
383 }
384 }
385
386 private void onPackageAdded(@NonNull final String packageName,
387 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100388 try {
389 traceBegin(TRACE_TAG_RRO, "OMS#onPackageAdded " + packageName);
390 for (final int userId : userIds) {
391 synchronized (mLock) {
392 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
393 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100394 if (pi != null && !pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100395 mPackageManager.cachePackageInfo(packageName, userId, pi);
396 if (pi.isOverlayPackage()) {
397 mImpl.onOverlayPackageAdded(packageName, userId);
398 } else {
399 mImpl.onTargetPackageAdded(packageName, userId);
400 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100401 }
402 }
403 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100404 } finally {
405 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100406 }
407 }
408
409 private void onPackageChanged(@NonNull final String packageName,
410 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100411 try {
412 traceBegin(TRACE_TAG_RRO, "OMS#onPackageChanged " + packageName);
413 for (int userId : userIds) {
414 synchronized (mLock) {
415 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
416 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100417 if (pi != null && pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100418 mPackageManager.cachePackageInfo(packageName, userId, pi);
419 if (pi.isOverlayPackage()) {
420 mImpl.onOverlayPackageChanged(packageName, userId);
421 } else {
422 mImpl.onTargetPackageChanged(packageName, userId);
423 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100424 }
425 }
426 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100427 } finally {
428 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100429 }
430 }
431
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100432 private void onPackageReplacing(@NonNull final String packageName,
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100433 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100434 try {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100435 traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplacing " + packageName);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100436 for (int userId : userIds) {
437 synchronized (mLock) {
438 mPackageManager.forgetPackageInfo(packageName, userId);
439 final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
440 if (oi != null) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100441 mImpl.onOverlayPackageReplacing(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100442 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100443 }
444 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100445 } finally {
446 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100447 }
448 }
449
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100450 private void onPackageReplaced(@NonNull final String packageName,
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100451 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100452 try {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100453 traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplaced " + packageName);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100454 for (int userId : userIds) {
455 synchronized (mLock) {
456 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
457 false);
Mårten Kongstadad32ba92019-03-26 16:05:23 +0100458 if (pi != null && !pi.applicationInfo.isInstantApp()) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100459 mPackageManager.cachePackageInfo(packageName, userId, pi);
460 if (pi.isOverlayPackage()) {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100461 mImpl.onOverlayPackageReplaced(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100462 } else {
Mårten Kongstad15a0ac02019-03-26 10:30:08 +0100463 mImpl.onTargetPackageReplaced(packageName, userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100464 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100465 }
466 }
467 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100468 } finally {
469 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100470 }
471 }
472
473 private void onPackageRemoved(@NonNull final String packageName,
474 @NonNull final int[] userIds) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100475 try {
476 traceBegin(TRACE_TAG_RRO, "OMS#onPackageRemoved " + packageName);
477 for (int userId : userIds) {
478 synchronized (mLock) {
479 mPackageManager.forgetPackageInfo(packageName, userId);
480 final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
481 if (oi != null) {
482 mImpl.onOverlayPackageRemoved(packageName, userId);
483 } else {
484 mImpl.onTargetPackageRemoved(packageName, userId);
485 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100486 }
487 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100488 } finally {
489 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100490 }
491 }
492 }
493
494 private final class UserReceiver extends BroadcastReceiver {
495 @Override
496 public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700497 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100498 switch (intent.getAction()) {
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700499 case ACTION_USER_ADDED:
500 if (userId != UserHandle.USER_NULL) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100501 try {
502 traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_ADDED");
503 final ArrayList<String> targets;
504 synchronized (mLock) {
505 targets = mImpl.updateOverlaysForUser(userId);
506 }
507 updateOverlayPaths(userId, targets);
508 } finally {
509 traceEnd(TRACE_TAG_RRO);
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700510 }
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700511 }
512 break;
513
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100514 case ACTION_USER_REMOVED:
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100515 if (userId != UserHandle.USER_NULL) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100516 try {
517 traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_REMOVED");
518 synchronized (mLock) {
519 mImpl.onUserRemoved(userId);
520 mPackageManager.forgetAllPackageInfos(userId);
521 }
522 } finally {
523 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100524 }
525 }
526 break;
527 default:
528 // do nothing
529 break;
530 }
531 }
532 }
533
534 private final IBinder mService = new IOverlayManager.Stub() {
535 @Override
Adam Lesinskic745f422017-04-05 16:31:30 -0700536 public Map<String, List<OverlayInfo>> getAllOverlays(int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100537 try {
538 traceBegin(TRACE_TAG_RRO, "OMS#getAllOverlays " + userId);
539 userId = handleIncomingUser(userId, "getAllOverlays");
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100540
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100541 synchronized (mLock) {
542 return mImpl.getOverlaysForUser(userId);
543 }
544 } finally {
545 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100546 }
547 }
548
549 @Override
550 public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName,
551 int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100552 try {
553 traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfosForTarget " + targetPackageName);
554 userId = handleIncomingUser(userId, "getOverlayInfosForTarget");
555 if (targetPackageName == null) {
556 return Collections.emptyList();
557 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100558
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100559 synchronized (mLock) {
560 return mImpl.getOverlayInfosForTarget(targetPackageName, userId);
561 }
562 } finally {
563 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100564 }
565 }
566
567 @Override
568 public OverlayInfo getOverlayInfo(@Nullable final String packageName,
569 int userId) throws RemoteException {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100570 try {
571 traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfo " + packageName);
572 userId = handleIncomingUser(userId, "getOverlayInfo");
573 if (packageName == null) {
574 return null;
575 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100576
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100577 synchronized (mLock) {
578 return mImpl.getOverlayInfo(packageName, userId);
579 }
580 } finally {
581 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100582 }
583 }
584
585 @Override
586 public boolean setEnabled(@Nullable final String packageName, final boolean enable,
587 int userId) throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100588 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100589 traceBegin(TRACE_TAG_RRO, "OMS#setEnabled " + packageName + " " + enable);
Winsond9d17362019-10-02 12:41:29 -0700590 enforceActor(packageName, "setEnabled", userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100591 userId = handleIncomingUser(userId, "setEnabled");
592 if (packageName == null) {
593 return false;
594 }
595
596 final long ident = Binder.clearCallingIdentity();
597 try {
598 synchronized (mLock) {
599 return mImpl.setEnabled(packageName, enable, userId);
600 }
601 } finally {
602 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100603 }
604 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100605 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100606 }
607 }
608
609 @Override
Jason Monk929ed8d2017-03-07 16:01:20 -0500610 public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable,
611 int userId) throws RemoteException {
Jason Monk929ed8d2017-03-07 16:01:20 -0500612 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100613 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusive " + packageName + " " + enable);
Winsond9d17362019-10-02 12:41:29 -0700614 enforceActor(packageName, "setEnabledExclusive", userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100615 userId = handleIncomingUser(userId, "setEnabledExclusive");
616 if (packageName == null || !enable) {
617 return false;
618 }
619
620 final long ident = Binder.clearCallingIdentity();
621 try {
622 synchronized (mLock) {
623 return mImpl.setEnabledExclusive(packageName, false /* withinCategory */,
624 userId);
625 }
626 } finally {
627 Binder.restoreCallingIdentity(ident);
Adrian Roosc84df772018-01-19 21:20:22 +0100628 }
629 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100630 traceEnd(TRACE_TAG_RRO);
Adrian Roosc84df772018-01-19 21:20:22 +0100631 }
632 }
633
634 @Override
635 public boolean setEnabledExclusiveInCategory(@Nullable String packageName, int userId)
636 throws RemoteException {
Adrian Roosc84df772018-01-19 21:20:22 +0100637 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100638 traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusiveInCategory " + packageName);
Winsond9d17362019-10-02 12:41:29 -0700639 enforceActor(packageName, "setEnabledExclusiveInCategory", userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100640 userId = handleIncomingUser(userId, "setEnabledExclusiveInCategory");
641 if (packageName == null) {
642 return false;
643 }
644
645 final long ident = Binder.clearCallingIdentity();
646 try {
647 synchronized (mLock) {
648 return mImpl.setEnabledExclusive(packageName, true /* withinCategory */,
649 userId);
650 }
651 } finally {
652 Binder.restoreCallingIdentity(ident);
Jason Monk929ed8d2017-03-07 16:01:20 -0500653 }
654 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100655 traceEnd(TRACE_TAG_RRO);
Jason Monk929ed8d2017-03-07 16:01:20 -0500656 }
657 }
658
659 @Override
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100660 public boolean setPriority(@Nullable final String packageName,
661 @Nullable final String parentPackageName, int userId) throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100662 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100663 traceBegin(TRACE_TAG_RRO, "OMS#setPriority " + packageName + " "
664 + parentPackageName);
Winsond9d17362019-10-02 12:41:29 -0700665 enforceActor(packageName, "setPriority", userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100666 userId = handleIncomingUser(userId, "setPriority");
667 if (packageName == null || parentPackageName == null) {
668 return false;
669 }
670
671 final long ident = Binder.clearCallingIdentity();
672 try {
673 synchronized (mLock) {
674 return mImpl.setPriority(packageName, parentPackageName, userId);
675 }
676 } finally {
677 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100678 }
679 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100680 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100681 }
682 }
683
684 @Override
685 public boolean setHighestPriority(@Nullable final String packageName, int userId)
686 throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100687 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100688 traceBegin(TRACE_TAG_RRO, "OMS#setHighestPriority " + packageName);
Winsond9d17362019-10-02 12:41:29 -0700689 enforceActor(packageName, "setHighestPriority", userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100690 userId = handleIncomingUser(userId, "setHighestPriority");
691 if (packageName == null) {
692 return false;
693 }
694
695 final long ident = Binder.clearCallingIdentity();
696 try {
697 synchronized (mLock) {
698 return mImpl.setHighestPriority(packageName, userId);
699 }
700 } finally {
701 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100702 }
703 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100704 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100705 }
706 }
707
708 @Override
709 public boolean setLowestPriority(@Nullable final String packageName, int userId)
710 throws RemoteException {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100711 try {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100712 traceBegin(TRACE_TAG_RRO, "OMS#setLowestPriority " + packageName);
Winsond9d17362019-10-02 12:41:29 -0700713 enforceActor(packageName, "setLowestPriority", userId);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100714 userId = handleIncomingUser(userId, "setLowestPriority");
715 if (packageName == null) {
716 return false;
717 }
718
719 final long ident = Binder.clearCallingIdentity();
720 try {
721 synchronized (mLock) {
722 return mImpl.setLowestPriority(packageName, userId);
723 }
724 } finally {
725 Binder.restoreCallingIdentity(ident);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100726 }
727 } finally {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100728 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100729 }
730 }
731
732 @Override
Winson Chung43f311e2019-04-29 12:57:21 -0700733 public String[] getDefaultOverlayPackages() throws RemoteException {
734 try {
735 traceBegin(TRACE_TAG_RRO, "OMS#getDefaultOverlayPackages");
736 getContext().enforceCallingOrSelfPermission(
737 android.Manifest.permission.MODIFY_THEME_OVERLAY, null);
738
739 final long ident = Binder.clearCallingIdentity();
740 try {
741 synchronized (mLock) {
742 return mImpl.getDefaultOverlayPackages();
743 }
744 } finally {
745 Binder.restoreCallingIdentity(ident);
746 }
747 } finally {
748 traceEnd(TRACE_TAG_RRO);
749 }
750 }
751
752 @Override
Ryan Mitchell4043ca72019-06-03 16:11:24 -0700753 public void invalidateCachesForOverlay(@Nullable String packageName, int userId)
754 throws RemoteException {
755 if (packageName == null) {
756 return;
757 }
758
Winsond9d17362019-10-02 12:41:29 -0700759 enforceActor(packageName, "invalidateCachesForOverlay", userId);
Ryan Mitchell4043ca72019-06-03 16:11:24 -0700760 userId = handleIncomingUser(userId, "invalidateCachesForOverlay");
761 final long ident = Binder.clearCallingIdentity();
762 try {
763 synchronized (mLock) {
764 mImpl.removeIdmapForOverlay(packageName, userId);
765 }
766 } finally {
767 Binder.restoreCallingIdentity(ident);
768 }
769 }
770
771 @Override
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100772 public void onShellCommand(@NonNull final FileDescriptor in,
773 @NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
774 @NonNull final String[] args, @NonNull final ShellCallback callback,
775 @NonNull final ResultReceiver resultReceiver) {
Mårten Kongstad4ea02d12019-06-14 14:08:18 +0200776 (new OverlayManagerShellCommand(getContext(), this)).exec(
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100777 this, in, out, err, args, callback, resultReceiver);
778 }
779
780 @Override
Mårten Kongstada465aec2019-04-12 12:32:41 +0200781 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
782 final DumpState dumpState = new DumpState();
Ryan Mitchellb7ef06a2019-07-17 17:16:23 -0700783 dumpState.setUserId(UserHandle.USER_ALL);
Mårten Kongstada465aec2019-04-12 12:32:41 +0200784
785 int opti = 0;
786 while (opti < args.length) {
787 final String opt = args[opti];
788 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
789 break;
790 }
791 opti++;
792
793 if ("-h".equals(opt)) {
794 pw.println("dump [-h] [--verbose] [--user USER_ID] [[FIELD] PACKAGE]");
795 pw.println(" Print debugging information about the overlay manager.");
796 pw.println(" With optional parameter PACKAGE, limit output to the specified");
797 pw.println(" package. With optional parameter FIELD, limit output to");
798 pw.println(" the value of that SettingsItem field. Field names are");
799 pw.println(" case insensitive and out.println the m prefix can be omitted,");
800 pw.println(" so the following are equivalent: mState, mstate, State, state.");
801 return;
802 } else if ("--user".equals(opt)) {
Mårten Kongstada465aec2019-04-12 12:32:41 +0200803 if (opti >= args.length) {
804 pw.println("Error: user missing argument");
805 return;
806 }
807 try {
808 dumpState.setUserId(Integer.parseInt(args[opti]));
Ryan Mitchellb7ef06a2019-07-17 17:16:23 -0700809 opti++;
Mårten Kongstada465aec2019-04-12 12:32:41 +0200810 } catch (NumberFormatException e) {
811 pw.println("Error: user argument is not a number: " + args[opti]);
812 return;
813 }
814 } else if ("--verbose".equals(opt)) {
815 dumpState.setVerbose(true);
816 } else {
817 pw.println("Unknown argument: " + opt + "; use -h for help");
818 }
819 }
820 if (opti < args.length) {
821 final String arg = args[opti];
822 opti++;
823 switch (arg) {
824 case "packagename":
825 case "userid":
826 case "targetpackagename":
827 case "targetoverlayablename":
828 case "basecodepath":
829 case "state":
830 case "isenabled":
831 case "isstatic":
832 case "priority":
833 case "category":
834 dumpState.setField(arg);
835 break;
836 default:
837 dumpState.setPackageName(arg);
838 break;
839 }
840 }
841 if (dumpState.getPackageName() == null && opti < args.length) {
842 dumpState.setPackageName(args[opti]);
843 opti++;
844 }
845
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100846 enforceDumpPermission("dump");
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100847 synchronized (mLock) {
Mårten Kongstada465aec2019-04-12 12:32:41 +0200848 mImpl.dump(pw, dumpState);
849 if (dumpState.getPackageName() == null) {
850 mPackageManager.dump(pw, dumpState);
851 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100852 }
853 }
854
855 /**
856 * Ensure that the caller has permission to interact with the given userId.
857 * If the calling user is not the same as the provided user, the caller needs
858 * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or
859 * root).
860 *
861 * @param userId the user to interact with
862 * @param message message for any SecurityException
863 */
864 private int handleIncomingUser(final int userId, @NonNull final String message) {
865 return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
866 Binder.getCallingUid(), userId, false, true, message, null);
867 }
868
869 /**
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100870 * Enforce that the caller holds the DUMP permission (or is system or root).
871 *
872 * @param message used as message if SecurityException is thrown
873 * @throws SecurityException if the permission check fails
874 */
875 private void enforceDumpPermission(@NonNull final String message) {
Winson Chungddaf3512019-03-18 13:02:44 -0700876 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, message);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100877 }
Winsond9d17362019-10-02 12:41:29 -0700878
879 private void enforceActor(String packageName, String methodName, int userId)
880 throws SecurityException {
881 OverlayInfo overlayInfo = mImpl.getOverlayInfo(packageName, userId);
882 int callingUid = Binder.getCallingUid();
883 mActorEnforcer.enforceActor(overlayInfo, methodName, callingUid, userId);
884 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100885 };
886
Adam Lesinskic745f422017-04-05 16:31:30 -0700887 private final class OverlayChangeListener
888 implements OverlayManagerServiceImpl.OverlayChangeListener {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100889 @Override
Mårten Kongstad497945c2018-04-27 09:56:13 +0200890 public void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100891 schedulePersistSettings();
Adam Lesinskic745f422017-04-05 16:31:30 -0700892 FgThread.getHandler().post(() -> {
Mårten Kongstad497945c2018-04-27 09:56:13 +0200893 updateAssets(userId, targetPackageName);
894
Mårten Kongstad6d18d772019-10-04 10:50:10 +0200895 final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
Mårten Kongstad497945c2018-04-27 09:56:13 +0200896 Uri.fromParts("package", targetPackageName, null));
897 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
898
899 if (DEBUG) {
900 Slog.d(TAG, "send broadcast " + intent);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100901 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700902
Mårten Kongstad497945c2018-04-27 09:56:13 +0200903 try {
904 ActivityManager.getService().broadcastIntent(null, intent, null, null, 0,
905 null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false,
906 userId);
907 } catch (RemoteException e) {
908 // Intentionally left empty.
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100909 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700910 });
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100911 }
912 }
913
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700914 /**
915 * Updates the target packages' set of enabled overlays in PackageManager.
916 */
917 private void updateOverlayPaths(int userId, List<String> targetPackageNames) {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100918 try {
919 traceBegin(TRACE_TAG_RRO, "OMS#updateOverlayPaths " + targetPackageNames);
920 if (DEBUG) {
921 Slog.d(TAG, "Updating overlay assets");
922 }
923 final PackageManagerInternal pm =
924 LocalServices.getService(PackageManagerInternal.class);
925 final boolean updateFrameworkRes = targetPackageNames.contains("android");
926 if (updateFrameworkRes) {
927 targetPackageNames = pm.getTargetPackageNames(userId);
928 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200929
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100930 final Map<String, List<String>> pendingChanges =
931 new ArrayMap<>(targetPackageNames.size());
932 synchronized (mLock) {
933 final List<String> frameworkOverlays =
934 mImpl.getEnabledOverlayPackageNames("android", userId);
935 final int n = targetPackageNames.size();
936 for (int i = 0; i < n; i++) {
937 final String targetPackageName = targetPackageNames.get(i);
938 List<String> list = new ArrayList<>();
939 if (!"android".equals(targetPackageName)) {
940 list.addAll(frameworkOverlays);
941 }
942 list.addAll(mImpl.getEnabledOverlayPackageNames(targetPackageName, userId));
943 pendingChanges.put(targetPackageName, list);
944 }
945 }
946
Mårten Kongstad38988342018-12-04 10:28:01 +0100947 final int n = targetPackageNames.size();
948 for (int i = 0; i < n; i++) {
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200949 final String targetPackageName = targetPackageNames.get(i);
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100950 if (DEBUG) {
951 Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=["
952 + TextUtils.join(",", pendingChanges.get(targetPackageName))
953 + "] userId=" + userId);
Todd Kennedy560830c2017-06-16 13:55:13 -0700954 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200955
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100956 if (!pm.setEnabledOverlayPackages(
957 userId, targetPackageName, pendingChanges.get(targetPackageName))) {
958 Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d",
959 targetPackageName, userId));
960 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700961 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +0100962 } finally {
963 traceEnd(TRACE_TAG_RRO);
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200964 }
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700965 }
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200966
Adam Lesinskiada8deb2017-05-12 13:50:42 -0700967 private void updateAssets(final int userId, final String targetPackageName) {
968 updateAssets(userId, Collections.singletonList(targetPackageName));
969 }
970
971 private void updateAssets(final int userId, List<String> targetPackageNames) {
972 updateOverlayPaths(userId, targetPackageNames);
Mårten Kongstad2e0d0f32016-06-02 09:35:31 +0200973 final IActivityManager am = ActivityManager.getService();
974 try {
975 am.scheduleApplicationInfoChanged(targetPackageNames, userId);
976 } catch (RemoteException e) {
977 // Intentionally left empty.
978 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100979 }
980
981 private void schedulePersistSettings() {
982 if (mPersistSettingsScheduled.getAndSet(true)) {
983 return;
984 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700985 IoThread.getHandler().post(() -> {
986 mPersistSettingsScheduled.set(false);
987 if (DEBUG) {
988 Slog.d(TAG, "Writing overlay settings");
989 }
990 synchronized (mLock) {
991 FileOutputStream stream = null;
992 try {
993 stream = mSettingsFile.startWrite();
994 mSettings.persist(stream);
995 mSettingsFile.finishWrite(stream);
996 } catch (IOException | XmlPullParserException e) {
997 mSettingsFile.failWrite(stream);
998 Slog.e(TAG, "failed to persist overlay state", e);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100999 }
1000 }
1001 });
1002 }
1003
1004 private void restoreSettings() {
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001005 try {
1006 traceBegin(TRACE_TAG_RRO, "OMS#restoreSettings");
1007 synchronized (mLock) {
1008 if (!mSettingsFile.getBaseFile().exists()) {
1009 return;
Adam Lesinskid11c5512017-04-11 12:01:10 -07001010 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001011 try (FileInputStream stream = mSettingsFile.openRead()) {
1012 mSettings.restore(stream);
Adam Lesinskid11c5512017-04-11 12:01:10 -07001013
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001014 // We might have data for dying users if the device was
1015 // restarted before we received USER_REMOVED. Remove data for
1016 // users that will not exist after the system is ready.
1017
1018 final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/);
1019 final int[] liveUserIds = new int[liveUsers.size()];
1020 for (int i = 0; i < liveUsers.size(); i++) {
1021 liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier();
Adam Lesinskid11c5512017-04-11 12:01:10 -07001022 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001023 Arrays.sort(liveUserIds);
1024
1025 for (int userId : mSettings.getUsers()) {
1026 if (Arrays.binarySearch(liveUserIds, userId) < 0) {
1027 mSettings.removeUser(userId);
1028 }
1029 }
1030 } catch (IOException | XmlPullParserException e) {
1031 Slog.e(TAG, "failed to restore overlay state", e);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001032 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001033 }
Mårten Kongstadacfcdc72018-12-03 14:59:51 +01001034 } finally {
1035 traceEnd(TRACE_TAG_RRO);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001036 }
1037 }
1038
Winsond9d17362019-10-02 12:41:29 -07001039 /**
1040 * Delegate for {@link android.content.pm.PackageManager} and {@link PackageManagerInternal}
1041 * functionality, separated for easy testing.
1042 *
1043 * @hide
1044 */
1045 public static final class PackageManagerHelper implements
1046 OverlayManagerServiceImpl.PackageManagerHelper, OverlayActorEnforcer.VerifyCallback {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001047
Winsond9d17362019-10-02 12:41:29 -07001048 private final Context mContext;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001049 private final IPackageManager mPackageManager;
1050 private final PackageManagerInternal mPackageManagerInternal;
1051
1052 // Use a cache for performance and for consistency within OMS: because
1053 // additional PACKAGE_* intents may be delivered while we process an
1054 // intent, querying the PackageManagerService for the actual current
1055 // state may lead to contradictions within OMS. Better then to lag
1056 // behind until all pending intents have been processed.
1057 private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>();
1058
Winsond9d17362019-10-02 12:41:29 -07001059 PackageManagerHelper(Context context) {
1060 mContext = context;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001061 mPackageManager = getPackageManager();
1062 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
1063 }
1064
Winsond9d17362019-10-02 12:41:29 -07001065 // TODO(b/143096091): Remove PackageInfo cache so that PackageManager is always queried
1066 // to enforce visibility/other permission checks
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001067 public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId,
1068 final boolean useCache) {
1069 if (useCache) {
1070 final PackageInfo cachedPi = getCachedPackageInfo(packageName, userId);
1071 if (cachedPi != null) {
1072 return cachedPi;
1073 }
1074 }
1075 try {
1076 final PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0, userId);
1077 if (useCache && pi != null) {
1078 cachePackageInfo(packageName, userId, pi);
1079 }
1080 return pi;
1081 } catch (RemoteException e) {
1082 // Intentionally left empty.
1083 }
1084 return null;
1085 }
1086
1087 @Override
1088 public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId) {
Winsond9d17362019-10-02 12:41:29 -07001089 // TODO(b/143096091): Remove clearing calling ID
1090 long callingIdentity = Binder.clearCallingIdentity();
1091 try {
1092 return getPackageInfo(packageName, userId, true);
1093 } finally {
1094 Binder.restoreCallingIdentity(callingIdentity);
1095 }
1096 }
1097
1098 @NonNull
1099 @Override
1100 public Map<String, ? extends Map<String, String>> getNamedActors() {
1101 return SystemConfig.getInstance().getNamedActors();
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001102 }
1103
1104 @Override
1105 public boolean signaturesMatching(@NonNull final String packageName1,
1106 @NonNull final String packageName2, final int userId) {
1107 // The package manager does not support different versions of packages
1108 // to be installed for different users: ignore userId for now.
1109 try {
Adam Lesinskic745f422017-04-05 16:31:30 -07001110 return mPackageManager.checkSignatures(
1111 packageName1, packageName2) == SIGNATURE_MATCH;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001112 } catch (RemoteException e) {
1113 // Intentionally left blank
1114 }
1115 return false;
1116 }
1117
1118 @Override
1119 public List<PackageInfo> getOverlayPackages(final int userId) {
1120 return mPackageManagerInternal.getOverlayPackages(userId);
1121 }
1122
Winsond9d17362019-10-02 12:41:29 -07001123 @Nullable
1124 @Override
1125 public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
1126 @Nullable String targetOverlayableName, int userId)
1127 throws IOException {
1128 // TODO(b/143096091): Remove clearing calling ID
1129 long callingIdentity = Binder.clearCallingIdentity();
1130 try {
1131 PackageInfo packageInfo = getPackageInfo(packageName, userId);
1132 if (packageInfo == null) {
1133 throw new IOException("Unable to get target package");
1134 }
1135
1136 String baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
1137
1138 ApkAssets apkAssets = null;
1139 try {
1140 apkAssets = ApkAssets.loadFromPath(baseCodePath);
1141 return apkAssets.getOverlayableInfo(targetOverlayableName);
1142 } finally {
1143 if (apkAssets != null) {
1144 try {
1145 apkAssets.close();
1146 } catch (Throwable ignored) {
1147 }
1148 }
1149 }
1150 } finally {
1151 Binder.restoreCallingIdentity(callingIdentity);
1152 }
1153 }
1154
1155 @Override
1156 public boolean doesTargetDefineOverlayable(String targetPackageName, int userId)
1157 throws RemoteException, IOException {
1158 // TODO(b/143096091): Remove clearing calling ID
1159 long callingIdentity = Binder.clearCallingIdentity();
1160 try {
1161 PackageInfo packageInfo = mPackageManager.getPackageInfo(targetPackageName, 0,
1162 userId);
1163 String baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
1164
1165 ApkAssets apkAssets = null;
1166 try {
1167 apkAssets = ApkAssets.loadFromPath(baseCodePath);
1168 return apkAssets.definesOverlayable();
1169 } finally {
1170 if (apkAssets != null) {
1171 try {
1172 apkAssets.close();
1173 } catch (Throwable ignored) {
1174 }
1175 }
1176 }
1177 } finally {
1178 Binder.restoreCallingIdentity(callingIdentity);
1179 }
1180 }
1181
1182 @Override
1183 public void enforcePermission(String permission, String message) throws SecurityException {
1184 mContext.enforceCallingOrSelfPermission(permission, message);
1185 }
1186
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001187 public PackageInfo getCachedPackageInfo(@NonNull final String packageName,
1188 final int userId) {
1189 final HashMap<String, PackageInfo> map = mCache.get(userId);
1190 return map == null ? null : map.get(packageName);
1191 }
1192
1193 public void cachePackageInfo(@NonNull final String packageName, final int userId,
1194 @NonNull final PackageInfo pi) {
1195 HashMap<String, PackageInfo> map = mCache.get(userId);
1196 if (map == null) {
1197 map = new HashMap<>();
1198 mCache.put(userId, map);
1199 }
1200 map.put(packageName, pi);
1201 }
1202
1203 public void forgetPackageInfo(@NonNull final String packageName, final int userId) {
1204 final HashMap<String, PackageInfo> map = mCache.get(userId);
1205 if (map == null) {
1206 return;
1207 }
1208 map.remove(packageName);
1209 if (map.isEmpty()) {
1210 mCache.delete(userId);
1211 }
1212 }
1213
1214 public void forgetAllPackageInfos(final int userId) {
1215 mCache.delete(userId);
1216 }
1217
Winsond9d17362019-10-02 12:41:29 -07001218 @Nullable
1219 @Override
1220 public String[] getPackagesForUid(int uid) {
1221 // TODO(b/143096091): Remove clearing calling ID
1222 long callingIdentity = Binder.clearCallingIdentity();
1223 try {
1224 try {
1225 return mPackageManager.getPackagesForUid(uid);
1226 } catch (RemoteException ignored) {
1227 return null;
1228 }
1229 } finally {
1230 Binder.restoreCallingIdentity(callingIdentity);
1231 }
1232 }
1233
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001234 private static final String TAB1 = " ";
1235 private static final String TAB2 = TAB1 + TAB1;
1236
Mårten Kongstada465aec2019-04-12 12:32:41 +02001237 public void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001238 pw.println("PackageInfo cache");
1239
Mårten Kongstada465aec2019-04-12 12:32:41 +02001240 if (!dumpState.isVerbose()) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001241 int count = 0;
Mårten Kongstad38988342018-12-04 10:28:01 +01001242 final int n = mCache.size();
1243 for (int i = 0; i < n; i++) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001244 final int userId = mCache.keyAt(i);
1245 count += mCache.get(userId).size();
1246 }
1247 pw.println(TAB1 + count + " package(s)");
1248 return;
1249 }
1250
1251 if (mCache.size() == 0) {
1252 pw.println(TAB1 + "<empty>");
1253 return;
1254 }
1255
Mårten Kongstad38988342018-12-04 10:28:01 +01001256 final int n = mCache.size();
1257 for (int i = 0; i < n; i++) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +01001258 final int userId = mCache.keyAt(i);
1259 pw.println(TAB1 + "User " + userId);
1260 final HashMap<String, PackageInfo> map = mCache.get(userId);
1261 for (Map.Entry<String, PackageInfo> entry : map.entrySet()) {
1262 pw.println(TAB2 + entry.getKey() + ": " + entry.getValue());
1263 }
1264 }
1265 }
1266 }
1267}