summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/BubbleTextView.java28
-rw-r--r--src/com/android/launcher3/DeleteDropTarget.java22
-rw-r--r--src/com/android/launcher3/FolderIcon.java9
-rw-r--r--src/com/android/launcher3/Launcher.java9
-rw-r--r--src/com/android/launcher3/LauncherModel.java126
-rw-r--r--src/com/android/launcher3/PreloadIconDrawable.java168
-rw-r--r--src/com/android/launcher3/ShortcutInfo.java11
-rw-r--r--src/com/android/launcher3/StartupReceiver.java15
-rw-r--r--src/com/android/launcher3/Workspace.java12
-rw-r--r--src/com/android/launcher3/compat/UserHandleCompat.java13
10 files changed, 353 insertions, 60 deletions
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 57dcea044..3f619a812 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -136,7 +136,8 @@ public class BubbleTextView extends TextView {
setContentDescription(info.contentDescription);
}
setTag(info);
- if (info.isPromise()) {
+
+ if (info.wasPromise) {
applyState();
}
}
@@ -431,42 +432,55 @@ public class BubbleTextView extends TextView {
}
public void applyState() {
- int alpha = getResources().getInteger(R.integer.promise_icon_alpha);
+ 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);
- alpha = 255;
+ 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;
case ShortcutInfo.PACKAGE_STATE_ERROR:
setText(R.string.package_state_error);
+ progressLevel = 0;
break;
case ShortcutInfo.PACKAGE_STATE_UNKNOWN:
default:
+ progressLevel = 0;
setText(R.string.package_state_unknown);
break;
}
- if (DEBUG) Log.d(TAG, "setting icon alpha to: " + alpha);
+
Drawable[] drawables = getCompoundDrawables();
- for (int i = 0; i < drawables.length; i++) {
- if (drawables[i] != null) {
- drawables[i].setAlpha(alpha);
+ 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();
}
}
}
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 20546b8d8..3d45432c2 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -187,11 +187,6 @@ public class DeleteDropTarget extends ButtonDropTarget {
if (!willAcceptDrop(info) || isAllAppsWidget(source, info)) {
isVisible = false;
}
- if (useUninstallLabel &&
- !(((ItemInfo) info).user.equals(UserHandleCompat.myUserHandle()))) {
- // Don't support uninstall for apps from other profiles.
- isVisible = false;
- }
if (useUninstallLabel) {
setCompoundDrawablesRelativeWithIntrinsicBounds(mUninstallDrawable, null, null, null);
@@ -287,19 +282,16 @@ public class DeleteDropTarget extends ButtonDropTarget {
if (isAllAppsApplication(d.dragSource, item)) {
// Uninstall the application if it is being dragged from AppsCustomize
AppInfo appInfo = (AppInfo) item;
- // We don't support uninstalling apps from other profiles.
- if (item.user.equals(UserHandleCompat.myUserHandle())) {
- mLauncher.startApplicationUninstallActivity(appInfo.componentName, appInfo.flags);
- }
+ mLauncher.startApplicationUninstallActivity(appInfo.componentName, appInfo.flags,
+ appInfo.user);
} else if (isUninstallFromWorkspace(d)) {
ShortcutInfo shortcut = (ShortcutInfo) item;
- // We don't support uninstalling apps from other profiles.
- if (shortcut.intent != null && shortcut.intent.getComponent() != null &&
- shortcut.user.equals(UserHandleCompat.myUserHandle())) {
+ if (shortcut.intent != null && shortcut.intent.getComponent() != null) {
final ComponentName componentName = shortcut.intent.getComponent();
final DragSource dragSource = d.dragSource;
- mWaitingForUninstall =
- mLauncher.startApplicationUninstallActivity(componentName, shortcut.flags);
+ final UserHandleCompat user = shortcut.user;
+ mWaitingForUninstall = mLauncher.startApplicationUninstallActivity(
+ componentName, shortcut.flags, user);
if (mWaitingForUninstall) {
final Runnable checkIfUninstallWasSuccess = new Runnable() {
@Override
@@ -307,7 +299,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
mWaitingForUninstall = false;
String packageName = componentName.getPackageName();
boolean uninstallSuccessful = !AllAppsList.packageHasActivities(
- getContext(), packageName, UserHandleCompat.myUserHandle());
+ getContext(), packageName, user);
if (dragSource instanceof Folder) {
((Folder) dragSource).
onUninstallActivityReturned(uninstallSuccessful);
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index ab8976a59..4f674f55a 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -605,7 +605,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
computePreviewDrawingParams(mAnimParams.drawable);
} else {
v = (TextView) items.get(0);
- d = v.getCompoundDrawables()[1];
+ d = getTopDrawable(v);
computePreviewDrawingParams(d);
}
@@ -614,7 +614,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
for (int i = nItemsInPreview - 1; i >= 0; i--) {
v = (TextView) items.get(i);
if (!mHiddenItems.contains(v.getTag())) {
- d = v.getCompoundDrawables()[1];
+ d = getTopDrawable(v);
mParams = computePreviewItemDrawingParams(i, mParams);
mParams.drawable = d;
drawPreviewItem(canvas, mParams);
@@ -625,6 +625,11 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
}
+ private Drawable getTopDrawable(TextView v) {
+ Drawable d = v.getCompoundDrawables()[1];
+ return (d instanceof PreloadIconDrawable) ? ((PreloadIconDrawable) d).mIcon : d;
+ }
+
private void animateFirstItem(final Drawable d, int duration, final boolean reverse,
final Runnable onCompleteRunnable) {
final PreviewItemDrawingParams finalParams = computePreviewItemDrawingParams(0, null);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index a85b5b18d..951b5d459 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1089,6 +1089,9 @@ public class Launcher extends Activity
// Custom content scroll progress changed. From 0 (not showing) to 1 (fully showing).
public void onScrollProgressChanged(float progress);
+
+ // Indicates whether the user is allowed to scroll away from the custom content.
+ boolean isScrollingAllowed();
}
protected boolean hasSettings() {
@@ -2718,7 +2721,8 @@ public class Launcher extends Activity
}
// returns true if the activity was started
- boolean startApplicationUninstallActivity(ComponentName componentName, int flags) {
+ boolean startApplicationUninstallActivity(ComponentName componentName, int flags,
+ UserHandleCompat user) {
if ((flags & AppInfo.DOWNLOADED_FLAG) == 0) {
// System applications cannot be installed. For now, show a toast explaining that.
// We may give them the option of disabling apps this way.
@@ -2732,6 +2736,9 @@ public class Launcher extends Activity
Intent.ACTION_DELETE, Uri.fromParts("package", packageName, className));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ if (user != null) {
+ user.addToIntent(intent, Intent.EXTRA_USER);
+ }
startActivity(intent);
return true;
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 29cfbb285..b01db7194 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -19,12 +19,19 @@ package com.android.launcher3;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
-import android.content.*;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentProviderClient;
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
@@ -45,11 +52,11 @@ import android.text.TextUtils;
import android.util.Log;
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.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
import java.lang.ref.WeakReference;
import java.net.URISyntaxException;
@@ -63,6 +70,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -157,6 +165,9 @@ public class LauncherModel extends BroadcastReceiver
// sBgWorkspaceScreens is the ordered set of workspace screens.
static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();
+ // sPendingPackages is a set of packages which could be on sdcard and are not available yet
+ static final HashMap<UserHandleCompat, HashSet<String>> sPendingPackages = new HashMap<>();
+
// </ only access in worker thread >
private IconCache mIconCache;
@@ -1826,6 +1837,9 @@ public class LauncherModel extends BroadcastReceiver
final PackageManager manager = context.getPackageManager();
final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
final boolean isSafeMode = manager.isSafeMode();
+ final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+ final boolean isSdCardReady = context.registerReceiver(null,
+ new IntentFilter(StartupReceiver.SYESTEM_READY)) != null;
LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
@@ -1919,6 +1933,7 @@ public class LauncherModel extends BroadcastReceiver
try {
int itemType = c.getInt(itemTypeIndex);
boolean restored = 0 != c.getInt(restoredIndex);
+ boolean allowMissingTarget = false;
switch (itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
@@ -1935,30 +1950,51 @@ public class LauncherModel extends BroadcastReceiver
try {
intent = Intent.parseUri(intentDescription, 0);
ComponentName cn = intent.getComponent();
- if (cn != null && !isValidPackageActivity(context, cn, user)) {
- if (restored) {
- // might be installed later
+ if (cn != null && cn.getPackageName() != null) {
+ boolean validPkg = launcherApps.isPackageEnabledForProfile(
+ cn.getPackageName(), user);
+ boolean validComponent = validPkg &&
+ launcherApps.isActivityEnabledForProfile(cn, user);
+
+ if (validComponent) {
+ if (restored) {
+ // no special handling necessary for this item
+ restoredRows.add(id);
+ restored = false;
+ }
+ } else if (validPkg) {
+ // The app is installed but the component is no
+ // longer available.
+ Launcher.addDumpLog(TAG,
+ "Invalid component removed: " + cn, true);
+ itemsToRemove.add(id);
+ continue;
+ } else if (restored) {
+ // Package is not yet available but might be
+ // installed later.
Launcher.addDumpLog(TAG,
"package not yet restored: " + cn, true);
+ } else if (isSdCardReady) {
+ // Do not wait for external media load anymore.
+ // Log the invalid package, and remove it
+ Launcher.addDumpLog(TAG,
+ "Invalid package removed: " + cn, true);
+ itemsToRemove.add(id);
+ continue;
} else {
- if (!mAppsCanBeOnRemoveableStorage) {
- // Log the invalid package, and remove it
- Launcher.addDumpLog(TAG,
- "Invalid package removed: " + cn, true);
- itemsToRemove.add(id);
- } else {
- // If apps can be on external storage, then we just
- // leave them for the user to remove (maybe add
- // visual treatment to it)
- Launcher.addDumpLog(TAG,
- "Invalid package found: " + cn, true);
+ // SdCard is not ready yet. Package might get available,
+ // once it is ready.
+ Launcher.addDumpLog(TAG, "Invalid package: " + cn
+ + " (check again later)", true);
+ HashSet<String> pkgs = sPendingPackages.get(user);
+ if (pkgs == null) {
+ pkgs = new HashSet<>();
+ sPendingPackages.put(user, pkgs);
}
- continue;
+ pkgs.add(cn.getPackageName());
+ allowMissingTarget = true;
+ // Add the icon on the workspace anyway.
}
- } else if (restored) {
- // no special handling necessary for this restored item
- restoredRows.add(id);
- restored = false;
}
} catch (URISyntaxException e) {
Launcher.addDumpLog(TAG,
@@ -1980,8 +2016,8 @@ public class LauncherModel extends BroadcastReceiver
}
} else if (itemType ==
LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- info = getShortcutInfo(manager, intent, user, context, c, iconIndex,
- titleIndex, mLabelCache);
+ info = getShortcutInfo(manager, intent, user, context, c,
+ iconIndex, titleIndex, mLabelCache, allowMissingTarget);
} else {
info = getShortcutInfo(c, context, iconTypeIndex,
iconPackageIndex, iconResourceIndex, iconIndex,
@@ -2198,6 +2234,12 @@ public class LauncherModel extends BroadcastReceiver
}
}
+ if (!isSdCardReady && !sPendingPackages.isEmpty()) {
+ context.registerReceiver(new AppsAvailabilityCheck(),
+ new IntentFilter(StartupReceiver.SYESTEM_READY),
+ null, sWorker);
+ }
+
if (loadedOldDb) {
long maxScreenId = 0;
// If we're importing we use the old screen order.
@@ -2743,6 +2785,33 @@ public class LauncherModel extends BroadcastReceiver
sWorker.post(task);
}
+ private class AppsAvailabilityCheck extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (sBgLock) {
+ final LauncherAppsCompat launcherApps = LauncherAppsCompat
+ .getInstance(mApp.getContext());
+ ArrayList<String> packagesRemoved;
+ for (Entry<UserHandleCompat, HashSet<String>> entry : sPendingPackages.entrySet()) {
+ UserHandleCompat user = entry.getKey();
+ packagesRemoved = new ArrayList<>();
+ for (String pkg : entry.getValue()) {
+ if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {
+ Launcher.addDumpLog(TAG, "Package not found: " + pkg, true);
+ packagesRemoved.add(pkg);
+ }
+ }
+ if (!packagesRemoved.isEmpty()) {
+ enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_REMOVE,
+ packagesRemoved.toArray(new String[packagesRemoved.size()]), user));
+ }
+ }
+ sPendingPackages.clear();
+ }
+ }
+ }
+
private class PackageUpdatedTask implements Runnable {
int mOp;
String[] mPackages;
@@ -2978,6 +3047,7 @@ public class LauncherModel extends BroadcastReceiver
info.setIcon(mIconCache.getIcon(intent, info.title.toString(), info.user));
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
info.restoredIntent = intent;
+ info.wasPromise = true;
info.setState(ShortcutInfo.PACKAGE_STATE_UNKNOWN);
return info;
}
@@ -3006,7 +3076,7 @@ public class LauncherModel extends BroadcastReceiver
*/
public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
UserHandleCompat user, Context context) {
- return getShortcutInfo(manager, intent, user, context, null, -1, -1, null);
+ return getShortcutInfo(manager, intent, user, context, null, -1, -1, null, false);
}
/**
@@ -3016,7 +3086,7 @@ public class LauncherModel extends BroadcastReceiver
*/
public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
UserHandleCompat user, Context context, Cursor c, int iconIndex, int titleIndex,
- HashMap<Object, CharSequence> labelCache) {
+ HashMap<Object, CharSequence> labelCache, boolean allowMissingTarget) {
if (user == null) {
Log.d(TAG, "Null user found in getShortcutInfo");
return null;
@@ -3032,7 +3102,7 @@ public class LauncherModel extends BroadcastReceiver
newIntent.addCategory(Intent.CATEGORY_LAUNCHER);
newIntent.setComponent(componentName);
LauncherActivityInfoCompat lai = mLauncherApps.resolveActivity(newIntent, user);
- if (lai == null) {
+ if ((lai == null) && !allowMissingTarget) {
Log.d(TAG, "Missing activity found in getShortcutInfo: " + componentName);
return null;
}
diff --git a/src/com/android/launcher3/PreloadIconDrawable.java b/src/com/android/launcher3/PreloadIconDrawable.java
new file mode 100644
index 000000000..d9365cc1f
--- /dev/null
+++ b/src/com/android/launcher3/PreloadIconDrawable.java
@@ -0,0 +1,168 @@
+package com.android.launcher3;
+
+import android.animation.ObjectAnimator;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+
+class PreloadIconDrawable extends Drawable {
+ private static final float ANIMATION_PROGRESS_STOPPED = -1.0f;
+ private static final float ANIMATION_PROGRESS_STARTED = 0f;
+ private static final float ANIMATION_PROGRESS_COMPLETED = 1.0f;
+
+ private static final float ICON_SCALE_FACTOR = 0.6f;
+
+ private static Bitmap sProgressBg, sProgressFill;
+
+ private final Rect mCanvasClipRect = new Rect();
+ private final RectF mRect = new RectF();
+ private final Path mProgressPath = new Path();
+ private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+
+ final Drawable mIcon;
+
+ /**
+ * Indicates the progress of the preloader [0-100]. If it goes above 100, only the icon
+ * is shown with no progress bar.
+ */
+ private int mProgress = 0;
+ private boolean mPathChanged;
+
+ private float mAnimationProgress = ANIMATION_PROGRESS_STOPPED;
+ private ObjectAnimator mAnimator;
+
+ public PreloadIconDrawable(Drawable icon, Resources res) {
+ mIcon = icon;
+
+ setBounds(icon.getBounds());
+ mPathChanged = false;
+
+ if (sProgressBg == null) {
+ sProgressBg = BitmapFactory.decodeResource(res, R.drawable.bg_preloader);
+ }
+ if (sProgressFill == null) {
+ sProgressFill = BitmapFactory.decodeResource(res, R.drawable.bg_preloader_progress);
+ }
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ final Rect r = getBounds();
+ if (canvas.getClipBounds(mCanvasClipRect) && !Rect.intersects(mCanvasClipRect, r)) {
+ // The draw region has been clipped.
+ return;
+ }
+ final float iconScale;
+
+ if ((mAnimationProgress >= ANIMATION_PROGRESS_STARTED)
+ && (mAnimationProgress < ANIMATION_PROGRESS_COMPLETED)) {
+ mPaint.setAlpha((int) ((1 - mAnimationProgress) * 255));
+ canvas.drawBitmap(sProgressBg, null, r, mPaint);
+ canvas.drawBitmap(sProgressFill, null, r, mPaint);
+ iconScale = ICON_SCALE_FACTOR + (1 - ICON_SCALE_FACTOR) * mAnimationProgress;
+
+ } else if (mAnimationProgress == ANIMATION_PROGRESS_STOPPED) {
+ mPaint.setAlpha(255);
+ iconScale = ICON_SCALE_FACTOR;
+ canvas.drawBitmap(sProgressBg, null, r, mPaint);
+
+ if (mProgress >= 100) {
+ canvas.drawBitmap(sProgressFill, null, r, mPaint);
+ } else if (mProgress > 0) {
+ if (mPathChanged) {
+ mProgressPath.reset();
+ mProgressPath.moveTo(r.exactCenterX(), r.centerY());
+
+ mRect.set(r);
+ mProgressPath.arcTo(mRect, -90, mProgress * 3.6f);
+ mProgressPath.close();
+ mPathChanged = false;
+ }
+
+ canvas.save();
+ canvas.clipPath(mProgressPath);
+ canvas.drawBitmap(sProgressFill, null, r, mPaint);
+ canvas.restore();
+ }
+ } else {
+ iconScale = 1;
+ }
+
+ canvas.save();
+ canvas.scale(iconScale, iconScale, r.exactCenterX(), r.exactCenterY());
+ mIcon.draw(canvas);
+ canvas.restore();
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ mIcon.setBounds(bounds);
+ mPathChanged = true;
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mIcon.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ mIcon.setColorFilter(cf);
+ }
+
+ @Override
+ protected boolean onLevelChange(int level) {
+ mProgress = level;
+ mPathChanged = true;
+
+ // Stop Animation
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ mAnimator = null;
+ }
+ mAnimationProgress = ANIMATION_PROGRESS_STOPPED;
+
+ invalidateSelf();
+ return true;
+ }
+
+ /**
+ * Runs the finish animation if it is has not been run after last level change.
+ */
+ public void maybePerformFinishedAnimation() {
+ if (mAnimationProgress > ANIMATION_PROGRESS_STOPPED) {
+ return;
+ }
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+ setAnimationProgress(ANIMATION_PROGRESS_STARTED);
+ mAnimator = ObjectAnimator.ofFloat(this, "animationProgress",
+ ANIMATION_PROGRESS_STARTED, ANIMATION_PROGRESS_COMPLETED);
+ mAnimator.start();
+ }
+
+ public void setAnimationProgress(float progress) {
+ if (progress != mAnimationProgress) {
+ mAnimationProgress = progress;
+ invalidateSelf();
+ }
+ }
+
+ public float getAnimationProgress() {
+ return mAnimationProgress;
+ }
+}
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index d2573a4a1..7e1f0d649 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -16,13 +16,9 @@
package com.android.launcher3;
-import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.util.Log;
@@ -96,6 +92,11 @@ public class ShortcutInfo extends ItemInfo {
*/
Intent restoredIntent;
+ /**
+ * This is set once to indicate that it was a promise info at some point of its life.
+ */
+ boolean wasPromise = false;
+
ShortcutInfo() {
itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
}
@@ -119,7 +120,7 @@ public class ShortcutInfo extends ItemInfo {
}
}
- ShortcutInfo(Intent intent, CharSequence title, String contentDescrition,
+ ShortcutInfo(Intent intent, CharSequence title, String contentDescription,
Bitmap icon, UserHandleCompat user) {
this();
this.intent = intent;
diff --git a/src/com/android/launcher3/StartupReceiver.java b/src/com/android/launcher3/StartupReceiver.java
new file mode 100644
index 000000000..4499917f0
--- /dev/null
+++ b/src/com/android/launcher3/StartupReceiver.java
@@ -0,0 +1,15 @@
+package com.android.launcher3;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class StartupReceiver extends BroadcastReceiver {
+
+ static final String SYESTEM_READY = "com.android.launcher3.SYESTEM_READY";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ context.sendStickyBroadcast(new Intent(SYESTEM_READY));
+ }
+}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 48795af13..a8e7580c3 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1159,12 +1159,20 @@ public class Workspace extends SmoothPagedView
(mTouchDownTime - mCustomContentShowTime) > CUSTOM_CONTENT_GESTURE_DELAY;
boolean swipeInIgnoreDirection = isLayoutRtl() ? deltaX < 0 : deltaX > 0;
- if (swipeInIgnoreDirection && getScreenIdForPageIndex(getCurrentPage()) ==
- CUSTOM_CONTENT_SCREEN_ID && passRightSwipesToCustomContent) {
+ boolean onCustomContentScreen =
+ getScreenIdForPageIndex(getCurrentPage()) == CUSTOM_CONTENT_SCREEN_ID;
+ if (swipeInIgnoreDirection && onCustomContentScreen && passRightSwipesToCustomContent) {
// Pass swipes to the right to the custom content page.
return;
}
+ if (onCustomContentScreen && (mCustomContentCallbacks != null)
+ && !mCustomContentCallbacks.isScrollingAllowed()) {
+ // Don't allow workspace scrolling if the current custom content screen doesn't allow
+ // scrolling.
+ return;
+ }
+
if (theta > MAX_SWIPE_ANGLE) {
// Above MAX_SWIPE_ANGLE, we don't want to ever start scrolling the workspace
return;
diff --git a/src/com/android/launcher3/compat/UserHandleCompat.java b/src/com/android/launcher3/compat/UserHandleCompat.java
index 8f5dda238..4baf05247 100644
--- a/src/com/android/launcher3/compat/UserHandleCompat.java
+++ b/src/com/android/launcher3/compat/UserHandleCompat.java
@@ -16,6 +16,7 @@
package com.android.launcher3.compat;
+import android.content.Intent;
import android.os.Build;
import android.os.UserHandle;
@@ -78,4 +79,16 @@ public class UserHandleCompat {
return 0;
}
}
+
+ /**
+ * Adds {@link UserHandle} to the intent in for L or above.
+ * Pre-L the launcher doesn't support showing apps for multiple
+ * profiles so this is a no-op.
+ */
+ public void addToIntent(Intent intent, String name) {
+ // TODO change this to use api version once L gets an API number.
+ if ("L".equals(Build.VERSION.CODENAME) && mUser != null) {
+ intent.putExtra(name, mUser);
+ }
+ }
} \ No newline at end of file