PackageInstallerCompatVL.java revision a22666f68151269853e7ab6ab696ee6361bac793
1/*
2 * Copyright (C) 2014 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.launcher3.compat;
18
19import android.content.Context;
20import android.content.pm.PackageInstaller;
21import android.content.pm.PackageInstaller.SessionCallback;
22import android.content.pm.PackageInstaller.SessionInfo;
23import android.util.Log;
24import android.util.SparseArray;
25
26import com.android.launcher3.IconCache;
27import com.android.launcher3.LauncherAppState;
28
29import java.util.ArrayList;
30import java.util.HashSet;
31
32public class PackageInstallerCompatVL extends PackageInstallerCompat {
33
34    private static final String TAG = "PackageInstallerCompatVL";
35    private static final boolean DEBUG = false;
36
37    private final SparseArray<SessionInfo> mPendingReplays = new SparseArray<SessionInfo>();
38    private final HashSet<String> mPendingBadgeUpdates = new HashSet<String>();
39    private final PackageInstaller mInstaller;
40    private final IconCache mCache;
41
42    private boolean mResumed;
43    private boolean mBound;
44
45    PackageInstallerCompatVL(Context context) {
46        mInstaller = context.getPackageManager().getPackageInstaller();
47        LauncherAppState.setApplicationContext(context.getApplicationContext());
48        mCache = LauncherAppState.getInstance().getIconCache();
49
50        mResumed = false;
51        mBound = false;
52
53        mInstaller.registerSessionCallback(mCallback);
54
55        // On start, send updates for all active sessions
56        for (SessionInfo info : mInstaller.getAllSessions()) {
57            mPendingReplays.append(info.getSessionId(), info);
58        }
59    }
60
61    @Override
62    public void updateActiveSessionCache() {
63        UserHandleCompat user = UserHandleCompat.myUserHandle();
64        for (SessionInfo info : mInstaller.getAllSessions()) {
65            addSessionInfoToCahce(info, user);
66        }
67    }
68
69    private void addSessionInfoToCahce(SessionInfo info, UserHandleCompat user) {
70        String packageName = info.getAppPackageName();
71        if (packageName != null) {
72            mCache.cachePackageInstallInfo(packageName, user, info.getAppIcon(),
73                    info.getAppLabel());
74        }
75    }
76
77    @Override
78    public void onStop() {
79        mInstaller.unregisterSessionCallback(mCallback);
80    }
81
82    @Override
83    public void onFinishBind() {
84        mBound = true;
85        replayUpdates(null);
86    }
87
88    @Override
89    public void onPause() {
90        mResumed = false;
91    }
92
93    @Override
94    public void onResume() {
95        mResumed = true;
96        replayUpdates(null);
97    }
98
99    @Override
100    public void recordPackageUpdate(String packageName, int state, int progress) {
101        // No op
102    }
103
104    private void replayUpdates(PackageInstallInfo newInfo) {
105        if (DEBUG) Log.d(TAG, "updates resumed");
106        if (!mResumed || !mBound) {
107            // Not yet ready
108            return;
109        }
110        if ((mPendingReplays.size() == 0) && (newInfo == null)) {
111            // Nothing to update
112            return;
113        }
114
115        LauncherAppState app = LauncherAppState.getInstanceNoCreate();
116        if (app == null) {
117            // Try again later
118            if (DEBUG) Log.d(TAG, "app is null, delaying send");
119            return;
120        }
121
122        ArrayList<PackageInstallInfo> updates = new ArrayList<PackageInstallInfo>();
123        if ((newInfo != null) && (newInfo.state != STATUS_INSTALLED)) {
124            updates.add(newInfo);
125        }
126        for (int i = mPendingReplays.size() - 1; i >= 0; i--) {
127            SessionInfo session = mPendingReplays.valueAt(i);
128            if (session.getAppPackageName() != null) {
129                updates.add(new PackageInstallInfo(session.getAppPackageName(),
130                        STATUS_INSTALLING,
131                        (int) (session.getProgress() * 100)));
132            }
133        }
134        mPendingReplays.clear();
135        if (!updates.isEmpty()) {
136            app.setPackageState(updates);
137        }
138
139        if (!mPendingBadgeUpdates.isEmpty()) {
140            for (String pkg : mPendingBadgeUpdates) {
141                app.updatePackageBadge(pkg);
142            }
143            mPendingBadgeUpdates.clear();
144        }
145    }
146
147    private final SessionCallback mCallback = new SessionCallback() {
148
149        @Override
150        public void onCreated(int sessionId) {
151            pushSessionBadgeToLauncher(sessionId);
152        }
153
154        @Override
155        public void onFinished(int sessionId, boolean success) {
156            mPendingReplays.remove(sessionId);
157            SessionInfo session = mInstaller.getSessionInfo(sessionId);
158            if ((session != null) && (session.getAppPackageName() != null)) {
159                mPendingBadgeUpdates.remove(session.getAppPackageName());
160                // Replay all updates with a one time update for this installed package. No
161                // need to store this record for future updates, as the app list will get
162                // refreshed on resume.
163                replayUpdates(new PackageInstallInfo(session.getAppPackageName(),
164                        success ? STATUS_INSTALLED : STATUS_FAILED, 0));
165            }
166        }
167
168        @Override
169        public void onProgressChanged(int sessionId, float progress) {
170            SessionInfo session = mInstaller.getSessionInfo(sessionId);
171            if (session != null) {
172                mPendingReplays.put(sessionId, session);
173                replayUpdates(null);
174            }
175        }
176
177        @Override
178        public void onActiveChanged(int sessionId, boolean active) { }
179
180        @Override
181        public void onBadgingChanged(int sessionId) {
182            pushSessionBadgeToLauncher(sessionId);
183        }
184
185        private void pushSessionBadgeToLauncher(int sessionId) {
186            SessionInfo session = mInstaller.getSessionInfo(sessionId);
187            if (session != null) {
188                addSessionInfoToCahce(session, UserHandleCompat.myUserHandle());
189                if (session.getAppPackageName() != null) {
190                    mPendingBadgeUpdates.add(session.getAppPackageName());
191                }
192                mPendingReplays.put(sessionId, session);
193                replayUpdates(null);
194            }
195        }
196    };
197}
198