summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWinson Chung <winsonc@google.com>2012-04-03 14:22:34 -0700
committerWinson Chung <winsonc@google.com>2012-04-09 17:04:00 -0700
commita2413751e3a698aef9c87411a639637883856939 (patch)
treee71fc7aa7fef5408ca7956c5ad373504d763337c
parente9bafe991b5bbcd033e1f27c66ba254d55117b20 (diff)
downloadandroid_packages_apps_Trebuchet-a2413751e3a698aef9c87411a639637883856939.tar.gz
android_packages_apps_Trebuchet-a2413751e3a698aef9c87411a639637883856939.tar.bz2
android_packages_apps_Trebuchet-a2413751e3a698aef9c87411a639637883856939.zip
Adding delay upon user interaction to prevent the new-app animation from taking over your phone. (Bug 6248609)
- Fixing issue where we might have been reading the db items while handling previous broadcast and adding db items to invalid positions - Making items add alternating from the center page (as opposed to the current page) - Re-adding the strict-mode fix (really requires 1. to be true) - Adding flag for enabling strict mode exceptions - Removing items from the new apps add list on uninstall-shortcut broadcast Change-Id: I495e80bf5f8dbb4b87dd709460937d6f2a1e05e7
-rw-r--r--src/com/android/launcher2/DragController.java14
-rw-r--r--src/com/android/launcher2/InstallShortcutReceiver.java42
-rw-r--r--src/com/android/launcher2/Launcher.java100
-rw-r--r--src/com/android/launcher2/UninstallShortcutReceiver.java35
4 files changed, 149 insertions, 42 deletions
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 2a1d65adc..9a61db666 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -440,6 +440,19 @@ public class DragController {
return mTmpPoint;
}
+ private long mLastTouchUpTime = -1;
+ long getLastGestureUpTime() {
+ if (mDragging) {
+ return System.currentTimeMillis();
+ } else {
+ return mLastTouchUpTime;
+ }
+ }
+
+ void resetLastGestureUpTime() {
+ mLastTouchUpTime = -1;
+ }
+
/**
* Call this from a drag source view.
*/
@@ -467,6 +480,7 @@ public class DragController {
mLastDropTarget = null;
break;
case MotionEvent.ACTION_UP:
+ mLastTouchUpTime = System.currentTimeMillis();
if (mDragging) {
PointF vec = isFlingingToDelete(mDragObject.dragSource);
if (vec != null) {
diff --git a/src/com/android/launcher2/InstallShortcutReceiver.java b/src/com/android/launcher2/InstallShortcutReceiver.java
index 4c0974fd3..19b1c69d2 100644
--- a/src/com/android/launcher2/InstallShortcutReceiver.java
+++ b/src/com/android/launcher2/InstallShortcutReceiver.java
@@ -56,7 +56,6 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
String spKey = LauncherApplication.getSharedPreferencesKey();
SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
- final int screen = Launcher.getScreen();
final Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
if (intent == null) {
return;
@@ -74,17 +73,23 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
}
}
- final ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);
- final boolean exists = LauncherModel.shortcutExists(context, name, intent);
+ // Lock on the app so that we don't try and get the items while apps are being added
+ LauncherApplication app = (LauncherApplication) context.getApplicationContext();
final int[] result = {INSTALL_SHORTCUT_SUCCESSFUL};
-
- // Try adding the target to the workspace screens incrementally, starting at the current
- // screen and alternating between +1, -1, +2, -2, etc. (using ~ ceil(i/2f)*(-1)^(i-1))
boolean found = false;
- for (int i = 0; i < (2 * Launcher.SCREEN_COUNT) + 1 && !found; ++i) {
- int si = screen + (int) ((i / 2f) + 0.5f) * ((i % 2 == 1) ? 1 : -1);
- if (0 <= si && si < Launcher.SCREEN_COUNT) {
- found = installShortcut(context, data, items, name, intent, si, exists, sp, result);
+ synchronized (app) {
+ final ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);
+ final boolean exists = LauncherModel.shortcutExists(context, name, intent);
+
+ // Try adding to the workspace screens incrementally, starting at the default or center
+ // screen and alternating between +1, -1, +2, -2, etc. (using ~ ceil(i/2f)*(-1)^(i-1))
+ final int screen = Launcher.DEFAULT_SCREEN;
+ for (int i = 0; i < (2 * Launcher.SCREEN_COUNT) + 1 && !found; ++i) {
+ int si = screen + (int) ((i / 2f) + 0.5f) * ((i % 2 == 1) ? 1 : -1);
+ if (0 <= si && si < Launcher.SCREEN_COUNT) {
+ found = installShortcut(context, data, items, name, intent, si, exists, sp,
+ result);
+ }
}
}
@@ -102,8 +107,8 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
}
private boolean installShortcut(Context context, Intent data, ArrayList<ItemInfo> items,
- String name, Intent intent, int screen, boolean shortcutExists,
- SharedPreferences sharedPrefs, int[] result) {
+ String name, Intent intent, final int screen, boolean shortcutExists,
+ final SharedPreferences sharedPrefs, int[] result) {
if (findEmptyCell(context, items, mCoordinates, screen)) {
if (intent != null) {
if (intent.getAction() == null) {
@@ -122,10 +127,15 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
newApps = sharedPrefs.getStringSet(NEW_APPS_LIST_KEY, newApps);
}
newApps.add(intent.toUri(0).toString());
- sharedPrefs.edit()
- .putInt(NEW_APPS_PAGE_KEY, screen)
- .putStringSet(NEW_APPS_LIST_KEY, newApps)
- .commit();
+ final Set<String> savedNewApps = newApps;
+ new Thread("setNewAppsThread") {
+ public void run() {
+ sharedPrefs.edit()
+ .putInt(NEW_APPS_PAGE_KEY, screen)
+ .putStringSet(NEW_APPS_LIST_KEY, savedNewApps)
+ .commit();
+ }
+ }.start();
// Update the Launcher db
LauncherApplication app = (LauncherApplication) context.getApplicationContext();
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index b3ce96884..cef713763 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -55,10 +55,10 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.Debug;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
+import android.os.StrictMode;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
@@ -85,7 +85,6 @@ import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
-import android.view.animation.BounceInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.InputMethodManager;
import android.widget.Advanceable;
@@ -123,6 +122,7 @@ public final class Launcher extends Activity
static final boolean PROFILE_STARTUP = false;
static final boolean DEBUG_WIDGETS = false;
+ static final boolean DEBUG_STRICT_MODE = false;
private static final int MENU_GROUP_WALLPAPER = 1;
private static final int MENU_WALLPAPER_SETTINGS = Menu.FIRST + 1;
@@ -182,6 +182,9 @@ public final class Launcher extends Activity
private static final Object sLock = new Object();
private static int sScreen = DEFAULT_SCREEN;
+ // How long to wait before the new-shortcut animation automatically pans the workspace
+ private static int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 10;
+
private final BroadcastReceiver mCloseSystemDialogsReceiver
= new CloseSystemDialogsIntentReceiver();
private final ContentObserver mWidgetObserver = new AppWidgetResetObserver();
@@ -289,6 +292,21 @@ public final class Launcher extends Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
+ if (DEBUG_STRICT_MODE) {
+ StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+ .detectDiskReads()
+ .detectDiskWrites()
+ .detectNetwork() // or .detectAll() for all detectable problems
+ .penaltyLog()
+ .build());
+ StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
+ .detectLeakedSqlLiteObjects()
+ .detectLeakedClosableObjects()
+ .penaltyLog()
+ .penaltyDeath()
+ .build());
+ }
+
super.onCreate(savedInstanceState);
LauncherApplication app = ((LauncherApplication)getApplication());
mSharedPrefs = getSharedPreferences(LauncherApplication.getSharedPreferencesKey(),
@@ -635,6 +653,7 @@ public final class Launcher extends Activity
super.onPause();
mPaused = true;
mDragController.cancelDrag();
+ mDragController.resetLastGestureUpTime();
}
@Override
@@ -3258,27 +3277,46 @@ public final class Launcher extends Activity
Runnable newAppsRunnable = new Runnable() {
@Override
public void run() {
- runNewAppsAnimation();
+ runNewAppsAnimation(false);
}
};
- if (mNewShortcutAnimatePage > -1 &&
- mNewShortcutAnimatePage != mWorkspace.getCurrentPage()) {
- mWorkspace.snapToPage(mNewShortcutAnimatePage, newAppsRunnable);
+
+ boolean willSnapPage = mNewShortcutAnimatePage > -1 &&
+ mNewShortcutAnimatePage != mWorkspace.getCurrentPage();
+ if (canRunNewAppsAnimation()) {
+ // If the user has not interacted recently, then either snap to the new page to show
+ // the new-apps animation or just run them if they are to appear on the current page
+ if (willSnapPage) {
+ mWorkspace.snapToPage(mNewShortcutAnimatePage, newAppsRunnable);
+ } else {
+ runNewAppsAnimation(false);
+ }
} else {
- newAppsRunnable.run();
+ // If the user has interacted recently, then run the animations immediately if they
+ // are on another page (or just normally if they are added to the current page)
+ runNewAppsAnimation(willSnapPage);
}
}
mWorkspaceLoading = false;
}
+ private boolean canRunNewAppsAnimation() {
+ long diff = System.currentTimeMillis() - mDragController.getLastGestureUpTime();
+ return diff > (NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS * 1000);
+ }
+
/**
* Runs a new animation that scales up icons that were added while Launcher was in the
* background.
+ *
+ * @param immediate whether to run the animation or show the results immediately
*/
- private void runNewAppsAnimation() {
+ private void runNewAppsAnimation(boolean immediate) {
AnimatorSet anim = new AnimatorSet();
Collection<Animator> bounceAnims = new ArrayList<Animator>();
+
+ // Order these new views spatially so that they animate in order
Collections.sort(mNewShortcutAnimateViews, new Comparator<View>() {
@Override
public int compare(View a, View b) {
@@ -3288,25 +3326,35 @@ public final class Launcher extends Activity
return (alp.cellY * cellCountX + alp.cellX) - (blp.cellY * cellCountX + blp.cellX);
}
});
- for (int i = 0; i < mNewShortcutAnimateViews.size(); ++i) {
- View v = mNewShortcutAnimateViews.get(i);
- ValueAnimator bounceAnim = ObjectAnimator.ofPropertyValuesHolder(v,
- PropertyValuesHolder.ofFloat("alpha", 1f),
- PropertyValuesHolder.ofFloat("scaleX", 1f),
- PropertyValuesHolder.ofFloat("scaleY", 1f));
- bounceAnim.setDuration(InstallShortcutReceiver.NEW_SHORTCUT_BOUNCE_DURATION);
- bounceAnim.setStartDelay(i * InstallShortcutReceiver.NEW_SHORTCUT_STAGGER_DELAY);
- bounceAnim.setInterpolator(new SmoothPagedView.OvershootInterpolator());
- bounceAnims.add(bounceAnim);
- }
- anim.playTogether(bounceAnims);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mWorkspace.postDelayed(mBuildLayersRunnable, 500);
+
+ // Animate each of the views in place (or show them immediately if requested)
+ if (immediate) {
+ for (View v : mNewShortcutAnimateViews) {
+ v.setAlpha(1f);
+ v.setScaleX(1f);
+ v.setScaleY(1f);
}
- });
- anim.start();
+ } else {
+ for (int i = 0; i < mNewShortcutAnimateViews.size(); ++i) {
+ View v = mNewShortcutAnimateViews.get(i);
+ ValueAnimator bounceAnim = ObjectAnimator.ofPropertyValuesHolder(v,
+ PropertyValuesHolder.ofFloat("alpha", 1f),
+ PropertyValuesHolder.ofFloat("scaleX", 1f),
+ PropertyValuesHolder.ofFloat("scaleY", 1f));
+ bounceAnim.setDuration(InstallShortcutReceiver.NEW_SHORTCUT_BOUNCE_DURATION);
+ bounceAnim.setStartDelay(i * InstallShortcutReceiver.NEW_SHORTCUT_STAGGER_DELAY);
+ bounceAnim.setInterpolator(new SmoothPagedView.OvershootInterpolator());
+ bounceAnims.add(bounceAnim);
+ }
+ anim.playTogether(bounceAnims);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mWorkspace.postDelayed(mBuildLayersRunnable, 500);
+ }
+ });
+ anim.start();
+ }
// Clean up
mNewShortcutAnimatePage = -1;
diff --git a/src/com/android/launcher2/UninstallShortcutReceiver.java b/src/com/android/launcher2/UninstallShortcutReceiver.java
index eb4ee4cf3..3f6de7c5a 100644
--- a/src/com/android/launcher2/UninstallShortcutReceiver.java
+++ b/src/com/android/launcher2/UninstallShortcutReceiver.java
@@ -20,11 +20,14 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.ContentResolver;
+import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.widget.Toast;
import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.Set;
import com.android.launcher.R;
@@ -36,7 +39,16 @@ public class UninstallShortcutReceiver extends BroadcastReceiver {
if (!ACTION_UNINSTALL_SHORTCUT.equals(data.getAction())) {
return;
}
+ String spKey = LauncherApplication.getSharedPreferencesKey();
+ SharedPreferences sharedPrefs = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ LauncherApplication app = (LauncherApplication) context.getApplicationContext();
+ synchronized (app) {
+ removeShortcut(context, data, sharedPrefs);
+ }
+ }
+
+ private void removeShortcut(Context context, Intent data, final SharedPreferences sharedPrefs) {
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
@@ -77,6 +89,29 @@ public class UninstallShortcutReceiver extends BroadcastReceiver {
Toast.makeText(context, context.getString(R.string.shortcut_uninstalled, name),
Toast.LENGTH_SHORT).show();
}
+
+ // Remove any items due to be animated
+ boolean appRemoved;
+ Set<String> newApps = new HashSet<String>();
+ newApps = sharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps);
+ do {
+ appRemoved = newApps.remove(intent.toUri(0).toString());
+ } while (appRemoved);
+ if (appRemoved) {
+ final Set<String> savedNewApps = newApps;
+ new Thread("setNewAppsThread-remove") {
+ public void run() {
+ SharedPreferences.Editor editor = sharedPrefs.edit();
+ editor.putStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY,
+ savedNewApps);
+ if (savedNewApps.isEmpty()) {
+ // Reset the page index if there are no more items
+ editor.putInt(InstallShortcutReceiver.NEW_APPS_PAGE_KEY, -1);
+ }
+ editor.commit();
+ }
+ }.start();
+ }
}
}
}