summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2016-09-25 21:23:25 -0700
committerSunny Goyal <sunnygoyal@google.com>2016-09-30 11:18:38 -0700
commit1acc56a4eb9a74f28e32eadf62f389d3221b50ff (patch)
treecd4abe2d544e7b08b7c08bcaae0d6cda4e26d382 /src
parentde45283519570477b2c01feaa12e19e53cf0b57d (diff)
downloadandroid_packages_apps_Trebuchet-1acc56a4eb9a74f28e32eadf62f389d3221b50ff.tar.gz
android_packages_apps_Trebuchet-1acc56a4eb9a74f28e32eadf62f389d3221b50ff.tar.bz2
android_packages_apps_Trebuchet-1acc56a4eb9a74f28e32eadf62f389d3221b50ff.zip
Moving the widget auto-advance logic to AppWidgetHostView instead of
handling it in launcher This fixes the bug where launcher ignores auto-advance property changes during app update or widget remote views update as well as simplifies widget management On potential downside of this refactoring is that the auto advance will keep running even when all-apps or widgets tray is open. We could eventually use onVisibilityAggregated to handle visibility changes, but currenly the workspace visibility is not being updated properly in these cases Change-Id: Ie7331fec1877f43ad23e634d37571d8f3ef51e59
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/Launcher.java118
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetHostView.java110
2 files changed, 110 insertions, 118 deletions
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 0a14c421d..5428f3314 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -30,7 +30,6 @@ import android.app.AlertDialog;
import android.app.SearchManager;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
@@ -56,7 +55,6 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
-import android.os.Message;
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.Trace;
@@ -81,7 +79,6 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.OvershootInterpolator;
import android.view.inputmethod.InputMethodManager;
-import android.widget.Advanceable;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
@@ -274,27 +271,16 @@ public class Launcher extends Activity
private IconCache mIconCache;
private ExtractedColors mExtractedColors;
private LauncherAccessibilityDelegate mAccessibilityDelegate;
+ private Handler mHandler = new Handler();
private boolean mIsResumeFromActionScreenOff;
- @Thunk boolean mUserPresent = true;
- private boolean mVisible;
- private boolean mHasFocus;
- private boolean mAttached;
+ private boolean mHasFocus = false;
+ private boolean mAttached = false;
/** Maps launcher activity components to their list of shortcut ids. */
private MultiHashMap<ComponentKey, String> mDeepShortcutMap = new MultiHashMap<>();
private View.OnTouchListener mHapticFeedbackTouchListener;
- // Related to the auto-advancing of widgets
- private final int ADVANCE_MSG = 1;
- private static final int ADVANCE_INTERVAL = 20000;
- private static final int ADVANCE_STAGGER = 250;
-
- private boolean mAutoAdvanceRunning = false;
- private long mAutoAdvanceSentTime;
- private long mAutoAdvanceTimeLeft = -1;
- @Thunk HashMap<View, AppWidgetProviderInfo> mWidgetsToAdvance = new HashMap<>();
-
// Determines how long to wait after a rotation before restoring the screen orientation to
// match the sensor state.
private static final int RESTORE_SCREEN_ORIENTATION_DELAY = 500;
@@ -1568,10 +1554,6 @@ public class Launcher extends Activity
mWorkspace.addInScreen(hostView, item.container, item.screenId,
item.cellX, item.cellY, item.spanX, item.spanY, insert);
-
- if (!item.isCustomWidget()) {
- addWidgetToAutoAdvanceIfNeeded(hostView, appWidgetInfo);
- }
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -1579,9 +1561,7 @@ public class Launcher extends Activity
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
- mUserPresent = false;
mDragLayer.clearResizeFrame();
- updateAutoAdvanceState();
// Reset AllApps to its initial state only if we are not in the middle of
// processing a multi-step drop
@@ -1592,9 +1572,6 @@ public class Launcher extends Activity
}
}
mIsResumeFromActionScreenOff = true;
- } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
- mUserPresent = true;
- updateAutoAdvanceState();
}
}
};
@@ -1606,11 +1583,9 @@ public class Launcher extends Activity
// Listen for broadcasts related to user-presence
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(Intent.ACTION_USER_PRESENT);
registerReceiver(mReceiver, filter);
FirstFrameAnimatorHelper.initializeDrawListener(getWindow().getDecorView());
mAttached = true;
- mVisible = true;
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onAttachedToWindow();
@@ -1620,13 +1595,10 @@ public class Launcher extends Activity
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
- mVisible = false;
-
if (mAttached) {
unregisterReceiver(mReceiver);
mAttached = false;
}
- updateAutoAdvanceState();
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onDetachedFromWindow();
@@ -1634,12 +1606,10 @@ public class Launcher extends Activity
}
public void onWindowVisibilityChanged(int visibility) {
- mVisible = visibility == View.VISIBLE;
- updateAutoAdvanceState();
// The following code used to be in onResume, but it turns out onResume is called when
// you're in All Apps and click home to go to the workspace. onWindowVisibilityChanged
// is a more appropriate event to handle
- if (mVisible) {
+ if (visibility == View.VISIBLE) {
if (!mWorkspaceLoading) {
final ViewTreeObserver observer = mWorkspace.getViewTreeObserver();
// We want to let Launcher draw itself at least once before we force it to build
@@ -1674,72 +1644,6 @@ public class Launcher extends Activity
}
}
- @Thunk void sendAdvanceMessage(long delay) {
- mHandler.removeMessages(ADVANCE_MSG);
- Message msg = mHandler.obtainMessage(ADVANCE_MSG);
- mHandler.sendMessageDelayed(msg, delay);
- mAutoAdvanceSentTime = System.currentTimeMillis();
- }
-
- @Thunk void updateAutoAdvanceState() {
- boolean autoAdvanceRunning = mVisible && mUserPresent && !mWidgetsToAdvance.isEmpty();
- if (autoAdvanceRunning != mAutoAdvanceRunning) {
- mAutoAdvanceRunning = autoAdvanceRunning;
- if (autoAdvanceRunning) {
- long delay = mAutoAdvanceTimeLeft == -1 ? ADVANCE_INTERVAL : mAutoAdvanceTimeLeft;
- sendAdvanceMessage(delay);
- } else {
- if (!mWidgetsToAdvance.isEmpty()) {
- mAutoAdvanceTimeLeft = Math.max(0, ADVANCE_INTERVAL -
- (System.currentTimeMillis() - mAutoAdvanceSentTime));
- }
- mHandler.removeMessages(ADVANCE_MSG);
- mHandler.removeMessages(0); // Remove messages sent using postDelayed()
- }
- }
- }
-
- @Thunk final Handler mHandler = new Handler(new Handler.Callback() {
-
- @Override
- public boolean handleMessage(Message msg) {
- if (msg.what == ADVANCE_MSG) {
- int i = 0;
- for (View key: mWidgetsToAdvance.keySet()) {
- final View v = key.findViewById(mWidgetsToAdvance.get(key).autoAdvanceViewId);
- final int delay = ADVANCE_STAGGER * i;
- if (v instanceof Advanceable) {
- mHandler.postDelayed(new Runnable() {
- public void run() {
- ((Advanceable) v).advance();
- }
- }, delay);
- }
- i++;
- }
- sendAdvanceMessage(ADVANCE_INTERVAL);
- }
- return true;
- }
- });
-
- private void addWidgetToAutoAdvanceIfNeeded(View hostView, AppWidgetProviderInfo appWidgetInfo) {
- if (appWidgetInfo == null || appWidgetInfo.autoAdvanceViewId == -1) return;
- View v = hostView.findViewById(appWidgetInfo.autoAdvanceViewId);
- if (v instanceof Advanceable) {
- mWidgetsToAdvance.put(hostView, appWidgetInfo);
- ((Advanceable) v).fyiWillBeAdvancedByHostKThx();
- updateAutoAdvanceState();
- }
- }
-
- private void removeWidgetToAutoAdvance(View hostView) {
- if (mWidgetsToAdvance.containsKey(hostView)) {
- mWidgetsToAdvance.remove(hostView);
- updateAutoAdvanceState();
- }
- }
-
public void showOutOfSpaceMessage(boolean isHotseatLayout) {
int strId = (isHotseatLayout ? R.string.hotseat_out_of_space : R.string.out_of_space);
Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT).show();
@@ -1934,9 +1838,6 @@ public class Launcher extends Activity
public void onDestroy() {
super.onDestroy();
- // Remove all pending runnables
- mHandler.removeMessages(ADVANCE_MSG);
- mHandler.removeMessages(0);
mWorkspace.removeCallbacks(mBuildLayersRunnable);
mWorkspace.removeFolderListeners();
@@ -1959,8 +1860,6 @@ public class Launcher extends Activity
}
mAppWidgetHost = null;
- mWidgetsToAdvance.clear();
-
TextKeyListener.getInstance().release();
((AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE))
@@ -2280,7 +2179,6 @@ public class Launcher extends Activity
} else if (itemInfo instanceof LauncherAppWidgetInfo) {
final LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) itemInfo;
mWorkspace.removeWorkspaceItem(v);
- removeWidgetToAutoAdvance(v);
if (deleteFromDb) {
deleteWidgetInfo(widgetInfo);
}
@@ -3229,10 +3127,6 @@ public class Launcher extends Activity
// Change the state *after* we've called all the transition code
mState = State.WORKSPACE;
- // Resume the auto-advance of widgets
- mUserPresent = true;
- updateAutoAdvanceState();
-
if (changed) {
// Send an accessibility event to announce the context change
getWindow().getDecorView()
@@ -3338,9 +3232,6 @@ public class Launcher extends Activity
// Change the state *after* we've called all the transition code
mState = toState;
- // Pause the auto-advance of widgets until we are out of AllApps
- mUserPresent = false;
- updateAutoAdvanceState();
closeFolder();
closeShortcutsContainer();
@@ -3566,7 +3457,6 @@ public class Launcher extends Activity
mWorkspace.clearDropTargets();
mWorkspace.removeAllWorkspaceScreens();
- mWidgetsToAdvance.clear();
if (mHotseat != null) {
mHotseat.resetLayout();
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index ed1079ff3..fa5e519b1 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -20,6 +20,9 @@ import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.graphics.Rect;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.util.SparseBooleanArray;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -28,6 +31,7 @@ import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.Advanceable;
import android.widget.RemoteViews;
import com.android.launcher3.dragndrop.DragLayer.TouchCompleteListener;
@@ -39,6 +43,13 @@ import java.util.ArrayList;
*/
public class LauncherAppWidgetHostView extends AppWidgetHostView implements TouchCompleteListener {
+ // Related to the auto-advancing of widgets
+ private static final long ADVANCE_INTERVAL = 20000;
+ private static final long ADVANCE_STAGGER = 250;
+
+ // Maintains a list of widget ids which are supposed to be auto advanced.
+ private static final SparseBooleanArray sAutoAdvanceWidgetIds = new SparseBooleanArray();
+
LayoutInflater mInflater;
private CheckLongPressHelper mLongPressHelper;
@@ -54,6 +65,10 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
protected int mErrorViewId = R.layout.appwidget_error;
+ private boolean mIsAttachedToWindow;
+ private boolean mIsAutoAdvanceRegistered;
+ private Runnable mAutoAdvanceRunnable;
+
public LauncherAppWidgetHostView(Context context) {
super(context);
mContext = context;
@@ -78,6 +93,9 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
// Store the orientation in which the widget was inflated
updateLastInflationOrientation();
super.updateAppWidget(remoteViews);
+
+ // The provider info or the views might have changed.
+ checkIfAutoAdvance();
}
public boolean isReinflateRequired() {
@@ -153,6 +171,19 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
+
+ mIsAttachedToWindow = true;
+ checkIfAutoAdvance();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ // We can't directly use isAttachedToWindow() here, as this is called before the internal
+ // state is updated. So isAttachedToWindow() will return true until next frame.
+ mIsAttachedToWindow = false;
+ checkIfAutoAdvance();
}
@Override
@@ -171,10 +202,6 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
return info;
}
- public LauncherAppWidgetProviderInfo getLauncherAppWidgetProviderInfo() {
- return (LauncherAppWidgetProviderInfo) getAppWidgetInfo();
- }
-
@Override
public void onTouchComplete() {
if (!mLongPressHelper.hasPerformedLongPress()) {
@@ -296,4 +323,79 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(getClass().getName());
}
+
+ @Override
+ protected void onWindowVisibilityChanged(int visibility) {
+ super.onWindowVisibilityChanged(visibility);
+ maybeRegisterAutoAdvance();
+ }
+
+ private void checkIfAutoAdvance() {
+ boolean isAutoAdvance = false;
+ Advanceable target = getAdvanceable();
+ if (target != null) {
+ isAutoAdvance = true;
+ target.fyiWillBeAdvancedByHostKThx();
+ }
+
+ boolean wasAutoAdvance = sAutoAdvanceWidgetIds.indexOfKey(getAppWidgetId()) >= 0;
+ if (isAutoAdvance != wasAutoAdvance) {
+ if (isAutoAdvance) {
+ sAutoAdvanceWidgetIds.put(getAppWidgetId(), true);
+ } else {
+ sAutoAdvanceWidgetIds.delete(getAppWidgetId());
+ }
+ maybeRegisterAutoAdvance();
+ }
+ }
+
+ private Advanceable getAdvanceable() {
+ AppWidgetProviderInfo info = getAppWidgetInfo();
+ if (info == null || info.autoAdvanceViewId == NO_ID || !mIsAttachedToWindow) {
+ return null;
+ }
+ View v = findViewById(info.autoAdvanceViewId);
+ return (v instanceof Advanceable) ? (Advanceable) v : null;
+ }
+
+ private void maybeRegisterAutoAdvance() {
+ Handler handler = getHandler();
+ boolean shouldRegisterAutoAdvance = getWindowVisibility() == VISIBLE && handler != null
+ && (sAutoAdvanceWidgetIds.indexOfKey(getAppWidgetId()) >= 0);
+ if (shouldRegisterAutoAdvance != mIsAutoAdvanceRegistered) {
+ mIsAutoAdvanceRegistered = shouldRegisterAutoAdvance;
+ if (mAutoAdvanceRunnable == null) {
+ mAutoAdvanceRunnable = new Runnable() {
+ @Override
+ public void run() {
+ runAutoAdvance();
+ }
+ };
+ }
+
+ handler.removeCallbacks(mAutoAdvanceRunnable);
+ scheduleNextAdvance();
+ }
+ }
+
+ private void scheduleNextAdvance() {
+ if (!mIsAutoAdvanceRegistered) {
+ return;
+ }
+ long now = SystemClock.uptimeMillis();
+ long advanceTime = now + (ADVANCE_INTERVAL - (now % ADVANCE_INTERVAL)) +
+ ADVANCE_STAGGER * sAutoAdvanceWidgetIds.indexOfKey(getAppWidgetId());
+ Handler handler = getHandler();
+ if (handler != null) {
+ handler.postAtTime(mAutoAdvanceRunnable, advanceTime);
+ }
+ }
+
+ private void runAutoAdvance() {
+ Advanceable target = getAdvanceable();
+ if (target != null) {
+ target.advance();
+ }
+ scheduleNextAdvance();
+ }
}