summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/WindowManagerInternal.java7
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl39
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java69
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java12
-rw-r--r--services/core/java/com/android/server/policy/BarController.java8
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java13
-rw-r--r--services/core/java/com/android/server/policy/StatusBarController.java187
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java30
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java7
12 files changed, 435 insertions, 31 deletions
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index e36cfd2..7b4640b 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -224,4 +224,11 @@ public abstract class WindowManagerInternal {
* @param removeWindows Whether to also remove the windows associated with the token.
*/
public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows);
+
+ /**
+ * Registers a listener to be notified about app transition events.
+ *
+ * @param listener The listener to register.
+ */
+ public abstract void registerAppTransitionListener(AppTransitionListener listener);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index a3c0db4..2b0d244 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -1,19 +1,19 @@
/**
* Copyright (c) 2007, 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
+ * 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
+ * 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
+ * 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.internal.statusbar;
import com.android.internal.statusbar.StatusBarIcon;
@@ -43,5 +43,26 @@ oneway interface IStatusBar
void preloadRecentApps();
void cancelPreloadRecentApps();
void showScreenPinningRequest();
+
+ /**
+ * Notifies the status bar that an app transition is pending to delay applying some flags with
+ * visual impact until {@link #appTransitionReady} is called.
+ */
+ void appTransitionPending();
+
+ /**
+ * Notifies the status bar that a pending app transition has been cancelled.
+ */
+ void appTransitionCancelled();
+
+ /**
+ * Notifies the status bar that an app transition is now being executed.
+ *
+ * @param statusBarAnimationsStartTime the desired start time for all visual animations in the
+ * status bar caused by this app transition in uptime millis
+ * @param statusBarAnimationsDuration the duration for all visual animations in the status
+ * bar caused by this app transition in millis
+ */
+ void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 40c009f..6cb839e 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -1,16 +1,16 @@
/**
* Copyright (c) 2007, 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
+ * 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
+ * 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
+ * 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.
*/
@@ -61,4 +61,25 @@ interface IStatusBarService
void toggleRecentApps();
void preloadRecentApps();
void cancelPreloadRecentApps();
+
+ /**
+ * Notifies the status bar that an app transition is pending to delay applying some flags with
+ * visual impact until {@link #appTransitionReady} is called.
+ */
+ void appTransitionPending();
+
+ /**
+ * Notifies the status bar that a pending app transition has been cancelled.
+ */
+ void appTransitionCancelled();
+
+ /**
+ * Notifies the status bar that an app transition is now being executed.
+ *
+ * @param statusBarAnimationsStartTime the desired start time for all visual animations in the
+ * status bar caused by this app transition in uptime millis
+ * @param statusBarAnimationsDuration the duration for all visual animations in the status
+ * bar caused by this app transition in millis
+ */
+ void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 0b1b883..8f88e73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.util.Pair;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
@@ -57,6 +58,9 @@ public class CommandQueue extends IStatusBar.Stub {
private static final int MSG_NOTIFICATION_LIGHT_OFF = 16 << MSG_SHIFT;
private static final int MSG_NOTIFICATION_LIGHT_PULSE = 17 << MSG_SHIFT;
private static final int MSG_SHOW_SCREEN_PIN_REQUEST = 18 << MSG_SHIFT;
+ private static final int MSG_APP_TRANSITION_PENDING = 19 << MSG_SHIFT;
+ private static final int MSG_APP_TRANSITION_CANCELLED = 20 << MSG_SHIFT;
+ private static final int MSG_APP_TRANSITION_STARTING = 21 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -99,6 +103,9 @@ public class CommandQueue extends IStatusBar.Stub {
public void notificationLightOff();
public void notificationLightPulse(int argb, int onMillis, int offMillis);
public void showScreenPinningRequest();
+ public void appTransitionPending();
+ public void appTransitionCancelled();
+ public void appTransitionStarting(long startTime, long duration);
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -246,6 +253,28 @@ public class CommandQueue extends IStatusBar.Stub {
}
}
+ public void appTransitionPending() {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_APP_TRANSITION_PENDING);
+ mHandler.sendEmptyMessage(MSG_APP_TRANSITION_PENDING);
+ }
+ }
+
+ public void appTransitionCancelled() {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_APP_TRANSITION_PENDING);
+ mHandler.sendEmptyMessage(MSG_APP_TRANSITION_PENDING);
+ }
+ }
+
+ public void appTransitionStarting(long startTime, long duration) {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_APP_TRANSITION_STARTING);
+ mHandler.obtainMessage(MSG_APP_TRANSITION_STARTING, Pair.create(startTime, duration))
+ .sendToTarget();
+ }
+ }
+
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
@@ -328,6 +357,16 @@ public class CommandQueue extends IStatusBar.Stub {
case MSG_SHOW_SCREEN_PIN_REQUEST:
mCallbacks.showScreenPinningRequest();
break;
+ case MSG_APP_TRANSITION_PENDING:
+ mCallbacks.appTransitionPending();
+ break;
+ case MSG_APP_TRANSITION_CANCELLED:
+ mCallbacks.appTransitionCancelled();
+ break;
+ case MSG_APP_TRANSITION_STARTING:
+ Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
+ mCallbacks.appTransitionStarting(data.first, data.second);
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index ece69d3..3740d2a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -101,7 +101,6 @@ import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
-import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
@@ -115,7 +114,6 @@ import com.android.systemui.BatteryMeterView;
import com.android.systemui.DemoMode;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
-import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
@@ -138,7 +136,6 @@ import com.android.systemui.statusbar.NotificationOverflowContainer;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.SpeedBumpView;
-import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.AccessibilityController;
@@ -3638,6 +3635,21 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
+ @Override
+ public void appTransitionPending() {
+ mIconController.appTransitionPending();
+ }
+
+ @Override
+ public void appTransitionCancelled() {
+ mIconController.appTransitionCancelled();
+ }
+
+ @Override
+ public void appTransitionStarting(long startTime, long duration) {
+ mIconController.appTransitionStarting(startTime, duration);
+ }
+
private final class ShadeUpdates {
private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 5622993..8662b04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -16,11 +16,13 @@
package com.android.systemui.statusbar.phone;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Bundle;
+import android.os.SystemClock;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
@@ -48,9 +50,12 @@ import java.util.ArrayList;
*/
public class StatusBarIconController {
+ private static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
+
private Context mContext;
private PhoneStatusBar mPhoneStatusBar;
private Interpolator mLinearOutSlowIn;
+ private Interpolator mFastOutSlowIn;
private DemoStatusIcons mDemoStatusIcons;
private NotificationColorUtil mNotificationColorUtil;
@@ -69,6 +74,11 @@ public class StatusBarIconController {
private int mIconTint = Color.WHITE;
+ private boolean mTransitionPending;
+ private boolean mTintChangePending;
+ private int mPendingIconTint;
+ private ValueAnimator mTintAnimator;
+
public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
PhoneStatusBar phoneStatusBar) {
mContext = context;
@@ -86,6 +96,8 @@ public class StatusBarIconController {
mClock = (TextView) statusBar.findViewById(R.id.clock);
mLinearOutSlowIn = AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.linear_out_slow_in);
+ mFastOutSlowIn = AnimationUtils.loadInterpolator(mContext,
+ android.R.interpolator.fast_out_slow_in);
updateResources();
}
@@ -268,10 +280,45 @@ public class StatusBarIconController {
}
public void setIconTint(int tint) {
+ if (mTransitionPending) {
+ deferIconTintChange(tint);
+ } else {
+ animateIconTint(tint, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+ }
+ }
+
+ private void animateIconTint(int targetTint, long delay, long duration) {
+ if (mTintAnimator != null) {
+ mTintAnimator.cancel();
+ }
+ if (mIconTint == targetTint) {
+ return;
+ }
+ mTintAnimator = ValueAnimator.ofArgb(mIconTint, targetTint);
+ mTintAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ setIconTintInternal((Integer) animation.getAnimatedValue());
+ }
+ });
+ mTintAnimator.setDuration(duration);
+ mTintAnimator.setStartDelay(delay);
+ mTintAnimator.setInterpolator(mFastOutSlowIn);
+ mTintAnimator.start();
+ }
+ private void setIconTintInternal(int tint) {
mIconTint = tint;
applyIconTint();
}
+ private void deferIconTintChange(int tint) {
+ if (mTintChangePending && tint == mPendingIconTint) {
+ return;
+ }
+ mTintChangePending = true;
+ mPendingIconTint = tint;
+ }
+
private void applyIconTint() {
for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
StatusBarIconView v = (StatusBarIconView) mStatusIcons.getChildAt(i);
@@ -305,4 +352,26 @@ public class StatusBarIconController {
v.setTag(R.id.icon_is_grayscale, grayscale);
return grayscale;
}
+
+ public void appTransitionPending() {
+ mTransitionPending = true;
+ }
+
+ public void appTransitionCancelled() {
+ if (mTransitionPending && mTintChangePending) {
+ mTintChangePending = false;
+ animateIconTint(mPendingIconTint, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+ }
+ mTransitionPending = false;
+ }
+
+ public void appTransitionStarting(long startTime, long duration) {
+ if (mTransitionPending && mTintChangePending) {
+ mTintChangePending = false;
+ animateIconTint(mPendingIconTint,
+ Math.max(0, startTime - SystemClock.uptimeMillis()),
+ duration);
+ }
+ mTransitionPending = false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 6f2a392..413c891 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -170,4 +170,16 @@ public class TvStatusBar extends BaseStatusBar {
@Override
public void showScreenPinningRequest() {
}
+
+ @Override
+ public void appTransitionPending() {
+ }
+
+ @Override
+ public void appTransitionCancelled() {
+ }
+
+ @Override
+ public void appTransitionStarting(long startTime, long duration) {
+ }
}
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index bca2c16..e972ec7 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -43,15 +43,15 @@ public class BarController {
private static final int TRANSLUCENT_ANIMATION_DELAY_MS = 1000;
- private final String mTag;
+ protected final String mTag;
private final int mTransientFlag;
private final int mUnhideFlag;
private final int mTranslucentFlag;
private final int mStatusBarManagerId;
private final int mTranslucentWmFlag;
- private final Handler mHandler;
+ protected final Handler mHandler;
private final Object mServiceAquireLock = new Object();
- private IStatusBarService mStatusBarService;
+ protected IStatusBarService mStatusBarService;
private WindowState mWin;
private int mState = StatusBarManager.WINDOW_STATE_SHOWING;
@@ -254,7 +254,7 @@ public class BarController {
}
}
- private IStatusBarService getStatusBarService() {
+ protected IStatusBarService getStatusBarService() {
synchronized (mServiceAquireLock) {
if (mStatusBarService == null) {
mStatusBarService = IStatusBarService.Stub.asInterface(
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b90d263..f691b4e 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -74,6 +74,7 @@ import android.telecom.TelecomManager;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
@@ -103,6 +104,8 @@ import android.view.accessibility.AccessibilityManager;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.view.animation.TranslateAnimation;
import com.android.internal.R;
import com.android.internal.statusbar.IStatusBarService;
@@ -724,12 +727,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
MyOrientationListener mOrientationListener;
- private final BarController mStatusBarController = new BarController("StatusBar",
- View.STATUS_BAR_TRANSIENT,
- View.STATUS_BAR_UNHIDE,
- View.STATUS_BAR_TRANSLUCENT,
- StatusBarManager.WINDOW_STATUS_BAR,
- WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ private final StatusBarController mStatusBarController = new StatusBarController();
private final BarController mNavigationBarController = new BarController("NavigationBar",
View.NAVIGATION_BAR_TRANSIENT,
@@ -1359,6 +1357,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (!mPowerManager.isInteractive()) {
goingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
}
+
+ mWindowManagerInternal.registerAppTransitionListener(
+ mStatusBarController.getAppTransitionListener());
}
/**
diff --git a/services/core/java/com/android/server/policy/StatusBarController.java b/services/core/java/com/android/server/policy/StatusBarController.java
new file mode 100644
index 0000000..4d4ab44
--- /dev/null
+++ b/services/core/java/com/android/server/policy/StatusBarController.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2015 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.server.policy;
+
+import android.app.StatusBarManager;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManagerInternal;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.Interpolator;
+import android.view.animation.TranslateAnimation;
+
+import com.android.internal.statusbar.IStatusBarService;
+
+import static android.view.WindowManagerInternal.*;
+
+/**
+ * Implements status bar specific behavior.
+ */
+public class StatusBarController extends BarController {
+
+ private static final long TRANSITION_DURATION = 120L;
+
+ private final AppTransitionListener mAppTransitionListener
+ = new AppTransitionListener() {
+
+ @Override
+ public void onAppTransitionPendingLocked() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ IStatusBarService statusbar = getStatusBarService();
+ if (statusbar != null) {
+ statusbar.appTransitionPending();
+ }
+ } catch (RemoteException e) {
+ Slog.e(mTag, "RemoteException when app transition is pending", e);
+ // re-acquire status bar service next time it is needed.
+ mStatusBarService = null;
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onAppTransitionStartingLocked(IBinder openToken, IBinder closeToken,
+ final Animation openAnimation, final Animation closeAnimation) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ IStatusBarService statusbar = getStatusBarService();
+ if (statusbar != null) {
+ long startTime = calculateStatusBarTransitionStartTime(openAnimation,
+ closeAnimation);
+ statusbar.appTransitionStarting(startTime, TRANSITION_DURATION);
+ }
+ } catch (RemoteException e) {
+ Slog.e(mTag, "RemoteException when app transition is starting", e);
+ // re-acquire status bar service next time it is needed.
+ mStatusBarService = null;
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onAppTransitionCancelledLocked() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ IStatusBarService statusbar = getStatusBarService();
+ if (statusbar != null) {
+ statusbar.appTransitionCancelled();
+ }
+ } catch (RemoteException e) {
+ Slog.e(mTag, "RemoteException when app transition is cancelled", e);
+ // re-acquire status bar service next time it is needed.
+ mStatusBarService = null;
+ }
+ }
+ });
+ }
+ };
+
+ public StatusBarController() {
+ super("StatusBar",
+ View.STATUS_BAR_TRANSIENT,
+ View.STATUS_BAR_UNHIDE,
+ View.STATUS_BAR_TRANSLUCENT,
+ StatusBarManager.WINDOW_STATUS_BAR,
+ WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ }
+
+ public AppTransitionListener getAppTransitionListener() {
+ return mAppTransitionListener;
+ }
+
+ /**
+ * For a given app transition with {@code openAnimation} and {@code closeAnimation}, this
+ * calculates the timings for the corresponding status bar transition.
+ *
+ * @return the desired start time of the status bar transition, in uptime millis
+ */
+ private long calculateStatusBarTransitionStartTime(Animation openAnimation,
+ Animation closeAnimation) {
+ if (openAnimation != null && closeAnimation != null) {
+ TranslateAnimation openTranslateAnimation = findTranslateAnimation(openAnimation);
+ TranslateAnimation closeTranslateAnimation = findTranslateAnimation(closeAnimation);
+ if (openTranslateAnimation != null) {
+
+ // Some interpolators are extremely quickly mostly finished, but not completely. For
+ // our purposes, we need to find the fraction for which ther interpolator is mostly
+ // there, and use that value for the calculation.
+ float t = findAlmostThereFraction(openTranslateAnimation.getInterpolator());
+ return SystemClock.uptimeMillis()
+ + openTranslateAnimation.getStartOffset()
+ + (long)(openTranslateAnimation.getDuration()*t) - TRANSITION_DURATION;
+ } else if (closeTranslateAnimation != null) {
+ return SystemClock.uptimeMillis();
+ } else {
+ return SystemClock.uptimeMillis();
+ }
+ } else {
+ return SystemClock.uptimeMillis();
+ }
+ }
+
+ /**
+ * Tries to find a {@link TranslateAnimation} inside the {@code animation}.
+ *
+ * @return the found animation, {@code null} otherwise
+ */
+ private TranslateAnimation findTranslateAnimation(Animation animation) {
+ if (animation instanceof TranslateAnimation) {
+ return (TranslateAnimation) animation;
+ } else if (animation instanceof AnimationSet) {
+ AnimationSet set = (AnimationSet) animation;
+ for (int i = 0; i < set.getAnimations().size(); i++) {
+ Animation a = set.getAnimations().get(i);
+ if (a instanceof TranslateAnimation) {
+ return (TranslateAnimation) a;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Binary searches for a {@code t} such that there exists a {@code -0.01 < eps < 0.01} for which
+ * {@code interpolator(t + eps) > 0.99}.
+ */
+ private float findAlmostThereFraction(Interpolator interpolator) {
+ float val = 0.5f;
+ float adj = 0.25f;
+ while (adj >= 0.01f) {
+ if (interpolator.getInterpolation(val) < 0.99f) {
+ val += adj;
+ } else {
+ val -= adj;
+ }
+ adj /= 2;
+ }
+ return val;
+ }
+}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index cf2ed07..f6df757 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -454,6 +454,35 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
}
}
+ @Override
+ public void appTransitionPending() {
+ if (mBar != null) {
+ try {
+ mBar.appTransitionPending();
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
+ public void appTransitionCancelled() {
+ if (mBar != null) {
+ try {
+ mBar.appTransitionCancelled();
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
+ public void appTransitionStarting(long statusBarAnimationsStartTime,
+ long statusBarAnimationsDuration) {
+ if (mBar != null) {
+ try {
+ mBar.appTransitionStarting(
+ statusBarAnimationsStartTime, statusBarAnimationsDuration);
+ } catch (RemoteException ex) {}
+ }
+ }
+
private void enforceStatusBar() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR,
"StatusBarManagerService");
@@ -625,7 +654,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
}
}
-
// ================================================================================
// Can be called from any thread
// ================================================================================
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1852be2..de8a2fc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -11619,5 +11619,12 @@ public class WindowManagerService extends IWindowManager.Stub
WindowManagerService.this.removeWindowToken(token);
}
}
+
+ @Override
+ public void registerAppTransitionListener(AppTransitionListener listener) {
+ synchronized (mWindowMap) {
+ mAppTransition.registerListenerLocked(listener);
+ }
+ }
}
}