blob: 321af43d9c3d739977a1c7d3a6410ca9b253ca72 [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.content.om.OverlayInfo.STATE_DISABLED;
20import static android.content.om.OverlayInfo.STATE_ENABLED;
21import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
22import static android.content.om.OverlayInfo.STATE_NO_IDMAP;
23
24import static com.android.server.om.OverlayManagerService.DEBUG;
25import static com.android.server.om.OverlayManagerService.TAG;
26
27import android.annotation.NonNull;
28import android.annotation.Nullable;
29import android.content.om.OverlayInfo;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010030import android.content.pm.PackageInfo;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080031import android.text.TextUtils;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010032import android.util.ArrayMap;
33import android.util.ArraySet;
34import android.util.Slog;
35
36import java.io.PrintWriter;
37import java.util.ArrayList;
38import java.util.Iterator;
39import java.util.List;
40import java.util.Map;
41import java.util.Set;
42
43/**
44 * Internal implementation of OverlayManagerService.
45 *
46 * Methods in this class should only be called by the OverlayManagerService.
47 * This class is not thread-safe; the caller is expected to ensure the
48 * necessary thread synchronization.
49 *
50 * @see OverlayManagerService
51 */
52final class OverlayManagerServiceImpl {
53 private final PackageManagerHelper mPackageManager;
54 private final IdmapManager mIdmapManager;
55 private final OverlayManagerSettings mSettings;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080056 private final Set<String> mDefaultOverlays;
Adam Lesinskic745f422017-04-05 16:31:30 -070057 private final OverlayChangeListener mListener;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010058
59 OverlayManagerServiceImpl(@NonNull final PackageManagerHelper packageManager,
60 @NonNull final IdmapManager idmapManager,
Adam Lesinskia5ca6242017-03-01 15:45:12 -080061 @NonNull final OverlayManagerSettings settings,
Adam Lesinskic745f422017-04-05 16:31:30 -070062 @NonNull final Set<String> defaultOverlays,
63 @NonNull final OverlayChangeListener listener) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010064 mPackageManager = packageManager;
65 mIdmapManager = idmapManager;
66 mSettings = settings;
Adam Lesinskia5ca6242017-03-01 15:45:12 -080067 mDefaultOverlays = defaultOverlays;
Adam Lesinskic745f422017-04-05 16:31:30 -070068 mListener = listener;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010069 }
70
Adam Lesinskiada8deb2017-05-12 13:50:42 -070071 /**
72 * Call this to synchronize the Settings for a user with what PackageManager knows about a user.
73 * Returns a list of target packages that must refresh their overlays. This list is the union
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010074 * of two sets: the set of targets with currently active overlays, and the
75 * set of targets that had, but no longer have, active overlays.
76 */
Adam Lesinskiada8deb2017-05-12 13:50:42 -070077 ArrayList<String> updateOverlaysForUser(final int newUserId) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010078 if (DEBUG) {
Adam Lesinskiada8deb2017-05-12 13:50:42 -070079 Slog.d(TAG, "updateOverlaysForUser newUserId=" + newUserId);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +010080 }
81
82 final Set<String> packagesToUpdateAssets = new ArraySet<>();
83 final ArrayMap<String, List<OverlayInfo>> tmp = mSettings.getOverlaysForUser(newUserId);
84 final int tmpSize = tmp.size();
85 final ArrayMap<String, OverlayInfo> storedOverlayInfos = new ArrayMap<>(tmpSize);
86 for (int i = 0; i < tmpSize; i++) {
87 final List<OverlayInfo> chunk = tmp.valueAt(i);
88 final int chunkSize = chunk.size();
89 for (int j = 0; j < chunkSize; j++) {
90 final OverlayInfo oi = chunk.get(j);
91 storedOverlayInfos.put(oi.packageName, oi);
92 }
93 }
94
95 List<PackageInfo> overlayPackages = mPackageManager.getOverlayPackages(newUserId);
96 final int overlayPackagesSize = overlayPackages.size();
97 for (int i = 0; i < overlayPackagesSize; i++) {
98 final PackageInfo overlayPackage = overlayPackages.get(i);
99 final OverlayInfo oi = storedOverlayInfos.get(overlayPackage.packageName);
100 if (oi == null || !oi.targetPackageName.equals(overlayPackage.overlayTarget)) {
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800101 // Update the overlay if it didn't exist or had the wrong target package.
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100102 mSettings.init(overlayPackage.packageName, newUserId,
103 overlayPackage.overlayTarget,
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900104 overlayPackage.applicationInfo.getBaseCodePath(),
Adam Lesinskiab56b9d2017-11-14 00:50:18 -0800105 overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority);
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800106
107 if (oi == null) {
108 // This overlay does not exist in our settings.
Adam Lesinskiab56b9d2017-11-14 00:50:18 -0800109 if (overlayPackage.isStaticOverlayPackage() ||
Jaekyun Seok84d7f1e2017-03-29 11:02:15 +0900110 mDefaultOverlays.contains(overlayPackage.packageName)) {
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800111 // Enable this overlay by default.
Adam Lesinskid11c5512017-04-11 12:01:10 -0700112 if (DEBUG) {
113 Slog.d(TAG, "Enabling overlay " + overlayPackage.packageName
114 + " for user " + newUserId + " by default");
115 }
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800116 mSettings.setEnabled(overlayPackage.packageName, newUserId, true);
117 }
118 } else {
119 // The targetPackageName we have stored doesn't match the overlay's target.
120 // Queue the old target for an update as well.
121 packagesToUpdateAssets.add(oi.targetPackageName);
122 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100123 }
124
125 try {
126 final PackageInfo targetPackage =
127 mPackageManager.getPackageInfo(overlayPackage.overlayTarget, newUserId);
128 updateState(targetPackage, overlayPackage, newUserId);
129 } catch (OverlayManagerSettings.BadKeyException e) {
130 Slog.e(TAG, "failed to update settings", e);
131 mSettings.remove(overlayPackage.packageName, newUserId);
132 }
133
134 packagesToUpdateAssets.add(overlayPackage.overlayTarget);
135 storedOverlayInfos.remove(overlayPackage.packageName);
136 }
137
138 // any OverlayInfo left in storedOverlayInfos is no longer
139 // installed and should be removed
140 final int storedOverlayInfosSize = storedOverlayInfos.size();
141 for (int i = 0; i < storedOverlayInfosSize; i++) {
Mårten Kongstadc0bba8b2017-01-27 10:15:49 +0100142 final OverlayInfo oi = storedOverlayInfos.valueAt(i);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100143 mSettings.remove(oi.packageName, oi.userId);
144 removeIdmapIfPossible(oi);
145 packagesToUpdateAssets.add(oi.targetPackageName);
146 }
147
148 // remove target packages that are not installed
149 final Iterator<String> iter = packagesToUpdateAssets.iterator();
150 while (iter.hasNext()) {
151 String targetPackageName = iter.next();
152 if (mPackageManager.getPackageInfo(targetPackageName, newUserId) == null) {
153 iter.remove();
154 }
155 }
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800156 return new ArrayList<>(packagesToUpdateAssets);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100157 }
158
159 void onUserRemoved(final int userId) {
160 if (DEBUG) {
161 Slog.d(TAG, "onUserRemoved userId=" + userId);
162 }
163 mSettings.removeUser(userId);
164 }
165
166 void onTargetPackageAdded(@NonNull final String packageName, final int userId) {
167 if (DEBUG) {
168 Slog.d(TAG, "onTargetPackageAdded packageName=" + packageName + " userId=" + userId);
169 }
170
171 final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
Mårten Kongstadb6f19c92017-06-26 15:26:32 +0200172 if (updateAllOverlaysForTarget(packageName, userId, targetPackage)) {
173 mListener.onOverlaysChanged(packageName, userId);
174 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100175 }
176
177 void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
178 if (DEBUG) {
179 Slog.d(TAG, "onTargetPackageChanged packageName=" + packageName + " userId=" + userId);
180 }
181
182 final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
Todd Kennedy560830c2017-06-16 13:55:13 -0700183 if (updateAllOverlaysForTarget(packageName, userId, targetPackage)) {
184 mListener.onOverlaysChanged(packageName, userId);
185 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100186 }
187
188 void onTargetPackageUpgrading(@NonNull final String packageName, final int userId) {
189 if (DEBUG) {
190 Slog.d(TAG, "onTargetPackageUpgrading packageName=" + packageName + " userId=" + userId);
191 }
192
Todd Kennedy560830c2017-06-16 13:55:13 -0700193 if (updateAllOverlaysForTarget(packageName, userId, null)) {
194 mListener.onOverlaysChanged(packageName, userId);
195 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100196 }
197
198 void onTargetPackageUpgraded(@NonNull final String packageName, final int userId) {
199 if (DEBUG) {
200 Slog.d(TAG, "onTargetPackageUpgraded packageName=" + packageName + " userId=" + userId);
201 }
202
203 final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
Todd Kennedy560830c2017-06-16 13:55:13 -0700204 if (updateAllOverlaysForTarget(packageName, userId, targetPackage)) {
205 mListener.onOverlaysChanged(packageName, userId);
206 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100207 }
208
209 void onTargetPackageRemoved(@NonNull final String packageName, final int userId) {
210 if (DEBUG) {
211 Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId);
212 }
213
Mårten Kongstadb6f19c92017-06-26 15:26:32 +0200214 if (updateAllOverlaysForTarget(packageName, userId, null)) {
215 mListener.onOverlaysChanged(packageName, userId);
216 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100217 }
218
Adam Lesinskic745f422017-04-05 16:31:30 -0700219 /**
220 * Returns true if the settings were modified for this target.
221 */
222 private boolean updateAllOverlaysForTarget(@NonNull final String packageName, final int userId,
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100223 @Nullable final PackageInfo targetPackage) {
Adam Lesinskic745f422017-04-05 16:31:30 -0700224 boolean modified = false;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100225 final List<OverlayInfo> ois = mSettings.getOverlaysForTarget(packageName, userId);
226 final int N = ois.size();
227 for (int i = 0; i < N; i++) {
228 final OverlayInfo oi = ois.get(i);
229 final PackageInfo overlayPackage = mPackageManager.getPackageInfo(oi.packageName, userId);
230 if (overlayPackage == null) {
Adam Lesinskic745f422017-04-05 16:31:30 -0700231 modified |= mSettings.remove(oi.packageName, oi.userId);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100232 removeIdmapIfPossible(oi);
233 } else {
234 try {
Adam Lesinskic745f422017-04-05 16:31:30 -0700235 modified |= updateState(targetPackage, overlayPackage, userId);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100236 } catch (OverlayManagerSettings.BadKeyException e) {
237 Slog.e(TAG, "failed to update settings", e);
Adam Lesinskic745f422017-04-05 16:31:30 -0700238 modified |= mSettings.remove(oi.packageName, userId);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100239 }
240 }
241 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700242 return modified;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100243 }
244
245 void onOverlayPackageAdded(@NonNull final String packageName, final int userId) {
246 if (DEBUG) {
247 Slog.d(TAG, "onOverlayPackageAdded packageName=" + packageName + " userId=" + userId);
248 }
249
250 final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
251 if (overlayPackage == null) {
252 Slog.w(TAG, "overlay package " + packageName + " was added, but couldn't be found");
253 onOverlayPackageRemoved(packageName, userId);
254 return;
255 }
256
257 final PackageInfo targetPackage =
258 mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
259
260 mSettings.init(packageName, userId, overlayPackage.overlayTarget,
Adam Lesinskiab56b9d2017-11-14 00:50:18 -0800261 overlayPackage.applicationInfo.getBaseCodePath(),
262 overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100263 try {
Adam Lesinskic745f422017-04-05 16:31:30 -0700264 if (updateState(targetPackage, overlayPackage, userId)) {
265 mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
266 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100267 } catch (OverlayManagerSettings.BadKeyException e) {
268 Slog.e(TAG, "failed to update settings", e);
269 mSettings.remove(packageName, userId);
270 }
271 }
272
273 void onOverlayPackageChanged(@NonNull final String packageName, final int userId) {
274 Slog.wtf(TAG, "onOverlayPackageChanged called, but only pre-installed overlays supported");
275 }
276
277 void onOverlayPackageUpgrading(@NonNull final String packageName, final int userId) {
278 Slog.wtf(TAG, "onOverlayPackageUpgrading called, but only pre-installed overlays supported");
279 }
280
281 void onOverlayPackageUpgraded(@NonNull final String packageName, final int userId) {
282 Slog.wtf(TAG, "onOverlayPackageUpgraded called, but only pre-installed overlays supported");
283 }
284
285 void onOverlayPackageRemoved(@NonNull final String packageName, final int userId) {
286 Slog.wtf(TAG, "onOverlayPackageRemoved called, but only pre-installed overlays supported");
287 }
288
289 OverlayInfo getOverlayInfo(@NonNull final String packageName, final int userId) {
290 try {
291 return mSettings.getOverlayInfo(packageName, userId);
292 } catch (OverlayManagerSettings.BadKeyException e) {
293 return null;
294 }
295 }
296
297 List<OverlayInfo> getOverlayInfosForTarget(@NonNull final String targetPackageName,
298 final int userId) {
299 return mSettings.getOverlaysForTarget(targetPackageName, userId);
300 }
301
302 Map<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
303 return mSettings.getOverlaysForUser(userId);
304 }
305
306 boolean setEnabled(@NonNull final String packageName, final boolean enable,
307 final int userId) {
308 if (DEBUG) {
309 Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d",
310 packageName, enable, userId));
311 }
312
313 final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
314 if (overlayPackage == null) {
315 return false;
316 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700317
318 // Ignore static overlays.
Adam Lesinskiab56b9d2017-11-14 00:50:18 -0800319 if (overlayPackage.isStaticOverlayPackage()) {
Jaekyun Seok04342892017-03-02 15:24:19 +0900320 return false;
321 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100322
323 try {
324 final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
325 final PackageInfo targetPackage =
326 mPackageManager.getPackageInfo(oi.targetPackageName, userId);
Adam Lesinskic745f422017-04-05 16:31:30 -0700327 boolean modified = mSettings.setEnabled(packageName, userId, enable);
328 modified |= updateState(targetPackage, overlayPackage, userId);
329
330 if (modified) {
331 mListener.onOverlaysChanged(oi.targetPackageName, userId);
332 }
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100333 return true;
334 } catch (OverlayManagerSettings.BadKeyException e) {
335 return false;
336 }
337 }
338
Adam Lesinskic745f422017-04-05 16:31:30 -0700339 boolean setEnabledExclusive(@NonNull final String packageName, final int userId) {
Jason Monk929ed8d2017-03-07 16:01:20 -0500340 if (DEBUG) {
Adam Lesinskic745f422017-04-05 16:31:30 -0700341 Slog.d(TAG, String.format("setEnabledExclusive packageName=%s userId=%d", packageName, userId));
Jason Monk929ed8d2017-03-07 16:01:20 -0500342 }
343
344 final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
345 if (overlayPackage == null) {
346 return false;
347 }
348
349 try {
350 final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
Adam Lesinskic745f422017-04-05 16:31:30 -0700351 final PackageInfo targetPackage =
352 mPackageManager.getPackageInfo(oi.targetPackageName, userId);
353
Jason Monk929ed8d2017-03-07 16:01:20 -0500354 List<OverlayInfo> allOverlays = getOverlayInfosForTarget(oi.targetPackageName, userId);
355
Adam Lesinskic745f422017-04-05 16:31:30 -0700356 boolean modified = false;
357
Jason Monk929ed8d2017-03-07 16:01:20 -0500358 // Disable all other overlays.
359 allOverlays.remove(oi);
360 for (int i = 0; i < allOverlays.size(); i++) {
Adam Lesinskic745f422017-04-05 16:31:30 -0700361 final String disabledOverlayPackageName = allOverlays.get(i).packageName;
362 final PackageInfo disabledOverlayPackageInfo = mPackageManager.getPackageInfo(
363 disabledOverlayPackageName, userId);
364 if (disabledOverlayPackageInfo == null) {
365 modified |= mSettings.remove(disabledOverlayPackageName, userId);
366 continue;
367 }
368
Adam Lesinskiab56b9d2017-11-14 00:50:18 -0800369 if (disabledOverlayPackageInfo.isStaticOverlayPackage()) {
Adam Lesinskic745f422017-04-05 16:31:30 -0700370 // Don't touch static overlays.
371 continue;
372 }
373
374 // Disable the overlay.
375 modified |= mSettings.setEnabled(disabledOverlayPackageName, userId, false);
376 modified |= updateState(targetPackage, disabledOverlayPackageInfo, userId);
Jason Monk929ed8d2017-03-07 16:01:20 -0500377 }
378
Adam Lesinskic745f422017-04-05 16:31:30 -0700379 // Enable the selected overlay.
380 modified |= mSettings.setEnabled(packageName, userId, true);
381 modified |= updateState(targetPackage, overlayPackage, userId);
382
383 if (modified) {
384 mListener.onOverlaysChanged(oi.targetPackageName, userId);
385 }
Jason Monk929ed8d2017-03-07 16:01:20 -0500386 return true;
387 } catch (OverlayManagerSettings.BadKeyException e) {
388 return false;
389 }
390 }
391
Adam Lesinskic745f422017-04-05 16:31:30 -0700392 private boolean isPackageUpdatableOverlay(@NonNull final String packageName, final int userId) {
Jaekyun Seok04342892017-03-02 15:24:19 +0900393 final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
Adam Lesinskiab56b9d2017-11-14 00:50:18 -0800394 if (overlayPackage == null || overlayPackage.isStaticOverlayPackage()) {
Jaekyun Seok04342892017-03-02 15:24:19 +0900395 return false;
396 }
397 return true;
398 }
399
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100400 boolean setPriority(@NonNull final String packageName,
401 @NonNull final String newParentPackageName, final int userId) {
Adam Lesinskic745f422017-04-05 16:31:30 -0700402 if (DEBUG) {
403 Slog.d(TAG, "setPriority packageName=" + packageName + " newParentPackageName="
404 + newParentPackageName + " userId=" + userId);
405 }
406
407 if (!isPackageUpdatableOverlay(packageName, userId)) {
408 return false;
409 }
410
411 final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
412 if (overlayPackage == null) {
413 return false;
414 }
415
416 if (mSettings.setPriority(packageName, newParentPackageName, userId)) {
417 mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
418 }
419 return true;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100420 }
421
422 boolean setHighestPriority(@NonNull final String packageName, final int userId) {
Adam Lesinskic745f422017-04-05 16:31:30 -0700423 if (DEBUG) {
424 Slog.d(TAG, "setHighestPriority packageName=" + packageName + " userId=" + userId);
425 }
426
427 if (!isPackageUpdatableOverlay(packageName, userId)) {
428 return false;
429 }
430
431 final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
432 if (overlayPackage == null) {
433 return false;
434 }
435
436 if (mSettings.setHighestPriority(packageName, userId)) {
437 mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
438 }
439 return true;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100440 }
441
442 boolean setLowestPriority(@NonNull final String packageName, final int userId) {
Adam Lesinskic745f422017-04-05 16:31:30 -0700443 if (DEBUG) {
444 Slog.d(TAG, "setLowestPriority packageName=" + packageName + " userId=" + userId);
445 }
446
447 if (!isPackageUpdatableOverlay(packageName, userId)) {
448 return false;
449 }
450
451 final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
452 if (overlayPackage == null) {
453 return false;
454 }
455
456 if (mSettings.setLowestPriority(packageName, userId)) {
457 mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
458 }
459 return true;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100460 }
461
462 void onDump(@NonNull final PrintWriter pw) {
463 mSettings.dump(pw);
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800464 pw.println("Default overlays: " + TextUtils.join(";", mDefaultOverlays));
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100465 }
466
467 List<String> getEnabledOverlayPackageNames(@NonNull final String targetPackageName,
468 final int userId) {
469 final List<OverlayInfo> overlays = mSettings.getOverlaysForTarget(targetPackageName, userId);
470 final List<String> paths = new ArrayList<>(overlays.size());
471 final int N = overlays.size();
472 for (int i = 0; i < N; i++) {
473 final OverlayInfo oi = overlays.get(i);
474 if (oi.isEnabled()) {
475 paths.add(oi.packageName);
476 }
477 }
478 return paths;
479 }
480
Adam Lesinskic745f422017-04-05 16:31:30 -0700481 /**
482 * Returns true if the settings/state was modified, false otherwise.
483 */
484 private boolean updateState(@Nullable final PackageInfo targetPackage,
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100485 @NonNull final PackageInfo overlayPackage, final int userId)
Adam Lesinskic745f422017-04-05 16:31:30 -0700486 throws OverlayManagerSettings.BadKeyException {
Jaekyun Seok04342892017-03-02 15:24:19 +0900487 // Static RROs targeting to "android", ie framework-res.apk, are handled by native layers.
488 if (targetPackage != null &&
Adam Lesinskiab56b9d2017-11-14 00:50:18 -0800489 !("android".equals(targetPackage.packageName)
490 && overlayPackage.isStaticOverlayPackage())) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100491 mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
492 }
493
Adam Lesinskic745f422017-04-05 16:31:30 -0700494 boolean modified = mSettings.setBaseCodePath(overlayPackage.packageName, userId,
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100495 overlayPackage.applicationInfo.getBaseCodePath());
496
497 final int currentState = mSettings.getState(overlayPackage.packageName, userId);
498 final int newState = calculateNewState(targetPackage, overlayPackage, userId);
499 if (currentState != newState) {
500 if (DEBUG) {
501 Slog.d(TAG, String.format("%s:%d: %s -> %s",
502 overlayPackage.packageName, userId,
503 OverlayInfo.stateToString(currentState),
504 OverlayInfo.stateToString(newState)));
505 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700506 modified |= mSettings.setState(overlayPackage.packageName, userId, newState);
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100507 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700508 return modified;
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100509 }
510
511 private int calculateNewState(@Nullable final PackageInfo targetPackage,
512 @NonNull final PackageInfo overlayPackage, final int userId)
513 throws OverlayManagerSettings.BadKeyException {
514 if (targetPackage == null) {
515 return STATE_MISSING_TARGET;
516 }
517
518 if (!mIdmapManager.idmapExists(overlayPackage, userId)) {
519 return STATE_NO_IDMAP;
520 }
521
522 final boolean enabled = mSettings.getEnabled(overlayPackage.packageName, userId);
523 return enabled ? STATE_ENABLED : STATE_DISABLED;
524 }
525
526 private void removeIdmapIfPossible(@NonNull final OverlayInfo oi) {
527 // For a given package, all Android users share the same idmap file.
528 // This works because Android currently does not support users to
529 // install different versions of the same package. It also means we
530 // cannot remove an idmap file if any user still needs it.
531 //
532 // When/if the Android framework allows different versions of the same
533 // package to be installed for different users, idmap file handling
534 // should be revised:
535 //
536 // - an idmap file should be unique for each {user, package} pair
537 //
538 // - the path to the idmap file should be passed to the native Asset
539 // Manager layers, just like the path to the apk is passed today
540 //
541 // As part of that change, calls to this method should be replaced by
542 // direct calls to IdmapManager.removeIdmap, without looping over all
543 // users.
544
545 if (!mIdmapManager.idmapExists(oi)) {
546 return;
547 }
Adam Lesinskic745f422017-04-05 16:31:30 -0700548 final int[] userIds = mSettings.getUsers();
549 for (int userId : userIds) {
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100550 try {
551 final OverlayInfo tmp = mSettings.getOverlayInfo(oi.packageName, userId);
552 if (tmp != null && tmp.isEnabled()) {
553 // someone is still using the idmap file -> we cannot remove it
554 return;
555 }
556 } catch (OverlayManagerSettings.BadKeyException e) {
557 // intentionally left empty
558 }
559 }
560 mIdmapManager.removeIdmap(oi, oi.userId);
561 }
562
Adam Lesinskic745f422017-04-05 16:31:30 -0700563 interface OverlayChangeListener {
564 void onOverlaysChanged(@NonNull String targetPackage, int userId);
565 }
566
Mårten Kongstadeabc9e92015-12-15 16:40:23 +0100567 interface PackageManagerHelper {
568 PackageInfo getPackageInfo(@NonNull String packageName, int userId);
569 boolean signaturesMatching(@NonNull String packageName1, @NonNull String packageName2,
570 int userId);
571 List<PackageInfo> getOverlayPackages(int userId);
572 }
573}