diff options
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/launcher3/BubbleTextView.java | 93 | ||||
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 19 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherAppState.java | 13 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherModel.java | 7 | ||||
-rw-r--r-- | src/com/android/launcher3/ShortcutInfo.java | 29 | ||||
-rw-r--r-- | src/com/android/launcher3/Workspace.java | 41 | ||||
-rw-r--r-- | src/com/android/launcher3/compat/LauncherAppsCompat.java | 7 | ||||
-rw-r--r-- | src/com/android/launcher3/compat/PackageInstallerCompat.java | 67 | ||||
-rw-r--r-- | src/com/android/launcher3/compat/PackageInstallerCompatV16.java | 170 | ||||
-rw-r--r-- | src/com/android/launcher3/compat/PackageInstallerCompatVL.java | 159 |
10 files changed, 500 insertions, 105 deletions
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index ffa7ec37e..ab94814c3 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -434,65 +434,48 @@ public class BubbleTextView extends TextView { } public void applyState() { - final int progressLevel; - final int state = getState(); - if (DEBUG) Log.d(TAG, "applying icon state: " + state); - - switch(state) { - case ShortcutInfo.PACKAGE_STATE_DEFAULT: - super.setText(mDefaultText); - progressLevel = 100; - break; - - case ShortcutInfo.PACKAGE_STATE_ENQUEUED: - setText(R.string.package_state_enqueued); - progressLevel = 0; - break; - - case ShortcutInfo.PACKAGE_STATE_DOWNLOADING: - setText(R.string.package_state_downloading); - // TODO(sunnygoyal): fix progress - progressLevel = 30; - break; - - case ShortcutInfo.PACKAGE_STATE_INSTALLING: - setText(R.string.package_state_installing); - progressLevel = 100; - break; + if (getTag() instanceof ShortcutInfo) { + ShortcutInfo info = (ShortcutInfo) getTag(); + final int state = info.getState(); + + final int progressLevel; + if (DEBUG) Log.d(TAG, "applying icon state: " + state); + + switch(state) { + case ShortcutInfo.PACKAGE_STATE_DEFAULT: + progressLevel = 100; + break; + + case ShortcutInfo.PACKAGE_STATE_INSTALLING: + setText(R.string.package_state_installing); + progressLevel = info.getProgress(); + break; + + case ShortcutInfo.PACKAGE_STATE_ERROR: + case ShortcutInfo.PACKAGE_STATE_UNKNOWN: + default: + progressLevel = 0; + setText(R.string.package_state_unknown); + break; + } - case ShortcutInfo.PACKAGE_STATE_ERROR: - setText(R.string.package_state_error); - progressLevel = 0; - break; + Drawable[] drawables = getCompoundDrawables(); + Drawable top = drawables[1]; + if (top != null) { + final PreloadIconDrawable preloadDrawable; + if (top instanceof PreloadIconDrawable) { + preloadDrawable = (PreloadIconDrawable) top; + } else { + preloadDrawable = new PreloadIconDrawable(top, getResources()); + setCompoundDrawables(drawables[0], preloadDrawable, drawables[2], drawables[3]); + } - case ShortcutInfo.PACKAGE_STATE_UNKNOWN: - default: - progressLevel = 0; - setText(R.string.package_state_unknown); - break; - } + preloadDrawable.setLevel(progressLevel); + if (state == ShortcutInfo.PACKAGE_STATE_DEFAULT) { + preloadDrawable.maybePerformFinishedAnimation(); + } - Drawable[] drawables = getCompoundDrawables(); - Drawable top = drawables[1]; - if ((top != null) && !(top instanceof PreloadIconDrawable)) { - top = new PreloadIconDrawable(top, getResources()); - setCompoundDrawables(drawables[0], top, drawables[2], drawables[3]); - } - if (top != null) { - top.setLevel(progressLevel); - if ((top instanceof PreloadIconDrawable) - && (state == ShortcutInfo.PACKAGE_STATE_DEFAULT)) { - ((PreloadIconDrawable) top).maybePerformFinishedAnimation(); } } } - - private int getState() { - if (! (getTag() instanceof ShortcutInfo)) { - return ShortcutInfo.PACKAGE_STATE_DEFAULT; - } else { - ShortcutInfo info = (ShortcutInfo) getTag(); - return info.getState(); - } - } } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index a5bf690d7..b5bed4cdf 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -82,10 +82,9 @@ import android.view.Menu; import android.view.MotionEvent; import android.view.Surface; import android.view.View; -import android.view.ViewAnimationUtils; -import android.view.Window; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; +import android.view.ViewAnimationUtils; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; @@ -93,9 +92,7 @@ import android.view.Window; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; -import android.view.animation.LinearInterpolator; import android.view.inputmethod.InputMethodManager; import android.widget.Advanceable; import android.widget.FrameLayout; @@ -107,10 +104,10 @@ import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.PagedView.PageSwitchListener; import com.android.launcher3.compat.LauncherActivityInfoCompat; import com.android.launcher3.compat.LauncherAppsCompat; +import com.android.launcher3.compat.PackageInstallerCompat; +import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; -import com.android.launcher3.DropTarget.DragObject; -import com.android.launcher3.PagedView.PageSwitchListener; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -1055,12 +1052,15 @@ public class Launcher extends Activity } mWorkspace.updateInteractionForState(); mWorkspace.onResume(); + + PackageInstallerCompat.getInstance(this).onResume(); } @Override protected void onPause() { // Ensure that items added to Launcher are queued until Launcher returns InstallShortcutReceiver.enableInstallQueue(); + PackageInstallerCompat.getInstance(this).onPause(); super.onPause(); mPaused = true; @@ -2028,6 +2028,7 @@ public class Launcher extends Activity mWorkspace = null; mDragController = null; + PackageInstallerCompat.getInstance(this).onStop(); LauncherAnimUtils.onDestroyActivity(); } @@ -4478,6 +4479,7 @@ public class Launcher extends Activity mWorkspace.getUniqueComponents(true, null); mIntentsOnWorkspaceFromUpgradePath = mWorkspace.getUniqueComponents(true, null); } + PackageInstallerCompat.getInstance(this).onFinishBind(); } private void sendLoadingCompleteBroadcastIfNecessary() { @@ -4591,9 +4593,10 @@ public class Launcher extends Activity * * Implementation of the method from LauncherModel.Callbacks. */ - public void updatePackageState(String pkgName, int state) { + @Override + public void updatePackageState(ArrayList<PackageInstallInfo> installInfo) { if (mWorkspace != null) { - mWorkspace.updatePackageState(pkgName, state); + mWorkspace.updatePackageState(installInfo); } } diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index 27bcd8172..4ab4e4bea 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -17,7 +17,11 @@ package com.android.launcher3; import android.app.SearchManager; -import android.content.*; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; @@ -25,8 +29,10 @@ import android.os.Handler; import android.util.Log; import com.android.launcher3.compat.LauncherAppsCompat; +import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import java.lang.ref.WeakReference; +import java.util.ArrayList; public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks { private static final String TAG = "LauncherAppState"; @@ -251,8 +257,7 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks { return getInstance().mBuildInfo.isDogfoodBuild(); } - public void setPackageState(String pkgName, int state) { - if (DEBUG) Log.d(TAG, "setPackageState(" + pkgName + ", " + state + ")"); - mModel.setPackageState(pkgName, state); + public void setPackageState(ArrayList<PackageInstallInfo> installInfo) { + mModel.setPackageState(installInfo); } } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index e115bf11c..86edaef44 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -55,6 +55,7 @@ import android.util.Pair; import com.android.launcher3.InstallWidgetReceiver.WidgetMimeTypeHandlerData; import com.android.launcher3.compat.LauncherActivityInfoCompat; import com.android.launcher3.compat.LauncherAppsCompat; +import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; @@ -195,7 +196,7 @@ public class LauncherModel extends BroadcastReceiver ArrayList<ItemInfo> addAnimated, ArrayList<AppInfo> addedApps); public void bindAppsUpdated(ArrayList<AppInfo> apps); - public void updatePackageState(String pkgName, int state); + public void updatePackageState(ArrayList<PackageInstallInfo> installInfo); public void bindComponentsRemoved(ArrayList<String> packageNames, ArrayList<AppInfo> appInfos, UserHandleCompat user); public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts); @@ -332,13 +333,13 @@ public class LauncherModel extends BroadcastReceiver return null; } - public void setPackageState(final String pkgName, final int state) { + public void setPackageState(final ArrayList<PackageInstallInfo> installInfo) { // Process the updated package state Runnable r = new Runnable() { public void run() { Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null; if (callbacks != null) { - callbacks.updatePackageState(pkgName, state); + callbacks.updatePackageState(installInfo); } } }; diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java index dc019b272..612b0a5aa 100644 --- a/src/com/android/launcher3/ShortcutInfo.java +++ b/src/com/android/launcher3/ShortcutInfo.java @@ -42,13 +42,7 @@ public class ShortcutInfo extends ItemInfo { public static final int PACKAGE_STATE_DEFAULT = 0; /** {@link #mState} meaning some external entity has promised to install this package. */ - public static final int PACKAGE_STATE_ENQUEUED = 1; - - /** {@link #mState} meaning but some external entity is downloading this package. */ - public static final int PACKAGE_STATE_DOWNLOADING = 2; - - /** {@link #mState} meaning some external entity is installing this package. */ - public static final int PACKAGE_STATE_INSTALLING = 3; + public static final int PACKAGE_STATE_INSTALLING = 1; /** * The intent used to start the application. @@ -89,6 +83,11 @@ public class ShortcutInfo extends ItemInfo { */ protected int mState; + /** + * The installation progress [0-100] of the package that this shortcut represents. + */ + protected int mProgress; + long firstInstallTime; int flags = 0; @@ -237,16 +236,24 @@ public class ShortcutInfo extends ItemInfo { public boolean isAbandoned() { return isPromise() - && (mState == ShortcutInfo.PACKAGE_STATE_ERROR - || mState == ShortcutInfo.PACKAGE_STATE_UNKNOWN); + && (mState == PACKAGE_STATE_ERROR + || mState == PACKAGE_STATE_UNKNOWN); } - public int getState() { - return mState; + public int getProgress() { + return mProgress; + } + + public void setProgress(int progress) { + mProgress = progress; } public void setState(int state) { mState = state; } + + public int getState() { + return mState; + } } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 6d9b34e21..7c8708b50 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -67,6 +67,7 @@ import android.widget.TextView; import com.android.launcher3.FolderIcon.FolderRingAnimator; import com.android.launcher3.Launcher.CustomContentCallbacks; import com.android.launcher3.LauncherSettings.Favorites; +import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import com.android.launcher3.compat.UserHandleCompat; import java.util.ArrayList; @@ -4864,26 +4865,32 @@ public class Workspace extends SmoothPagedView } } - public void updatePackageState(final String pkgName, final int state) { - mapOverItems(MAP_RECURSE, new ItemOperator() { - @Override - public boolean evaluate(ItemInfo info, View v, View parent) { - if (info instanceof ShortcutInfo - && ((ShortcutInfo) info).isPromiseFor(pkgName) - && v instanceof BubbleTextView) { - ((ShortcutInfo) info).setState(state); - ((BubbleTextView)v).applyState(); + public void updatePackageState(ArrayList<PackageInstallInfo> installInfos) { + HashSet<String> completedPackages = new HashSet<>(); + + for (final PackageInstallInfo installInfo : installInfos) { + mapOverItems(MAP_RECURSE, new ItemOperator() { + @Override + public boolean evaluate(ItemInfo info, View v, View parent) { + if (info instanceof ShortcutInfo + && ((ShortcutInfo) info).isPromiseFor(installInfo.packageName) + && v instanceof BubbleTextView) { + ((ShortcutInfo) info).setProgress(installInfo.progress); + ((ShortcutInfo) info).setState(installInfo.state); + ((BubbleTextView)v).applyState(); + } + // process all the shortcuts + return false; } - // process all the shortcuts - return false; + }); + + if (installInfo.state == ShortcutInfo.PACKAGE_STATE_DEFAULT) { + completedPackages.add(installInfo.packageName); } - }); + } - if (state == ShortcutInfo.PACKAGE_STATE_DEFAULT) { - // Update any pending widget - HashSet<String> packages = new HashSet<String>(); - packages.add(pkgName); - restorePendingWidgets(packages); + if (!completedPackages.isEmpty()) { + restorePendingWidgets(completedPackages); } } diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java index 8d978d4a3..cc0203d27 100644 --- a/src/com/android/launcher3/compat/LauncherAppsCompat.java +++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java @@ -20,17 +20,10 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; -import android.os.UserHandle; -import android.os.UserManager; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; public abstract class LauncherAppsCompat { diff --git a/src/com/android/launcher3/compat/PackageInstallerCompat.java b/src/com/android/launcher3/compat/PackageInstallerCompat.java new file mode 100644 index 000000000..89a2157eb --- /dev/null +++ b/src/com/android/launcher3/compat/PackageInstallerCompat.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.compat; + +import android.content.Context; + +import com.android.launcher3.Utilities; + +public abstract class PackageInstallerCompat { + + private static final Object sInstanceLock = new Object(); + private static PackageInstallerCompat sInstance; + + public static PackageInstallerCompat getInstance(Context context) { + synchronized (sInstanceLock) { + if (sInstance == null) { + if (Utilities.isLmp()) { + sInstance = new PackageInstallerCompatVL(context); + } else { + sInstance = new PackageInstallerCompatV16(context) { }; + } + } + return sInstance; + } + } + + public abstract void onPause(); + + public abstract void onResume(); + + public abstract void onFinishBind(); + + public abstract void onStop(); + + public abstract void recordPackageUpdate(String packageName, int state, int progress); + + public static final class PackageInstallInfo { + public final String packageName; + + public int state; + public int progress; + + public PackageInstallInfo(String packageName) { + this.packageName = packageName; + } + + public PackageInstallInfo(String packageName, int state, int progress) { + this.packageName = packageName; + this.state = state; + this.progress = progress; + } + } +} diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatV16.java b/src/com/android/launcher3/compat/PackageInstallerCompatV16.java new file mode 100644 index 000000000..653a88c7d --- /dev/null +++ b/src/com/android/launcher3/compat/PackageInstallerCompatV16.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.compat; + +import android.content.Context; +import android.content.SharedPreferences; +import android.text.TextUtils; +import android.util.Log; + +import com.android.launcher3.LauncherAppState; +import com.android.launcher3.ShortcutInfo; + +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONStringer; +import org.json.JSONTokener; + +import java.util.ArrayList; + +public class PackageInstallerCompatV16 extends PackageInstallerCompat { + + private static final String TAG = "PackageInstallerCompatV16"; + private static final boolean DEBUG = false; + + private static final String KEY_PROGRESS = "progress"; + private static final String KEY_STATE = "state"; + + private static final String PREFS = + "com.android.launcher3.compat.PackageInstallerCompatV16.queue"; + + protected final SharedPreferences mPrefs; + + boolean mUseQueue; + boolean mFinishedBind; + boolean mReplayPending; + + PackageInstallerCompatV16(Context context) { + mPrefs = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE); + } + + @Override + public void onPause() { + mUseQueue = true; + if (DEBUG) Log.d(TAG, "updates paused"); + } + + @Override + public void onResume() { + mUseQueue = false; + if (mFinishedBind) { + replayUpdates(); + } + } + + @Override + public void onFinishBind() { + mFinishedBind = true; + if (!mUseQueue) { + replayUpdates(); + } + } + + @Override + public void onStop() { } + + private void replayUpdates() { + if (DEBUG) Log.d(TAG, "updates resumed"); + LauncherAppState app = LauncherAppState.getInstanceNoCreate(); + if (app == null) { + mReplayPending = true; // try again later + if (DEBUG) Log.d(TAG, "app is null, delaying send"); + return; + } + mReplayPending = false; + ArrayList<PackageInstallInfo> updates = new ArrayList<>(); + for (String packageName: mPrefs.getAll().keySet()) { + final String json = mPrefs.getString(packageName, null); + if (!TextUtils.isEmpty(json)) { + updates.add(infoFromJson(packageName, json)); + } + } + if (!updates.isEmpty()) { + sendUpdate(app, updates); + } + } + + /** + * This should be called by the implementations to register a package update. + */ + @Override + public synchronized void recordPackageUpdate(String packageName, int state, int progress) { + SharedPreferences.Editor editor = mPrefs.edit(); + PackageInstallInfo installInfo = new PackageInstallInfo(packageName); + installInfo.progress = progress; + installInfo.state = state; + if (state == ShortcutInfo.PACKAGE_STATE_DEFAULT) { + // no longer necessary to track this package + editor.remove(packageName); + if (DEBUG) Log.d(TAG, "no longer tracking " + packageName); + } else { + editor.putString(packageName, infoToJson(installInfo)); + if (DEBUG) + Log.d(TAG, "saved state: " + infoToJson(installInfo) + + " for package: " + packageName); + + } + editor.commit(); + + if (!mUseQueue) { + if (mReplayPending) { + replayUpdates(); + } else { + LauncherAppState app = LauncherAppState.getInstanceNoCreate(); + ArrayList<PackageInstallInfo> update = new ArrayList<>(); + update.add(installInfo); + sendUpdate(app, update); + } + } + } + + private void sendUpdate(LauncherAppState app, ArrayList<PackageInstallInfo> updates) { + if (app == null) { + mReplayPending = true; // try again later + if (DEBUG) Log.d(TAG, "app is null, delaying send"); + } else { + app.setPackageState(updates); + } + } + + private static PackageInstallInfo infoFromJson(String packageName, String json) { + PackageInstallInfo info = new PackageInstallInfo(packageName); + try { + JSONObject object = (JSONObject) new JSONTokener(json).nextValue(); + info.state = object.getInt(KEY_STATE); + info.progress = object.getInt(KEY_PROGRESS); + } catch (JSONException e) { + Log.e(TAG, "failed to deserialize app state update", e); + } + return info; + } + + private static String infoToJson(PackageInstallInfo info) { + String value = null; + try { + JSONStringer json = new JSONStringer() + .object() + .key(KEY_STATE).value(info.state) + .key(KEY_PROGRESS).value(info.progress) + .endObject(); + value = json.toString(); + } catch (JSONException e) { + Log.e(TAG, "failed to serialize app state update", e); + } + return value; + } +} diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java new file mode 100644 index 000000000..7f6302f14 --- /dev/null +++ b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.compat; + +import android.content.Context; +import android.content.pm.InstallSessionInfo; +import android.content.pm.PackageInstaller; +import android.content.pm.PackageInstaller.SessionCallback; +import android.util.Log; +import android.util.SparseArray; + +import com.android.launcher3.LauncherAppState; +import com.android.launcher3.ShortcutInfo; + +import java.util.ArrayList; + +public class PackageInstallerCompatVL extends PackageInstallerCompat { + + private static final String TAG = "PackageInstallerCompatVL"; + private static final boolean DEBUG = false; + + private final SparseArray<InstallSessionInfo> mPendingReplays = new SparseArray<>(); + private final PackageInstaller mInstaller; + + private boolean mResumed; + private boolean mBound; + + PackageInstallerCompatVL(Context context) { + mInstaller = context.getPackageManager().getPackageInstaller(); + + mResumed = false; + mBound = false; + + mInstaller.addSessionCallback(mCallback); + // On start, send updates for all active sessions + for (InstallSessionInfo info : mInstaller.getAllSessions()) { + mPendingReplays.append(info.getSessionId(), info); + } + } + + @Override + public void onStop() { + mInstaller.removeSessionCallback(mCallback); + } + + @Override + public void onFinishBind() { + mBound = true; + replayUpdates(null); + } + + @Override + public void onPause() { + mResumed = false; + } + + @Override + public void onResume() { + mResumed = true; + replayUpdates(null); + } + + @Override + public void recordPackageUpdate(String packageName, int state, int progress) { + // No op + } + + private void replayUpdates(PackageInstallInfo newInfo) { + if (DEBUG) Log.d(TAG, "updates resumed"); + if (!mResumed || !mBound) { + // Not yet ready + return; + } + if ((mPendingReplays.size() == 0) && (newInfo == null)) { + // Nothing to update + return; + } + + LauncherAppState app = LauncherAppState.getInstanceNoCreate(); + if (app == null) { + // Try again later + if (DEBUG) Log.d(TAG, "app is null, delaying send"); + return; + } + + ArrayList<PackageInstallInfo> updates = new ArrayList<>(); + if (newInfo != null) { + updates.add(newInfo); + } + for (int i = mPendingReplays.size() - 1; i > 0; i--) { + InstallSessionInfo session = mPendingReplays.valueAt(i); + if (session.getAppPackageName() != null) { + updates.add(new PackageInstallInfo(session.getAppPackageName(), + ShortcutInfo.PACKAGE_STATE_INSTALLING, + (int) (session.getProgress() * 100))); + } + } + mPendingReplays.clear(); + if (!updates.isEmpty()) { + app.setPackageState(updates); + } + } + + private final SessionCallback mCallback = new SessionCallback() { + + @Override + public void onCreated(int sessionId) { + InstallSessionInfo session = mInstaller.getSessionInfo(sessionId); + if (session != null) { + mPendingReplays.put(sessionId, session); + replayUpdates(null); + } + } + + @Override + public void onFinished(int sessionId, boolean success) { + mPendingReplays.remove(sessionId); + InstallSessionInfo session = mInstaller.getSessionInfo(sessionId); + if ((session != null) && (session.getAppPackageName() != null)) { + // Replay all updates with a one time update for this installed package. No + // need to store this record for future updates, as the app list will get + // refreshed on resume. + replayUpdates(new PackageInstallInfo(session.getAppPackageName(), + success ? ShortcutInfo.PACKAGE_STATE_DEFAULT + : ShortcutInfo.PACKAGE_STATE_ERROR, 0)); + } + } + + @Override + public void onProgressChanged(int sessionId, float progress) { + InstallSessionInfo session = mInstaller.getSessionInfo(sessionId); + if (session != null) { + mPendingReplays.put(sessionId, session); + replayUpdates(null); + } + } + + @Override + public void onOpened(int sessionId) { } + + @Override + public void onClosed(int sessionId) { } + + }; +} |