OverlayManagerServiceImpl.java revision d11c5510b13171878f8d6f6a3424c7b2418c3031
1eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad/*
2eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * Copyright (C) 2016 The Android Open Source Project
3eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad *
4eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * Licensed under the Apache License, Version 2.0 (the "License");
5eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * you may not use this file except in compliance with the License.
6eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * You may obtain a copy of the License at
7eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad *
8eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad *      http://www.apache.org/licenses/LICENSE-2.0
9eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad *
10eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * Unless required by applicable law or agreed to in writing, software
11eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * distributed under the License is distributed on an "AS IS" BASIS,
12eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * See the License for the specific language governing permissions and
14eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * limitations under the License.
15eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad */
16eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
17eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadpackage com.android.server.om;
18eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
19eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport static android.content.om.OverlayInfo.STATE_DISABLED;
20eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport static android.content.om.OverlayInfo.STATE_ENABLED;
21eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
22eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport static android.content.om.OverlayInfo.STATE_NO_IDMAP;
23eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
24eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport static com.android.server.om.OverlayManagerService.DEBUG;
25eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport static com.android.server.om.OverlayManagerService.TAG;
26eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
27eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.annotation.NonNull;
28eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.annotation.Nullable;
29eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.content.om.OverlayInfo;
30eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.content.pm.PackageInfo;
31a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinskiimport android.text.TextUtils;
32eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.util.ArrayMap;
33eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.util.ArraySet;
34eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.util.Slog;
35eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
36eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport java.io.PrintWriter;
37eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport java.util.ArrayList;
38eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport java.util.Iterator;
39eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport java.util.List;
40eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport java.util.Map;
41eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport java.util.Set;
42eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
43eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad/**
44eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * Internal implementation of OverlayManagerService.
45eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad *
46eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * Methods in this class should only be called by the OverlayManagerService.
47eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * This class is not thread-safe; the caller is expected to ensure the
48eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * necessary thread synchronization.
49eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad *
50eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * @see OverlayManagerService
51eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad */
52eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadfinal class OverlayManagerServiceImpl {
53eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    private final PackageManagerHelper mPackageManager;
54eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    private final IdmapManager mIdmapManager;
55eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    private final OverlayManagerSettings mSettings;
56a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski    private final Set<String> mDefaultOverlays;
57c745f42169df6687a764e48b65878f22965c1530Adam Lesinski    private final OverlayChangeListener mListener;
58eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
59eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    OverlayManagerServiceImpl(@NonNull final PackageManagerHelper packageManager,
60eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            @NonNull final IdmapManager idmapManager,
61a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski            @NonNull final OverlayManagerSettings settings,
62c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            @NonNull final Set<String> defaultOverlays,
63c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            @NonNull final OverlayChangeListener listener) {
64eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        mPackageManager = packageManager;
65eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        mIdmapManager = idmapManager;
66eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        mSettings = settings;
67a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski        mDefaultOverlays = defaultOverlays;
68c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        mListener = listener;
69eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
70eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
71eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    /*
72eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad     * Call this when switching to a new Android user. Will return a list of
73eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad     * target packages that must refresh their overlays. This list is the union
74eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad     * of two sets: the set of targets with currently active overlays, and the
75eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad     * set of targets that had, but no longer have, active overlays.
76eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad     */
77eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    List<String> onSwitchUser(final int newUserId) {
78eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (DEBUG) {
79eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            Slog.d(TAG, "onSwitchUser newUserId=" + newUserId);
80eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
81eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
82eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final Set<String> packagesToUpdateAssets = new ArraySet<>();
83eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final ArrayMap<String, List<OverlayInfo>> tmp = mSettings.getOverlaysForUser(newUserId);
84eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final int tmpSize = tmp.size();
85eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final ArrayMap<String, OverlayInfo> storedOverlayInfos = new ArrayMap<>(tmpSize);
86eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        for (int i = 0; i < tmpSize; i++) {
87eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final List<OverlayInfo> chunk = tmp.valueAt(i);
88eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final int chunkSize = chunk.size();
89eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            for (int j = 0; j < chunkSize; j++) {
90eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                final OverlayInfo oi = chunk.get(j);
91eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                storedOverlayInfos.put(oi.packageName, oi);
92eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            }
93eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
94eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
95eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        List<PackageInfo> overlayPackages = mPackageManager.getOverlayPackages(newUserId);
96eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final int overlayPackagesSize = overlayPackages.size();
97eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        for (int i = 0; i < overlayPackagesSize; i++) {
98eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final PackageInfo overlayPackage = overlayPackages.get(i);
99eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final OverlayInfo oi = storedOverlayInfos.get(overlayPackage.packageName);
100eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            if (oi == null || !oi.targetPackageName.equals(overlayPackage.overlayTarget)) {
101a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski                // Update the overlay if it didn't exist or had the wrong target package.
102eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                mSettings.init(overlayPackage.packageName, newUserId,
103eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                        overlayPackage.overlayTarget,
10442d53f6b1883e3db514ad8d105d23fe6a1e9a59bJaekyun Seok                        overlayPackage.applicationInfo.getBaseCodePath(),
10542d53f6b1883e3db514ad8d105d23fe6a1e9a59bJaekyun Seok                        overlayPackage.isStaticOverlay, overlayPackage.overlayPriority);
106a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski
107a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski                if (oi == null) {
108a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski                    // This overlay does not exist in our settings.
10984d7f1ecfb962cb6c8e4adefa077729128c26d3bJaekyun Seok                    if (overlayPackage.isStaticOverlay ||
11084d7f1ecfb962cb6c8e4adefa077729128c26d3bJaekyun Seok                            mDefaultOverlays.contains(overlayPackage.packageName)) {
111a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski                        // Enable this overlay by default.
112d11c5510b13171878f8d6f6a3424c7b2418c3031Adam Lesinski                        if (DEBUG) {
113d11c5510b13171878f8d6f6a3424c7b2418c3031Adam Lesinski                            Slog.d(TAG, "Enabling overlay " + overlayPackage.packageName
114d11c5510b13171878f8d6f6a3424c7b2418c3031Adam Lesinski                                    + " for user " + newUserId + " by default");
115d11c5510b13171878f8d6f6a3424c7b2418c3031Adam Lesinski                        }
116a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski                        mSettings.setEnabled(overlayPackage.packageName, newUserId, true);
117a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski                    }
118a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski                } else {
119a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski                    // The targetPackageName we have stored doesn't match the overlay's target.
120a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski                    // Queue the old target for an update as well.
121a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski                    packagesToUpdateAssets.add(oi.targetPackageName);
122a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski                }
123eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            }
124eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
125eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            try {
126eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                final PackageInfo targetPackage =
127eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                        mPackageManager.getPackageInfo(overlayPackage.overlayTarget, newUserId);
128eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                updateState(targetPackage, overlayPackage, newUserId);
129eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            } catch (OverlayManagerSettings.BadKeyException e) {
130eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                Slog.e(TAG, "failed to update settings", e);
131eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                mSettings.remove(overlayPackage.packageName, newUserId);
132eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            }
133eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
134eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            packagesToUpdateAssets.add(overlayPackage.overlayTarget);
135eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            storedOverlayInfos.remove(overlayPackage.packageName);
136eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
137eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
138eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // any OverlayInfo left in storedOverlayInfos is no longer
139eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // installed and should be removed
140eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final int storedOverlayInfosSize = storedOverlayInfos.size();
141eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        for (int i = 0; i < storedOverlayInfosSize; i++) {
142c0bba8b18b41356721c2ebb25af83bc5bb5a74b0Mårten Kongstad            final OverlayInfo oi = storedOverlayInfos.valueAt(i);
143eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            mSettings.remove(oi.packageName, oi.userId);
144eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            removeIdmapIfPossible(oi);
145eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            packagesToUpdateAssets.add(oi.targetPackageName);
146eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
147eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
148eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // remove target packages that are not installed
149eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final Iterator<String> iter = packagesToUpdateAssets.iterator();
150eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        while (iter.hasNext()) {
151eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            String targetPackageName = iter.next();
152eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            if (mPackageManager.getPackageInfo(targetPackageName, newUserId) == null) {
153eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                iter.remove();
154eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            }
155eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
156a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski        return new ArrayList<>(packagesToUpdateAssets);
157eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
158eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
159eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onUserRemoved(final int userId) {
160eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (DEBUG) {
161eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            Slog.d(TAG, "onUserRemoved userId=" + userId);
162eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
163eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        mSettings.removeUser(userId);
164eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
165eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
166eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onTargetPackageAdded(@NonNull final String packageName, final int userId) {
167eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (DEBUG) {
168eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            Slog.d(TAG, "onTargetPackageAdded packageName=" + packageName + " userId=" + userId);
169eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
170eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
171eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
172eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        updateAllOverlaysForTarget(packageName, userId, targetPackage);
173eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
174eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
175eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
176eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (DEBUG) {
177eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            Slog.d(TAG, "onTargetPackageChanged packageName=" + packageName + " userId=" + userId);
178eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
179eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
180eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
181eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        updateAllOverlaysForTarget(packageName, userId, targetPackage);
182eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
183eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
184eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onTargetPackageUpgrading(@NonNull final String packageName, final int userId) {
185eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (DEBUG) {
186eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            Slog.d(TAG, "onTargetPackageUpgrading packageName=" + packageName + " userId=" + userId);
187eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
188eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
189eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        updateAllOverlaysForTarget(packageName, userId, null);
190eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
191eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
192eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onTargetPackageUpgraded(@NonNull final String packageName, final int userId) {
193eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (DEBUG) {
194eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            Slog.d(TAG, "onTargetPackageUpgraded packageName=" + packageName + " userId=" + userId);
195eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
196eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
197eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
198eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        updateAllOverlaysForTarget(packageName, userId, targetPackage);
199eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
200eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
201eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onTargetPackageRemoved(@NonNull final String packageName, final int userId) {
202eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (DEBUG) {
203eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId);
204eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
205eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
206eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        updateAllOverlaysForTarget(packageName, userId, null);
207eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
208eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
209c745f42169df6687a764e48b65878f22965c1530Adam Lesinski    /**
210c745f42169df6687a764e48b65878f22965c1530Adam Lesinski     * Returns true if the settings were modified for this target.
211c745f42169df6687a764e48b65878f22965c1530Adam Lesinski     */
212c745f42169df6687a764e48b65878f22965c1530Adam Lesinski    private boolean updateAllOverlaysForTarget(@NonNull final String packageName, final int userId,
213eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            @Nullable final PackageInfo targetPackage) {
214c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        boolean modified = false;
215eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final List<OverlayInfo> ois = mSettings.getOverlaysForTarget(packageName, userId);
216eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final int N = ois.size();
217eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        for (int i = 0; i < N; i++) {
218eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final OverlayInfo oi = ois.get(i);
219eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final PackageInfo overlayPackage = mPackageManager.getPackageInfo(oi.packageName, userId);
220eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            if (overlayPackage == null) {
221c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                modified |= mSettings.remove(oi.packageName, oi.userId);
222eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                removeIdmapIfPossible(oi);
223eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            } else {
224eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                try {
225c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                    modified |= updateState(targetPackage, overlayPackage, userId);
226eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                } catch (OverlayManagerSettings.BadKeyException e) {
227eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                    Slog.e(TAG, "failed to update settings", e);
228c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                    modified |= mSettings.remove(oi.packageName, userId);
229eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                }
230eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            }
231eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
232c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        return modified;
233eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
234eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
235eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onOverlayPackageAdded(@NonNull final String packageName, final int userId) {
236eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (DEBUG) {
237eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            Slog.d(TAG, "onOverlayPackageAdded packageName=" + packageName + " userId=" + userId);
238eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
239eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
240eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
241eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (overlayPackage == null) {
242eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            Slog.w(TAG, "overlay package " + packageName + " was added, but couldn't be found");
243eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            onOverlayPackageRemoved(packageName, userId);
244eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            return;
245eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
246eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
247eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final PackageInfo targetPackage =
248eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
249eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
250eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        mSettings.init(packageName, userId, overlayPackage.overlayTarget,
25142d53f6b1883e3db514ad8d105d23fe6a1e9a59bJaekyun Seok                overlayPackage.applicationInfo.getBaseCodePath(), overlayPackage.isStaticOverlay,
25242d53f6b1883e3db514ad8d105d23fe6a1e9a59bJaekyun Seok                overlayPackage.overlayPriority);
253eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        try {
254c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            if (updateState(targetPackage, overlayPackage, userId)) {
255c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
256c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            }
257eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        } catch (OverlayManagerSettings.BadKeyException e) {
258eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            Slog.e(TAG, "failed to update settings", e);
259eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            mSettings.remove(packageName, userId);
260eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
261eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
262eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
263eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onOverlayPackageChanged(@NonNull final String packageName, final int userId) {
264eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        Slog.wtf(TAG, "onOverlayPackageChanged called, but only pre-installed overlays supported");
265eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
266eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
267eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onOverlayPackageUpgrading(@NonNull final String packageName, final int userId) {
268eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        Slog.wtf(TAG, "onOverlayPackageUpgrading called, but only pre-installed overlays supported");
269eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
270eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
271eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onOverlayPackageUpgraded(@NonNull final String packageName, final int userId) {
272eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        Slog.wtf(TAG, "onOverlayPackageUpgraded called, but only pre-installed overlays supported");
273eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
274eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
275eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onOverlayPackageRemoved(@NonNull final String packageName, final int userId) {
276eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        Slog.wtf(TAG, "onOverlayPackageRemoved called, but only pre-installed overlays supported");
277eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
278eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
279eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    OverlayInfo getOverlayInfo(@NonNull final String packageName, final int userId) {
280eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        try {
281eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            return mSettings.getOverlayInfo(packageName, userId);
282eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        } catch (OverlayManagerSettings.BadKeyException e) {
283eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            return null;
284eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
285eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
286eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
287eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    List<OverlayInfo> getOverlayInfosForTarget(@NonNull final String targetPackageName,
288eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final int userId) {
289eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        return mSettings.getOverlaysForTarget(targetPackageName, userId);
290eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
291eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
292eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    Map<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
293eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        return mSettings.getOverlaysForUser(userId);
294eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
295eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
296eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    boolean setEnabled(@NonNull final String packageName, final boolean enable,
297eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final int userId) {
298eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (DEBUG) {
299eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d",
300eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                        packageName, enable, userId));
301eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
302eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
303eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
304eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (overlayPackage == null) {
305eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            return false;
306eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
307c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
308c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        // Ignore static overlays.
309c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (overlayPackage.isStaticOverlay) {
3100434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok            return false;
3110434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok        }
312eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
313eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        try {
314eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
315eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final PackageInfo targetPackage =
316eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                    mPackageManager.getPackageInfo(oi.targetPackageName, userId);
317c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            boolean modified = mSettings.setEnabled(packageName, userId, enable);
318c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            modified |= updateState(targetPackage, overlayPackage, userId);
319c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
320c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            if (modified) {
321c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                mListener.onOverlaysChanged(oi.targetPackageName, userId);
322c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            }
323929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk            return true;
324929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk        } catch (OverlayManagerSettings.BadKeyException e) {
325929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk            return false;
326929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk        }
327929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk    }
328929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk
329c745f42169df6687a764e48b65878f22965c1530Adam Lesinski    boolean setEnabledExclusive(@NonNull final String packageName, final int userId) {
330929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk        if (DEBUG) {
331c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            Slog.d(TAG, String.format("setEnabledExclusive packageName=%s userId=%d", packageName, userId));
332929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk        }
333929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk
334929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
335929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk        if (overlayPackage == null) {
336929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk            return false;
337929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk        }
338929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk
339929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk        try {
340929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk            final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
341c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            final PackageInfo targetPackage =
342c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                    mPackageManager.getPackageInfo(oi.targetPackageName, userId);
343c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
344929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk            List<OverlayInfo> allOverlays = getOverlayInfosForTarget(oi.targetPackageName, userId);
345929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk
346c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            boolean modified = false;
347c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
348929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk            // Disable all other overlays.
349929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk            allOverlays.remove(oi);
350929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk            for (int i = 0; i < allOverlays.size(); i++) {
351c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                final String disabledOverlayPackageName = allOverlays.get(i).packageName;
352c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                final PackageInfo disabledOverlayPackageInfo = mPackageManager.getPackageInfo(
353c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                        disabledOverlayPackageName, userId);
354c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                if (disabledOverlayPackageInfo == null) {
355c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                    modified |= mSettings.remove(disabledOverlayPackageName, userId);
356c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                    continue;
357c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                }
358c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
359c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                if (disabledOverlayPackageInfo.isStaticOverlay) {
360c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                    // Don't touch static overlays.
361c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                    continue;
362c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                }
363c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
364c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                // Disable the overlay.
365c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                modified |= mSettings.setEnabled(disabledOverlayPackageName, userId, false);
366c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                modified |= updateState(targetPackage, disabledOverlayPackageInfo, userId);
367929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk            }
368929ed8d2f46209026cfa6f4baa68b551d54401a0Jason Monk
369c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            // Enable the selected overlay.
370c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            modified |= mSettings.setEnabled(packageName, userId, true);
371c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            modified |= updateState(targetPackage, overlayPackage, userId);
372c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
373c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            if (modified) {
374c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                mListener.onOverlaysChanged(oi.targetPackageName, userId);
375c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            }
376eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            return true;
377eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        } catch (OverlayManagerSettings.BadKeyException e) {
378eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            return false;
379eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
380eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
381eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
382c745f42169df6687a764e48b65878f22965c1530Adam Lesinski    private boolean isPackageUpdatableOverlay(@NonNull final String packageName, final int userId) {
3830434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
3840434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok        if (overlayPackage == null || overlayPackage.isStaticOverlay) {
3850434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok            return false;
3860434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok        }
3870434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok        return true;
3880434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok    }
3890434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok
390eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    boolean setPriority(@NonNull final String packageName,
391eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            @NonNull final String newParentPackageName, final int userId) {
392c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (DEBUG) {
393c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            Slog.d(TAG, "setPriority packageName=" + packageName + " newParentPackageName="
394c745f42169df6687a764e48b65878f22965c1530Adam Lesinski                    + newParentPackageName + " userId=" + userId);
395c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
396c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
397c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (!isPackageUpdatableOverlay(packageName, userId)) {
398c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            return false;
399c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
400c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
401c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
402c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (overlayPackage == null) {
403c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            return false;
404c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
405c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
406c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (mSettings.setPriority(packageName, newParentPackageName, userId)) {
407c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
408c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
409c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        return true;
410eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
411eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
412eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    boolean setHighestPriority(@NonNull final String packageName, final int userId) {
413c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (DEBUG) {
414c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            Slog.d(TAG, "setHighestPriority packageName=" + packageName + " userId=" + userId);
415c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
416c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
417c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (!isPackageUpdatableOverlay(packageName, userId)) {
418c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            return false;
419c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
420c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
421c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
422c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (overlayPackage == null) {
423c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            return false;
424c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
425c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
426c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (mSettings.setHighestPriority(packageName, userId)) {
427c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
428c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
429c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        return true;
430eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
431eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
432eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    boolean setLowestPriority(@NonNull final String packageName, final int userId) {
433c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (DEBUG) {
434c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            Slog.d(TAG, "setLowestPriority packageName=" + packageName + " userId=" + userId);
435c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
436c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
437c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (!isPackageUpdatableOverlay(packageName, userId)) {
438c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            return false;
439c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
440c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
441c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
442c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (overlayPackage == null) {
443c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            return false;
444c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
445c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
446c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        if (mSettings.setLowestPriority(packageName, userId)) {
447c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
448c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        }
449c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        return true;
450eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
451eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
452eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    void onDump(@NonNull final PrintWriter pw) {
453eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        mSettings.dump(pw);
454a5ca62408381058c12bd5a1fe3b30f2512a73e03Adam Lesinski        pw.println("Default overlays: " + TextUtils.join(";", mDefaultOverlays));
455eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
456eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
457eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    List<String> getEnabledOverlayPackageNames(@NonNull final String targetPackageName,
458eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final int userId) {
459eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final List<OverlayInfo> overlays = mSettings.getOverlaysForTarget(targetPackageName, userId);
460eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final List<String> paths = new ArrayList<>(overlays.size());
461eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final int N = overlays.size();
462eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        for (int i = 0; i < N; i++) {
463eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            final OverlayInfo oi = overlays.get(i);
464eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            if (oi.isEnabled()) {
465eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                paths.add(oi.packageName);
466eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            }
467eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
468eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        return paths;
469eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
470eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
471c745f42169df6687a764e48b65878f22965c1530Adam Lesinski    /**
472c745f42169df6687a764e48b65878f22965c1530Adam Lesinski     * Returns true if the settings/state was modified, false otherwise.
473c745f42169df6687a764e48b65878f22965c1530Adam Lesinski     */
474c745f42169df6687a764e48b65878f22965c1530Adam Lesinski    private boolean updateState(@Nullable final PackageInfo targetPackage,
475eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            @NonNull final PackageInfo overlayPackage, final int userId)
476c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            throws OverlayManagerSettings.BadKeyException {
4770434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok        // Static RROs targeting to "android", ie framework-res.apk, are handled by native layers.
4780434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok        if (targetPackage != null &&
4790434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok                !("android".equals(targetPackage.packageName) && overlayPackage.isStaticOverlay)) {
480eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
481eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
482eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
483c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        boolean modified = mSettings.setBaseCodePath(overlayPackage.packageName, userId,
484eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                overlayPackage.applicationInfo.getBaseCodePath());
485eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
486eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final int currentState = mSettings.getState(overlayPackage.packageName, userId);
487eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final int newState = calculateNewState(targetPackage, overlayPackage, userId);
488eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (currentState != newState) {
489eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            if (DEBUG) {
490eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                Slog.d(TAG, String.format("%s:%d: %s -> %s",
491eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                            overlayPackage.packageName, userId,
492eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                            OverlayInfo.stateToString(currentState),
493eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                            OverlayInfo.stateToString(newState)));
494eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            }
495c745f42169df6687a764e48b65878f22965c1530Adam Lesinski            modified |= mSettings.setState(overlayPackage.packageName, userId, newState);
496eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
497c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        return modified;
498eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
499eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
500eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    private int calculateNewState(@Nullable final PackageInfo targetPackage,
501eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            @NonNull final PackageInfo overlayPackage, final int userId)
502eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        throws OverlayManagerSettings.BadKeyException {
503eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (targetPackage == null) {
504eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            return STATE_MISSING_TARGET;
505eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
506eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
507eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (!mIdmapManager.idmapExists(overlayPackage, userId)) {
508eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            return STATE_NO_IDMAP;
509eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
510eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
511eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        final boolean enabled = mSettings.getEnabled(overlayPackage.packageName, userId);
512eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        return enabled ? STATE_ENABLED : STATE_DISABLED;
513eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
514eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
515eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    private void removeIdmapIfPossible(@NonNull final OverlayInfo oi) {
516eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // For a given package, all Android users share the same idmap file.
517eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // This works because Android currently does not support users to
518eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // install different versions of the same package. It also means we
519eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // cannot remove an idmap file if any user still needs it.
520eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        //
521eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // When/if the Android framework allows different versions of the same
522eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // package to be installed for different users, idmap file handling
523eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // should be revised:
524eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        //
525eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // - an idmap file should be unique for each {user, package} pair
526eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        //
527eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // - the path to the idmap file should be passed to the native Asset
528eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        //   Manager layers, just like the path to the apk is passed today
529eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        //
530eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // As part of that change, calls to this method should be replaced by
531eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // direct calls to IdmapManager.removeIdmap, without looping over all
532eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        // users.
533eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
534eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        if (!mIdmapManager.idmapExists(oi)) {
535eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            return;
536eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
537c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        final int[] userIds = mSettings.getUsers();
538c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        for (int userId : userIds) {
539eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            try {
540eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                final OverlayInfo tmp = mSettings.getOverlayInfo(oi.packageName, userId);
541eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                if (tmp != null && tmp.isEnabled()) {
542eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                    // someone is still using the idmap file -> we cannot remove it
543eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                    return;
544eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                }
545eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            } catch (OverlayManagerSettings.BadKeyException e) {
546eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                // intentionally left empty
547eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad            }
548eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        }
549eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        mIdmapManager.removeIdmap(oi, oi.userId);
550eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
551eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad
552c745f42169df6687a764e48b65878f22965c1530Adam Lesinski    interface OverlayChangeListener {
553c745f42169df6687a764e48b65878f22965c1530Adam Lesinski        void onOverlaysChanged(@NonNull String targetPackage, int userId);
554c745f42169df6687a764e48b65878f22965c1530Adam Lesinski    }
555c745f42169df6687a764e48b65878f22965c1530Adam Lesinski
556eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    interface PackageManagerHelper {
557eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        PackageInfo getPackageInfo(@NonNull String packageName, int userId);
558eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        boolean signaturesMatching(@NonNull String packageName1, @NonNull String packageName2,
559eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad                                   int userId);
560eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad        List<PackageInfo> getOverlayPackages(int userId);
561eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad    }
562eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad}
563