• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.launcher3.compat;
18 
19 import android.content.Context;
20 import android.content.pm.ApplicationInfo;
21 import android.content.pm.PackageInstaller;
22 import android.content.pm.PackageInstaller.SessionCallback;
23 import android.content.pm.PackageInstaller.SessionInfo;
24 import android.os.Handler;
25 import android.os.Process;
26 import android.os.UserHandle;
27 import android.text.TextUtils;
28 import android.util.SparseArray;
29 
30 import com.android.launcher3.IconCache;
31 import com.android.launcher3.LauncherAppState;
32 import com.android.launcher3.LauncherModel;
33 import com.android.launcher3.config.FeatureFlags;
34 import com.android.launcher3.util.Thunk;
35 
36 import java.util.ArrayList;
37 import java.util.HashMap;
38 import java.util.Iterator;
39 import java.util.List;
40 
41 public class PackageInstallerCompatVL extends PackageInstallerCompat {
42 
43     private static final boolean DEBUG = false;
44 
45     @Thunk final SparseArray<String> mActiveSessions = new SparseArray<>();
46 
47     @Thunk final PackageInstaller mInstaller;
48     private final IconCache mCache;
49     private final Handler mWorker;
50     private final Context mAppContext;
51     private final HashMap<String,Boolean> mSessionVerifiedMap = new HashMap<>();
52 
PackageInstallerCompatVL(Context context)53     PackageInstallerCompatVL(Context context) {
54         mAppContext = context.getApplicationContext();
55         mInstaller = context.getPackageManager().getPackageInstaller();
56         mCache = LauncherAppState.getInstance(context).getIconCache();
57         mWorker = new Handler(LauncherModel.getWorkerLooper());
58         mInstaller.registerSessionCallback(mCallback, mWorker);
59     }
60 
61     @Override
updateAndGetActiveSessionCache()62     public HashMap<String, SessionInfo> updateAndGetActiveSessionCache() {
63         HashMap<String, SessionInfo> activePackages = new HashMap<>();
64         UserHandle user = Process.myUserHandle();
65         for (SessionInfo info : getAllVerifiedSessions()) {
66             addSessionInfoToCache(info, user);
67             if (info.getAppPackageName() != null) {
68                 activePackages.put(info.getAppPackageName(), info);
69                 mActiveSessions.put(info.getSessionId(), info.getAppPackageName());
70             }
71         }
72         return activePackages;
73     }
74 
addSessionInfoToCache(SessionInfo info, UserHandle user)75     @Thunk void addSessionInfoToCache(SessionInfo info, UserHandle user) {
76         String packageName = info.getAppPackageName();
77         if (packageName != null) {
78             mCache.cachePackageInstallInfo(packageName, user, info.getAppIcon(),
79                     info.getAppLabel());
80         }
81     }
82 
83     @Override
onStop()84     public void onStop() {
85         mInstaller.unregisterSessionCallback(mCallback);
86     }
87 
sendUpdate(PackageInstallInfo info)88     @Thunk void sendUpdate(PackageInstallInfo info) {
89         LauncherAppState app = LauncherAppState.getInstanceNoCreate();
90         if (app != null) {
91             app.getModel().setPackageState(info);
92         }
93     }
94 
95     private final SessionCallback mCallback = new SessionCallback() {
96 
97         @Override
98         public void onCreated(int sessionId) {
99             SessionInfo sessionInfo = pushSessionDisplayToLauncher(sessionId);
100             if (FeatureFlags.LAUNCHER3_PROMISE_APPS_IN_ALL_APPS && sessionInfo != null) {
101                 LauncherAppState app = LauncherAppState.getInstanceNoCreate();
102                 if (app != null) {
103                     app.getModel().onInstallSessionCreated(
104                             PackageInstallInfo.fromInstallingState(sessionInfo));
105                 }
106             }
107         }
108 
109         @Override
110         public void onFinished(int sessionId, boolean success) {
111             // For a finished session, we can't get the session info. So use the
112             // packageName from our local cache.
113             String packageName = mActiveSessions.get(sessionId);
114             mActiveSessions.remove(sessionId);
115 
116             if (packageName != null) {
117                 sendUpdate(PackageInstallInfo.fromState(
118                         success ? STATUS_INSTALLED : STATUS_FAILED,
119                         packageName));
120             }
121         }
122 
123         @Override
124         public void onProgressChanged(int sessionId, float progress) {
125             SessionInfo session = verify(mInstaller.getSessionInfo(sessionId));
126             if (session != null && session.getAppPackageName() != null) {
127                 sendUpdate(PackageInstallInfo.fromInstallingState(session));
128             }
129         }
130 
131         @Override
132         public void onActiveChanged(int sessionId, boolean active) { }
133 
134         @Override
135         public void onBadgingChanged(int sessionId) {
136             pushSessionDisplayToLauncher(sessionId);
137         }
138 
139         private SessionInfo pushSessionDisplayToLauncher(int sessionId) {
140             SessionInfo session = verify(mInstaller.getSessionInfo(sessionId));
141             if (session != null && session.getAppPackageName() != null) {
142                 mActiveSessions.put(sessionId, session.getAppPackageName());
143                 addSessionInfoToCache(session, Process.myUserHandle());
144                 LauncherAppState app = LauncherAppState.getInstanceNoCreate();
145                 if (app != null) {
146                     app.getModel().updateSessionDisplayInfo(session.getAppPackageName());
147                 }
148                 return session;
149             }
150             return null;
151         }
152     };
153 
verify(PackageInstaller.SessionInfo sessionInfo)154     private PackageInstaller.SessionInfo verify(PackageInstaller.SessionInfo sessionInfo) {
155         if (sessionInfo == null
156                 || sessionInfo.getInstallerPackageName() == null
157                 || TextUtils.isEmpty(sessionInfo.getAppPackageName())) {
158             return null;
159         }
160         String pkg = sessionInfo.getInstallerPackageName();
161         synchronized (mSessionVerifiedMap) {
162             if (!mSessionVerifiedMap.containsKey(pkg)) {
163                 LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mAppContext);
164                 boolean hasSystemFlag = launcherApps.getApplicationInfo(pkg,
165                         ApplicationInfo.FLAG_SYSTEM, Process.myUserHandle()) != null;
166                 mSessionVerifiedMap.put(pkg, DEBUG || hasSystemFlag);
167             }
168         }
169         return mSessionVerifiedMap.get(pkg) ? sessionInfo : null;
170     }
171 
172     @Override
getAllVerifiedSessions()173     public List<SessionInfo> getAllVerifiedSessions() {
174         List<SessionInfo> list = new ArrayList<>(mInstaller.getAllSessions());
175         Iterator<SessionInfo> it = list.iterator();
176         while (it.hasNext()) {
177             if (verify(it.next()) == null) {
178                 it.remove();
179             }
180         }
181         return list;
182     }
183 }
184