diff options
30 files changed, 705 insertions, 229 deletions
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 24844ba46c28..a48a38882085 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -905,7 +905,7 @@ public class ConnectivityManager { return null; } - private int networkTypeForNetworkCapabilities(NetworkCapabilities netCap) { + private int legacyTypeForNetworkCapabilities(NetworkCapabilities netCap) { if (netCap == null) return TYPE_NONE; if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) { return TYPE_MOBILE_CBS; @@ -928,6 +928,9 @@ public class ConnectivityManager { if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { return TYPE_MOBILE_HIPRI; } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P)) { + return TYPE_WIFI_P2P; + } return TYPE_NONE; } @@ -988,7 +991,7 @@ public class ConnectivityManager { private NetworkRequest requestNetworkForFeatureLocked(NetworkCapabilities netCap) { int delay = -1; - int type = networkTypeForNetworkCapabilities(netCap); + int type = legacyTypeForNetworkCapabilities(netCap); try { delay = mService.getRestoreDefaultNetworkDelay(type); } catch (RemoteException e) {} @@ -997,7 +1000,7 @@ public class ConnectivityManager { l.delay = delay; l.expireSequenceNumber = 0; l.networkRequest = sendRequestForNetwork(netCap, l.networkCallbackListener, 0, - REQUEST, true); + REQUEST, type); if (l.networkRequest == null) return null; sLegacyRequests.put(netCap, l); sendExpireMsgForFeature(netCap, l.expireSequenceNumber, delay); @@ -2144,7 +2147,7 @@ public class ConnectivityManager { private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallbackListener networkCallbackListener, int timeoutSec, int action, - boolean legacy) { + int legacyType) { NetworkRequest networkRequest = null; if (networkCallbackListener == null) { throw new IllegalArgumentException("null NetworkCallbackListener"); @@ -2157,7 +2160,7 @@ public class ConnectivityManager { new Binder()); } else { networkRequest = mService.requestNetwork(need, new Messenger(sCallbackHandler), - timeoutSec, new Binder(), legacy); + timeoutSec, new Binder(), legacyType); } if (networkRequest != null) { synchronized(sNetworkCallbackListener) { @@ -2187,7 +2190,7 @@ public class ConnectivityManager { */ public NetworkRequest requestNetwork(NetworkCapabilities need, NetworkCallbackListener networkCallbackListener) { - return sendRequestForNetwork(need, networkCallbackListener, 0, REQUEST, false); + return sendRequestForNetwork(need, networkCallbackListener, 0, REQUEST, TYPE_NONE); } /** @@ -2210,7 +2213,8 @@ public class ConnectivityManager { */ public NetworkRequest requestNetwork(NetworkCapabilities need, NetworkCallbackListener networkCallbackListener, int timeoutSec) { - return sendRequestForNetwork(need, networkCallbackListener, timeoutSec, REQUEST, false); + return sendRequestForNetwork(need, networkCallbackListener, timeoutSec, REQUEST, + TYPE_NONE); } /** @@ -2288,7 +2292,7 @@ public class ConnectivityManager { */ public NetworkRequest listenForNetwork(NetworkCapabilities need, NetworkCallbackListener networkCallbackListener) { - return sendRequestForNetwork(need, networkCallbackListener, 0, LISTEN, false); + return sendRequestForNetwork(need, networkCallbackListener, 0, LISTEN, TYPE_NONE); } /** diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index b67ae88c880c..5f1ff3e1d9d6 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -158,7 +158,7 @@ interface IConnectivityManager in NetworkCapabilities nc, int score); NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, - in Messenger messenger, int timeoutSec, in IBinder binder, boolean legacy); + in Messenger messenger, int timeoutSec, in IBinder binder, int legacy); NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities, in PendingIntent operation); diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java index ccc56e23af75..d2794127f542 100644 --- a/core/java/android/net/NetworkInfo.java +++ b/core/java/android/net/NetworkInfo.java @@ -188,6 +188,15 @@ public class NetworkInfo implements Parcelable { } /** + * @hide + */ + public void setType(int type) { + synchronized (this) { + mNetworkType = type; + } + } + + /** * Return a network-type-specific integer describing the subtype * of the network. * @return the network subtype diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 480cb057b075..47377e97be43 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -47,19 +47,19 @@ public class NetworkRequest implements Parcelable { public final int requestId; /** - * Set for legacy requests and the default. + * Set for legacy requests and the default. Set to TYPE_NONE for none. * Causes CONNECTIVITY_ACTION broadcasts to be sent. * @hide */ - public final boolean needsBroadcasts; + public final int legacyType; /** * @hide */ - public NetworkRequest(NetworkCapabilities nc, boolean needsBroadcasts, int rId) { + public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId) { requestId = rId; networkCapabilities = nc; - this.needsBroadcasts = needsBroadcasts; + this.legacyType = legacyType; } /** @@ -68,7 +68,7 @@ public class NetworkRequest implements Parcelable { public NetworkRequest(NetworkRequest that) { networkCapabilities = new NetworkCapabilities(that.networkCapabilities); requestId = that.requestId; - needsBroadcasts = that.needsBroadcasts; + this.legacyType = that.legacyType; } // implement the Parcelable interface @@ -77,16 +77,16 @@ public class NetworkRequest implements Parcelable { } public void writeToParcel(Parcel dest, int flags) { dest.writeParcelable(networkCapabilities, flags); - dest.writeInt(needsBroadcasts ? 1 : 0); + dest.writeInt(legacyType); dest.writeInt(requestId); } public static final Creator<NetworkRequest> CREATOR = new Creator<NetworkRequest>() { public NetworkRequest createFromParcel(Parcel in) { NetworkCapabilities nc = (NetworkCapabilities)in.readParcelable(null); - boolean needsBroadcasts = (in.readInt() == 1); + int legacyType = in.readInt(); int requestId = in.readInt(); - NetworkRequest result = new NetworkRequest(nc, needsBroadcasts, requestId); + NetworkRequest result = new NetworkRequest(nc, legacyType, requestId); return result; } public NetworkRequest[] newArray(int size) { @@ -95,14 +95,14 @@ public class NetworkRequest implements Parcelable { }; public String toString() { - return "NetworkRequest [ id=" + requestId + ", needsBroadcasts=" + needsBroadcasts + + return "NetworkRequest [ id=" + requestId + ", legacyType=" + legacyType + ", " + networkCapabilities.toString() + " ]"; } public boolean equals(Object obj) { if (obj instanceof NetworkRequest == false) return false; NetworkRequest that = (NetworkRequest)obj; - return (that.needsBroadcasts == this.needsBroadcasts && + return (that.legacyType == this.legacyType && that.requestId == this.requestId && ((that.networkCapabilities == null && this.networkCapabilities == null) || (that.networkCapabilities != null && @@ -110,7 +110,7 @@ public class NetworkRequest implements Parcelable { } public int hashCode() { - return requestId + (needsBroadcasts ? 1013 : 2026) + + return requestId + (legacyType * 1013) + (networkCapabilities.hashCode() * 1051); } } diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index 9d7a8b6071e2..543f4fbf72fe 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -441,8 +441,11 @@ public class RippleDrawable extends LayerDrawable { final int count = mAnimatingRipplesCount; final Ripple[] ripples = mAnimatingRipples; for (int i = 0; i < count; i++) { - ripples[i].cancel(); + // Calling cancel may remove the ripple from the animating ripple + // array, so cache the reference before nulling it out. + final Ripple ripple = ripples[i]; ripples[i] = null; + ripple.cancel(); } mAnimatingRipplesCount = 0; diff --git a/packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.png Binary files differnew file mode 100644 index 000000000000..6cd1176c5fdc --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.png diff --git a/packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.png Binary files differnew file mode 100644 index 000000000000..7237f0991028 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.png diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.png Binary files differnew file mode 100644 index 000000000000..8d56a1d41b4c --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.png Binary files differnew file mode 100644 index 000000000000..aed300bd197c --- /dev/null +++ b/packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.png diff --git a/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml b/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml new file mode 100644 index 000000000000..463fee81f8b4 --- /dev/null +++ b/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<ImageView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal|bottom" + android:scaleType="fitXY" + android:src="@drawable/recents_nav_bar_background" />
\ No newline at end of file diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 0184df2052dc..79a1df41d2a8 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -113,17 +113,20 @@ <!-- The min animation duration for animating views that are newly visible. --> <integer name="recents_filter_animate_new_views_min_duration">125</integer> <!-- The min animation duration for animating the task bar in. --> - <integer name="recents_animate_task_bar_enter_duration">300</integer> + <integer name="recents_animate_task_bar_enter_duration">250</integer> + <!-- The animation delay for animating the first task in. This should roughly be the animation + duration of the transition in to recents. --> + <integer name="recents_animate_task_bar_enter_delay">225</integer> <!-- The min animation duration for animating the task bar out. --> - <integer name="recents_animate_task_bar_exit_duration">150</integer> - <!-- The animation duration for animating in the info pane. --> - <integer name="recents_animate_task_view_info_pane_duration">150</integer> + <integer name="recents_animate_task_bar_exit_duration">125</integer> + <!-- The min animation duration for animating the nav bar scrim in. --> + <integer name="recents_nav_bar_scrim_enter_duration">400</integer> <!-- The animation duration for animating the removal of a task view. --> <integer name="recents_animate_task_view_remove_duration">250</integer> <!-- The minimum alpha for the dim applied to cards that go deeper into the stack. --> <integer name="recents_max_task_stack_view_dim">96</integer> - <!-- Transposes the search bar layout in landscape --> - <bool name="recents_transpose_search_layout_with_orientation">true</bool> + <!-- Transposes the recents layout in landscape. --> + <bool name="recents_transpose_layout_with_orientation">true</bool> <!-- Whether to enable KeyguardService or not --> <bool name="config_enableKeyguardService">true</bool> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 60a5643ba35d..9f12124f7191 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -322,6 +322,17 @@ <!-- Distance between notifications and header when they are considered to be colliding. --> <dimen name="header_notifications_collide_distance">24dp</dimen> - <!-- Move distance for the hint animations on the lockscreen (unlock, phone, camera)--> + <!-- Distance the user needs to drag vertically such that a swipe is accepted to unlock the + device. --> + <dimen name="unlock_move_distance">75dp</dimen> + + <!-- Move distance for the unlock hint animation on the lockscreen --> <dimen name="hint_move_distance">75dp</dimen> + + <!-- Move distance for the other hint animations on the lockscreen (phone, camera)--> + <dimen name="hint_move_distance_sideways">60dp</dimen> + + <!-- The width of the region on the left/right edge of the screen for performing the camera/ + phone hints. --> + <dimen name="edge_tap_area_width">48dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 373f11f532c0..7ab010a6b2e0 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -572,6 +572,12 @@ <!-- Shows when people have pressed the unlock icon to explain how to unlock. [CHAR LIMIT=60] --> <string name="keyguard_unlock">Swipe up to unlock</string> + <!-- Shows when people have clicked at the left edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] --> + <string name="phone_hint">Swipe right for phone</string> + + <!-- Shows when people have clicked at the right edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] --> + <string name="camera_hint">Swipe left for camera</string> + <string name="bugreport_tile_extended" translatable="false">%s\n%s (%s)</string> <!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] --> diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 00ee078f7ee7..c006c88174a7 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -906,6 +906,7 @@ public class KeyguardViewMediator extends SystemUI { if (mLockPatternUtils.checkVoldPassword()) { if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted"); // Without this, settings is not enabled until the lock screen first appears + mShowing = false; hideLocked(); return; } @@ -1219,9 +1220,17 @@ public class KeyguardViewMediator extends SystemUI { if (DEBUG) Log.d(TAG, "handleHide"); try { - // Don't actually hide the Keyguard at the moment, wait for window manager until - // it tells us it's safe to do so with startKeyguardExitAnimation. - mWM.keyguardGoingAway(); + if (mShowing) { + + // Don't actually hide the Keyguard at the moment, wait for window manager until + // it tells us it's safe to do so with startKeyguardExitAnimation. + mWM.keyguardGoingAway(); + } else { + + // Don't try to rely on WindowManager - if Keyguard wasn't showing, window + // manager won't start the exit animation. + handleStartKeyguardExitAnimation(0, 0); + } } catch (RemoteException e) { Log.e(TAG, "Error while calling WindowManager", e); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java index ca9bb94f68c5..bb19415499bf 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java @@ -152,6 +152,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta // Recents service binding Messenger mService = null; Messenger mMessenger; + RecentsMessageHandler mHandler; boolean mServiceIsBound = false; boolean mToggleRecentsUponServiceBound; RecentsServiceConnection mConnection = new RecentsServiceConnection(); @@ -168,7 +169,8 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta public AlternateRecentsComponent(Context context) { mContext = context; mSystemServicesProxy = new SystemServicesProxy(context); - mMessenger = new Messenger(new RecentsMessageHandler()); + mHandler = new RecentsMessageHandler(); + mMessenger = new Messenger(mHandler); } public void onStart() { @@ -507,7 +509,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta if (!useThumbnailTransition) { ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, R.anim.recents_from_launcher_enter, - R.anim.recents_from_launcher_exit); + R.anim.recents_from_launcher_exit, mHandler, this); startAlternateRecentsActivity(opts, false); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index df387c1a375e..fa8523448842 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -26,11 +26,14 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Configuration; import android.os.Bundle; import android.util.Pair; +import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.view.WindowManager; import android.widget.FrameLayout; import com.android.systemui.R; @@ -67,6 +70,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView FrameLayout mContainerView; RecentsView mRecentsView; View mEmptyView; + View mNavBarScrimView; AppWidgetHost mAppWidgetHost; AppWidgetProviderInfo mSearchAppWidgetInfo; @@ -99,7 +103,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView dismissRecentsIfVisible(); } } else if (action.equals(RecentsService.ACTION_START_ENTER_ANIMATION)) { - // Try and start the enter animation + // Try and start the enter animation (or restart it on configuration changed) mRecentsView.startOnEnterAnimation(); } } @@ -129,6 +133,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView mRecentsView.setBSP(root); } + // Hide the scrim by default when we enter recents + mNavBarScrimView.setVisibility(View.INVISIBLE); + // Add the default no-recents layout if (stacks.size() == 1 && stacks.get(0).getTaskCount() == 0) { mEmptyView.setVisibility(View.VISIBLE); @@ -269,10 +276,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView // Create the empty view LayoutInflater inflater = LayoutInflater.from(this); mEmptyView = inflater.inflate(R.layout.recents_empty, mContainerView, false); + mNavBarScrimView = inflater.inflate(R.layout.recents_nav_bar_scrim, mContainerView, false); mContainerView = new FrameLayout(this); mContainerView.addView(mRecentsView); mContainerView.addView(mEmptyView); + mContainerView.addView(mNavBarScrimView); setContentView(mContainerView); // Update the recent tasks @@ -282,6 +291,16 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView bindSearchBarAppWidget(); // Add the search bar layout addSearchBarAppWidgetView(); + + // Update if we are getting a configuration change + if (savedInstanceState != null) { + onConfigurationChange(); + } + } + + void onConfigurationChange() { + // Try and start the enter animation (or restart it on configuration changed) + mRecentsView.startOnEnterAnimation(); } @Override @@ -433,8 +452,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView @Override public void onBackPressed() { - boolean interceptedByInfoPanelClose = false; - // Unfilter any stacks if (!mRecentsView.unfilterFilteredStacks()) { super.onBackPressed(); @@ -442,8 +459,35 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView } @Override - public void onTaskLaunching() { + public void onEnterAnimationTriggered() { + // Fade in the scrim + RecentsConfiguration config = RecentsConfiguration.getInstance(); + if (config.hasNavBarScrim()) { + mNavBarScrimView.setVisibility(View.VISIBLE); + mNavBarScrimView.setAlpha(0f); + mNavBarScrimView.animate().alpha(1f) + .setStartDelay(config.taskBarEnterAnimDelay) + .setDuration(config.navBarScrimEnterDuration) + .setInterpolator(config.fastOutSlowInInterpolator) + .withLayer() + .start(); + } + } + + @Override + public void onTaskLaunching(boolean isTaskInStackBounds) { mTaskLaunched = true; + + // Fade out the scrim + RecentsConfiguration config = RecentsConfiguration.getInstance(); + if (!isTaskInStackBounds && config.hasNavBarScrim()) { + mNavBarScrimView.animate().alpha(0f) + .setStartDelay(0) + .setDuration(config.taskBarExitAnimDuration) + .setInterpolator(config.fastOutSlowInInterpolator) + .withLayer() + .start(); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java index 63916858705d..0cf6ee66ac35 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -41,7 +41,7 @@ public class RecentsConfiguration { public Rect displayRect = new Rect(); boolean isLandscape; - boolean transposeSearchLayoutWithOrientation; + boolean transposeRecentsLayoutWithOrientation; int searchBarAppWidgetId = -1; public float animationPxMovementPerSecond; @@ -58,7 +58,6 @@ public class RecentsConfiguration { public float taskStackWidthPaddingPct; public int taskStackTopPaddingPx; - public int taskViewInfoPaneAnimDuration; public int taskViewRemoveAnimDuration; public int taskViewRemoveAnimTranslationXPx; public int taskViewTranslationZMinPx; @@ -76,8 +75,11 @@ public class RecentsConfiguration { public int taskBarViewHighlightColor; public int taskBarEnterAnimDuration; + public int taskBarEnterAnimDelay; public int taskBarExitAnimDuration; + public int navBarScrimEnterDuration; + public boolean launchedFromAltTab; public boolean launchedWithThumbnailAnimation; @@ -108,8 +110,8 @@ public class RecentsConfiguration { isLandscape = res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; - transposeSearchLayoutWithOrientation = - res.getBoolean(R.bool.recents_transpose_search_layout_with_orientation); + transposeRecentsLayoutWithOrientation = + res.getBoolean(R.bool.recents_transpose_layout_with_orientation); if (Console.Enabled) { Console.log(Constants.Log.UI.MeasureAndLayout, "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait", @@ -133,8 +135,6 @@ public class RecentsConfiguration { taskStackWidthPaddingPct = widthPaddingPctValue.getFloat(); taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding); - taskViewInfoPaneAnimDuration = - res.getInteger(R.integer.recents_animate_task_view_info_pane_duration); taskViewRemoveAnimDuration = res.getInteger(R.integer.recents_animate_task_view_remove_duration); taskViewRemoveAnimTranslationXPx = @@ -163,9 +163,14 @@ public class RecentsConfiguration { taskBarEnterAnimDuration = res.getInteger(R.integer.recents_animate_task_bar_enter_duration); + taskBarEnterAnimDelay = + res.getInteger(R.integer.recents_animate_task_bar_enter_delay); taskBarExitAnimDuration = res.getInteger(R.integer.recents_animate_task_bar_exit_duration); + navBarScrimEnterDuration = + res.getInteger(R.integer.recents_nav_bar_scrim_enter_duration); + fastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.fast_out_slow_in); fastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context, @@ -203,11 +208,16 @@ public class RecentsConfiguration { launchedWithThumbnailAnimation = false; } - /** Returns whether the search bar app widget exists */ + /** Returns whether the search bar app widget exists. */ public boolean hasSearchBarAppWidget() { return searchBarAppWidgetId >= 0; } + /** Returns whether the nav bar scrim should be visible. */ + public boolean hasNavBarScrim() { + return !transposeRecentsLayoutWithOrientation || !isLandscape; + } + /** * Returns the task stack bounds in the current orientation. These bounds do not account for * the system insets. @@ -216,7 +226,7 @@ public class RecentsConfiguration { if (hasSearchBarAppWidget()) { Rect searchBarBounds = new Rect(); getSearchBarBounds(width, height, searchBarBounds); - if (isLandscape && transposeSearchLayoutWithOrientation) { + if (isLandscape && transposeRecentsLayoutWithOrientation) { // In landscape, the search bar appears on the left, so shift the task rect right taskStackBounds.set(searchBarBounds.width(), 0, width, height); } else { @@ -239,7 +249,7 @@ public class RecentsConfiguration { return; } - if (isLandscape && transposeSearchLayoutWithOrientation) { + if (isLandscape && transposeRecentsLayoutWithOrientation) { // In landscape, the search bar appears on the left searchBarSpaceBounds.set(0, 0, searchBarSpaceHeightPx, height); } else { diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java index 4e620b644457..8bcc7f5dcdeb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java @@ -38,6 +38,7 @@ public class RecentsPackageMonitor extends PackageMonitor { PackageCallbacks mCb; List<ActivityManager.RecentTaskInfo> mTasks; SystemServicesProxy mSsp; + boolean mRegistered; public RecentsPackageMonitor(Context context) { mSsp = new SystemServicesProxy(context); @@ -46,13 +47,19 @@ public class RecentsPackageMonitor extends PackageMonitor { /** Registers the broadcast receivers with the specified callbacks. */ public void register(Context context, PackageCallbacks cb) { mCb = cb; - register(context, Looper.getMainLooper(), false); + if (!mRegistered) { + register(context, Looper.getMainLooper(), false); + mRegistered = true; + } } /** Unregisters the broadcast receivers. */ @Override public void unregister() { - super.unregister(); + if (mRegistered) { + super.unregister(); + mRegistered = false; + } mTasks.clear(); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 6005275d251b..db398b18a854 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -54,7 +54,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV /** The RecentsView callbacks */ public interface RecentsViewCallbacks { - public void onTaskLaunching(); + public void onTaskLaunching(boolean isTaskInStackBounds); + public void onEnterAnimationTriggered(); } // The space partitioning root of this container @@ -160,6 +161,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV /** Requests all task stacks to start their enter-recents animation */ public void startOnEnterAnimation() { + // Notify callbacks that we are starting the enter animation + mCb.onEnterAnimationTriggered(); + int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); @@ -351,7 +355,11 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV final TaskStack stack, final Task task) { // Notify any callbacks of the launching of a new task if (mCb != null) { - mCb.onTaskLaunching(); + boolean isTaskInStackBounds = false; + if (stackView != null && tv != null) { + isTaskInStackBounds = stackView.isTaskInStackBounds(tv); + } + mCb.onTaskLaunching(isTaskInStackBounds); } final Runnable launchRunnable = new Runnable() { diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 053f1224c9f4..5830e37edca8 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -430,6 +430,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal return getScrollAmountOutOfBounds(getStackScroll()) != 0; } + /** Returns whether the task view is in the stack bounds or not */ + boolean isTaskInStackBounds(TaskView tv) { + Rect r = new Rect(); + tv.getHitRect(r); + return r.bottom <= mRect.bottom; + } + /** Updates the min and max virtual scroll bounds */ void updateMinMaxScroll(boolean boundScrollToNewMinMax) { // Compute the min and max scroll values diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index ffa181deeed7..632c816edad5 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -234,7 +234,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On mBarView.setTranslationY(-mBarView.getMeasuredHeight()); mBarView.animate() .translationY(0) - .setStartDelay(200) + .setStartDelay(config.taskBarEnterAnimDelay) .setInterpolator(config.fastOutSlowInInterpolator) .setDuration(config.taskBarEnterAnimDuration) .withLayer() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java index de27119f6fd4..4233ab8c300d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java @@ -52,7 +52,7 @@ public class InterceptedNotifications { for (int i = 0; i < n; i++) { final StatusBarNotification sbn = mIntercepted.valueAt(i); mReleased.add(sbn.getKey()); - mBar.addNotificationInternal(sbn, null); + mBar.displayNotification(sbn, null); } mIntercepted.clear(); updateSyntheticNotification(); @@ -71,16 +71,17 @@ public class InterceptedNotifications { public void retryIntercepts(Ranking ranking) { if (ranking == null) return; - boolean changed = false; final int N = mIntercepted.size(); + final ArraySet<String> removed = new ArraySet<String>(N); for (int i = 0; i < N; i++) { final StatusBarNotification sbn = mIntercepted.valueAt(i); if (!tryIntercept(sbn, ranking)) { - changed = true; - mBar.addNotificationInternal(sbn, ranking); + removed.add(sbn.getKey()); + mBar.displayNotification(sbn, ranking); } } - if (changed) { + if (!removed.isEmpty()) { + mIntercepted.removeAll(removed); updateSyntheticNotification(); } } @@ -96,12 +97,6 @@ public class InterceptedNotifications { return ent.key.equals(mSynKey); } - public void update(StatusBarNotification notification) { - if (mIntercepted.containsKey(notification.getKey())) { - mIntercepted.put(notification.getKey(), notification); - } - } - private boolean shouldDisplayIntercepted() { return Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.DISPLAY_INTERCEPTED_NOTIFICATIONS, 0) != 0; @@ -129,7 +124,7 @@ public class InterceptedNotifications { mBar.getCurrentUserHandle()); if (mSynKey == null) { mSynKey = sbn.getKey(); - mBar.addNotificationInternal(sbn, null); + mBar.displayNotification(sbn, null); } else { mBar.updateNotificationInternal(sbn, null); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java index 367d32611dbb..0fdc185ec648 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java @@ -27,6 +27,7 @@ public class BounceInterpolator implements Interpolator { @Override public float getInterpolation(float t) { + t *= 11f / 10f; if (t < 4f / 11f) { return SCALE_FACTOR * t * t; } else if (t < 8f / 11f) { @@ -36,8 +37,7 @@ public class BounceInterpolator implements Interpolator { float t2 = t - 9f / 11f; return SCALE_FACTOR * t2 * t2 + 15f / 16f; } else { - float t2 = t - 21f / 22f; - return SCALE_FACTOR * t2 * t2 + 63f / 64f; + return 1; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardPageSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardPageSwipeHelper.java index 0e3e9e6ea43a..086a266c443a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardPageSwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardPageSwipeHelper.java @@ -28,6 +28,7 @@ import android.view.ViewConfiguration; import android.view.ViewPropertyAnimator; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; + import com.android.systemui.R; import com.android.systemui.statusbar.FlingAnimationUtils; @@ -39,7 +40,10 @@ import java.util.ArrayList; public class KeyguardPageSwipeHelper { private static final float SWIPE_MAX_ICON_SCALE_AMOUNT = 2.0f; - private static final float SWIPE_RESTING_ALPHA_AMOUNT = 0.7f; + public static final float SWIPE_RESTING_ALPHA_AMOUNT = 0.5f; + public static final long HINT_PHASE1_DURATION = 250; + private static final long HINT_PHASE2_DURATION = 450; + private final Context mContext; private FlingAnimationUtils mFlingAnimationUtils; @@ -54,11 +58,13 @@ public class KeyguardPageSwipeHelper { private int mTouchSlop; private int mMinTranslationAmount; private int mMinFlingVelocity; + private int mHintDistance; private PowerManager mPowerManager; private final View mLeftIcon; private final View mCenterIcon; private final View mRightIcon; private Interpolator mFastOutSlowIn; + private Interpolator mBounceInterpolator; private Animator mSwipeAnimator; private boolean mCallbackCalled; @@ -81,9 +87,12 @@ public class KeyguardPageSwipeHelper { mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity(); mMinTranslationAmount = mContext.getResources().getDimensionPixelSize( R.dimen.keyguard_min_swipe_amount); + mHintDistance = + mContext.getResources().getDimensionPixelSize(R.dimen.hint_move_distance_sideways); mFlingAnimationUtils = new FlingAnimationUtils(mContext, 0.4f); mFastOutSlowIn = AnimationUtils.loadInterpolator(mContext, android.R.interpolator.fast_out_slow_in); + mBounceInterpolator = new BounceInterpolator(); } public boolean onTouchEvent(MotionEvent event) { @@ -168,6 +177,83 @@ public class KeyguardPageSwipeHelper { return false; } + public void startHintAnimation(boolean right, Runnable onFinishedListener) { + startHintAnimationPhase1(right, onFinishedListener); + } + + /** + * Phase 1: Move everything sidewards. + */ + private void startHintAnimationPhase1(boolean right, final Runnable onFinishedListener) { + float target = right ? -mHintDistance : mHintDistance; + startHintTranslationAnimations(target, HINT_PHASE1_DURATION, mFastOutSlowIn); + ValueAnimator animator = ValueAnimator.ofFloat(mTranslation, target); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mTranslation = (float) animation.getAnimatedValue(); + } + }); + animator.addListener(new AnimatorListenerAdapter() { + private boolean mCancelled; + + @Override + public void onAnimationCancel(Animator animation) { + mCancelled = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (mCancelled) { + mSwipeAnimator = null; + onFinishedListener.run(); + } else { + startUnlockHintAnimationPhase2(onFinishedListener); + } + } + }); + animator.setInterpolator(mFastOutSlowIn); + animator.setDuration(HINT_PHASE1_DURATION); + animator.start(); + mSwipeAnimator = animator; + } + + /** + * Phase 2: Move back. + */ + private void startUnlockHintAnimationPhase2(final Runnable onFinishedListener) { + startHintTranslationAnimations(0f /* target */, HINT_PHASE2_DURATION, mBounceInterpolator); + ValueAnimator animator = ValueAnimator.ofFloat(mTranslation, 0f); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mTranslation = (float) animation.getAnimatedValue(); + } + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mSwipeAnimator = null; + onFinishedListener.run(); + } + }); + animator.setInterpolator(mBounceInterpolator); + animator.setDuration(HINT_PHASE2_DURATION); + animator.start(); + mSwipeAnimator = animator; + } + + private void startHintTranslationAnimations(float target, long duration, + Interpolator interpolator) { + ArrayList<View> targetViews = mCallback.getTranslationViews(); + for (View targetView : targetViews) { + targetView.animate() + .setDuration(duration) + .setInterpolator(interpolator) + .translationX(target); + } + } + private void onUserActivity(long when) { mPowerManager.userActivity(when, false); } @@ -180,7 +266,6 @@ public class KeyguardPageSwipeHelper { View targetView = mTranslation > 0 ? mLeftIcon : mRightIcon; targetView.animate().cancel(); if (mSwipeAnimator != null) { - mSwipeAnimator.removeAllListeners(); mSwipeAnimator.cancel(); hideInactiveIcons(true); } @@ -218,11 +303,18 @@ public class KeyguardPageSwipeHelper { } }); animator.addListener(new AnimatorListenerAdapter() { + private boolean mCancelled; + + @Override + public void onAnimationCancel(Animator animation) { + mCancelled = true; + } + @Override public void onAnimationEnd(Animator animation) { mSwipeAnimator = null; mSwipingInProgress = false; - if (!snapBack && !mCallbackCalled) { + if (!snapBack && !mCallbackCalled && !mCancelled) { // ensure that the callback is called eventually mCallback.onAnimationToSideStarted(mTranslation < 0); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 7fc7cdb8221c..dbce718a6a23 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -23,7 +23,6 @@ import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Configuration; import android.util.AttributeSet; -import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; @@ -49,7 +48,8 @@ public class NotificationPanelView extends PanelView implements View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener, KeyguardPageSwipeHelper.Callback { - private static float EXPANSION_RUBBER_BAND_EXTRA_FACTOR = 0.6f; + private static final float EXPANSION_RUBBER_BAND_EXTRA_FACTOR = 0.6f; + private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f; private KeyguardPageSwipeHelper mPageSwiper; private StatusBarHeaderView mHeader; @@ -93,7 +93,9 @@ public class NotificationPanelView extends PanelView implements private FlingAnimationUtils mFlingAnimationUtils; private int mStatusBarMinHeight; private boolean mHeaderHidden; + private boolean mUnlockIconActive; private int mNotificationsHeaderCollideDistance; + private int mUnlockMoveDistance; private Interpolator mFastOutSlowInInterpolator; private Interpolator mFastOutLinearInterpolator; @@ -170,6 +172,7 @@ public class NotificationPanelView extends PanelView implements mQsPeekHeight = getResources().getDimensionPixelSize(R.dimen.qs_peek_height); mNotificationsHeaderCollideDistance = getResources().getDimensionPixelSize(R.dimen.header_notifications_collide_distance); + mUnlockMoveDistance = getResources().getDimensionPixelOffset(R.dimen.unlock_move_distance); mClockPositionAlgorithm.loadDimens(getResources()); } @@ -242,8 +245,8 @@ public class NotificationPanelView extends PanelView implements mClockAnimator.removeAllListeners(); mClockAnimator.cancel(); } - mClockAnimator = - ObjectAnimator.ofFloat(mKeyguardStatusView, View.Y, mClockAnimationTarget); + mClockAnimator = ObjectAnimator + .ofFloat(mKeyguardStatusView, View.Y, mClockAnimationTarget); mClockAnimator.setInterpolator(mFastOutSlowInInterpolator); mClockAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); mClockAnimator.addListener(new AnimatorListenerAdapter() { @@ -288,6 +291,7 @@ public class NotificationPanelView extends PanelView implements @Override public void resetViews() { mBlockTouches = false; + mUnlockIconActive = false; mPageSwiper.reset(); closeQs(); } @@ -422,7 +426,9 @@ public class NotificationPanelView extends PanelView implements } // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference // implementation. - if (!mIsExpanding && !mQsExpanded && mStatusBar.getBarState() != StatusBarState.SHADE) { + if ((!mIsExpanding || mHintAnimationRunning) + && !mQsExpanded + && mStatusBar.getBarState() != StatusBarState.SHADE) { mPageSwiper.onTouchEvent(event); if (mPageSwiper.isSwipingInProgress()) { return true; @@ -548,9 +554,7 @@ public class NotificationPanelView extends PanelView implements mHeader.setExpanded(expandVisually, mStackScrollerOverscrolling); mNotificationStackScroller.setEnabled(!mQsExpanded); mQsPanel.setVisibility(expandVisually ? View.VISIBLE : View.INVISIBLE); - mQsContainer.setVisibility(mKeyguardShowing && !mQsExpanded - ? View.INVISIBLE - : View.VISIBLE); + mQsContainer.setVisibility(mKeyguardShowing && !mQsExpanded ? View.INVISIBLE : View.VISIBLE); mScrollView.setTouchEnabled(mQsExpanded); } @@ -720,6 +724,30 @@ public class NotificationPanelView extends PanelView implements } mNotificationStackScroller.setStackHeight(expandedHeight); updateKeyguardHeaderVisibility(); + updateUnlockIcon(); + } + + private void updateUnlockIcon() { + if (mStatusBar.getBarState() == StatusBarState.KEYGUARD + || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) { + boolean active = getMaxPanelHeight() - getExpandedHeight() > mUnlockMoveDistance; + if (active && !mUnlockIconActive && mTracking) { + mKeyguardBottomArea.getLockIcon().animate() + .alpha(1f) + .scaleY(LOCK_ICON_ACTIVE_SCALE) + .scaleX(LOCK_ICON_ACTIVE_SCALE) + .setInterpolator(mFastOutLinearInterpolator) + .setDuration(150); + } else if (!active && mUnlockIconActive && mTracking) { + mKeyguardBottomArea.getLockIcon().animate() + .alpha(KeyguardPageSwipeHelper.SWIPE_RESTING_ALPHA_AMOUNT) + .scaleY(1f) + .scaleX(1f) + .setInterpolator(mFastOutLinearInterpolator) + .setDuration(150); + } + mUnlockIconActive = active; + } } /** @@ -728,8 +756,20 @@ public class NotificationPanelView extends PanelView implements private void updateKeyguardHeaderVisibility() { if (mStatusBar.getBarState() == StatusBarState.KEYGUARD || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) { - boolean hidden = mNotificationStackScroller.getNotificationsTopY() - <= mHeader.getBottom() + mNotificationsHeaderCollideDistance; + boolean hidden; + if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) { + + // When on Keyguard, we hide the header as soon as the top card of the notification + // stack scroller is close enough (collision distance) to the bottom of the header. + hidden = mNotificationStackScroller.getNotificationsTopY() + <= mHeader.getBottom() + mNotificationsHeaderCollideDistance; + } else { + + // In SHADE_LOCKED, the top card is already really close to the header. Hide it as + // soon as we start translating the stack. + hidden = mNotificationStackScroller.getTranslationY() < 0; + } + if (hidden && !mHeaderHidden) { mHeader.animate() .alpha(0f) @@ -796,12 +836,20 @@ public class NotificationPanelView extends PanelView implements protected void onTrackingStopped(boolean expand) { super.onTrackingStopped(expand); mOverExpansion = 0.0f; - mNotificationStackScroller.setOverScrolledPixels(0.0f, true /* onTop */, - true /* animate */); + mNotificationStackScroller.setOverScrolledPixels(0.0f, true /* onTop */, true /* animate */); if (expand && (mStatusBar.getBarState() == StatusBarState.KEYGUARD || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED)) { mPageSwiper.showAllIcons(true); } + if (!expand && (mStatusBar.getBarState() == StatusBarState.KEYGUARD + || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED)) { + mKeyguardBottomArea.getLockIcon().animate() + .alpha(0f) + .scaleX(2f) + .scaleY(2f) + .setInterpolator(mFastOutLinearInterpolator) + .setDuration(100); + } } @Override @@ -837,14 +885,61 @@ public class NotificationPanelView extends PanelView implements @Override public void onAnimationToSideStarted(boolean rightPage) { - if (rightPage) { - mKeyguardBottomArea.launchCamera(); - } else { + boolean start = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? rightPage : !rightPage; + if (start) { mKeyguardBottomArea.launchPhone(); + } else { + mKeyguardBottomArea.launchCamera(); } mBlockTouches = true; } + @Override + protected void onEdgeClicked(boolean right) { + if ((right && getRightIcon().getVisibility() != View.VISIBLE) + || (!right && getLeftIcon().getVisibility() != View.VISIBLE)) { + return; + } + mHintAnimationRunning = true; + mPageSwiper.startHintAnimation(right, new Runnable() { + @Override + public void run() { + mHintAnimationRunning = false; + mStatusBar.onHintFinished(); + } + }); + startHighlightIconAnimation(right ? getRightIcon() : getLeftIcon()); + boolean start = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? right : !right; + if (start) { + mStatusBar.onPhoneHintStarted(); + } else { + mStatusBar.onCameraHintStarted(); + } + } + + @Override + protected void startUnlockHintAnimation() { + super.startUnlockHintAnimation(); + startHighlightIconAnimation(getCenterIcon()); + } + + /** + * Starts the highlight (making it fully opaque) animation on an icon. + */ + private void startHighlightIconAnimation(final View icon) { + icon.animate() + .alpha(1.0f) + .setDuration(KeyguardPageSwipeHelper.HINT_PHASE1_DURATION) + .setInterpolator(mFastOutSlowInInterpolator) + .withEndAction(new Runnable() { + @Override + public void run() { + icon.animate().alpha(KeyguardPageSwipeHelper.SWIPE_RESTING_ALPHA_AMOUNT) + .setDuration(KeyguardPageSwipeHelper.HINT_PHASE1_DURATION) + .setInterpolator(mFastOutSlowInInterpolator); + } + }); + } @Override public float getPageWidth() { @@ -858,7 +953,9 @@ public class NotificationPanelView extends PanelView implements @Override public View getLeftIcon() { - return mKeyguardBottomArea.getPhoneImageView(); + return getLayoutDirection() == LAYOUT_DIRECTION_RTL + ? mKeyguardBottomArea.getCameraImageView() + : mKeyguardBottomArea.getPhoneImageView(); } @Override @@ -868,6 +965,8 @@ public class NotificationPanelView extends PanelView implements @Override public View getRightIcon() { - return mKeyguardBottomArea.getCameraImageView(); + return getLayoutDirection() == LAYOUT_DIRECTION_RTL + ? mKeyguardBottomArea.getPhoneImageView() + : mKeyguardBottomArea.getCameraImageView(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 4686933be6da..f43f3489b00a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -50,15 +50,17 @@ public abstract class PanelView extends FrameLayout { protected PhoneStatusBar mStatusBar; private float mPeekHeight; private float mHintDistance; + private int mEdgeTapAreaWidth; private float mInitialOffsetOnTouch; private float mExpandedFraction = 0; private float mExpandedHeight = 0; private boolean mJustPeeked; private boolean mClosing; - private boolean mTracking; + protected boolean mTracking; private boolean mTouchSlopExceeded; private int mTrackingPointer; protected int mTouchSlop; + protected boolean mHintAnimationRunning; private ValueAnimator mHeightAnimator; private ObjectAnimator mPeekAnimator; @@ -111,6 +113,7 @@ public abstract class PanelView extends FrameLayout { final ViewConfiguration configuration = ViewConfiguration.get(getContext()); mTouchSlop = configuration.getScaledTouchSlop(); mHintDistance = res.getDimension(R.dimen.hint_move_distance); + mEdgeTapAreaWidth = res.getDimensionPixelSize(R.dimen.edge_tap_area_width); } private void trackMovement(MotionEvent event) { @@ -147,7 +150,6 @@ public abstract class PanelView extends FrameLayout { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: - mInitialTouchY = y; mInitialTouchX = x; mInitialOffsetOnTouch = mExpandedHeight; @@ -156,10 +158,11 @@ public abstract class PanelView extends FrameLayout { initVelocityTracker(); } trackMovement(event); - if (!waitForTouchSlop || mHeightAnimator != null) { + if (!waitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning)) { if (mHeightAnimator != null) { mHeightAnimator.cancel(); // end any outstanding animations } + mTouchSlopExceeded = true; onTrackingStarted(); } if (mExpandedHeight == 0) { @@ -222,7 +225,7 @@ public abstract class PanelView extends FrameLayout { onTrackingStopped(expand); fling(vel, expand); } else { - boolean expands = onEmptySpaceClick(); + boolean expands = onEmptySpaceClick(mInitialTouchX); onTrackingStopped(expands); } if (mVelocityTracker != null) { @@ -279,8 +282,9 @@ public abstract class PanelView extends FrameLayout { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: - if (mHeightAnimator != null) { + if (mHeightAnimator != null && !mHintAnimationRunning) { mHeightAnimator.cancel(); // end any outstanding animations + mTouchSlopExceeded = true; return true; } mInitialTouchY = y; @@ -305,6 +309,9 @@ public abstract class PanelView extends FrameLayout { trackMovement(event); if (scrolledToBottom) { if (h < -mTouchSlop && h < -Math.abs(x - mInitialTouchX)) { + if (mHeightAnimator != null) { + mHeightAnimator.cancel(); + } mInitialOffsetOnTouch = mExpandedHeight; mInitialTouchY = y; mInitialTouchX = x; @@ -550,14 +557,22 @@ public abstract class PanelView extends FrameLayout { } cancelPeek(); onExpandingStarted(); - startUnlockHintAnimationPhase1(); + startUnlockHintAnimationPhase1(new Runnable() { + @Override + public void run() { + onExpandingFinished(); + mStatusBar.onHintFinished(); + mHintAnimationRunning = false; + } + }); mStatusBar.onUnlockHintStarted(); + mHintAnimationRunning = true; } /** * Phase 1: Move everything upwards. */ - private void startUnlockHintAnimationPhase1() { + private void startUnlockHintAnimationPhase1(final Runnable onAnimationFinished) { float target = Math.max(0, getMaxPanelHeight() - mHintDistance); ValueAnimator animator = createHeightAnimator(target); animator.setDuration(250); @@ -574,10 +589,9 @@ public abstract class PanelView extends FrameLayout { public void onAnimationEnd(Animator animation) { if (mCancelled) { mHeightAnimator = null; - onExpandingFinished(); - mStatusBar.onUnlockHintFinished(); + onAnimationFinished.run(); } else { - startUnlockHintAnimationPhase2(); + startUnlockHintAnimationPhase2(onAnimationFinished); } } }); @@ -588,7 +602,7 @@ public abstract class PanelView extends FrameLayout { /** * Phase 2: Bounce down. */ - private void startUnlockHintAnimationPhase2() { + private void startUnlockHintAnimationPhase2(final Runnable onAnimationFinished) { ValueAnimator animator = createHeightAnimator(getMaxPanelHeight()); animator.setDuration(450); animator.setInterpolator(mBounceInterpolator); @@ -596,8 +610,7 @@ public abstract class PanelView extends FrameLayout { @Override public void onAnimationEnd(Animator animation) { mHeightAnimator = null; - onExpandingFinished(); - mStatusBar.onUnlockHintFinished(); + onAnimationFinished.run(); } }); animator.start(); @@ -620,7 +633,22 @@ public abstract class PanelView extends FrameLayout { * * @return whether the panel will be expanded after the action performed by this method */ - private boolean onEmptySpaceClick() { + private boolean onEmptySpaceClick(float x) { + if (mHintAnimationRunning) { + return true; + } + if (x < mEdgeTapAreaWidth) { + onEdgeClicked(false /* right */); + return true; + } else if (x > getWidth() - mEdgeTapAreaWidth) { + onEdgeClicked(true /* right */); + return true; + } else { + return onMiddleClicked(); + } + } + + private boolean onMiddleClicked() { switch (mStatusBar.getBarState()) { case StatusBarState.KEYGUARD: startUnlockHintAnimation(); @@ -636,6 +664,8 @@ public abstract class PanelView extends FrameLayout { } } + protected abstract void onEdgeClicked(boolean right); + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s" + " tracking=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s" 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 b1216e69d0b4..082fe3a66e2f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -174,6 +174,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, /** The minimum delay in ms between reports of notification visibility. */ private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500; + /** + * The delay to reset the hint text when the hint animation is finished running. + */ + private static final int HINT_RESET_DELAY_MS = 1200; + // fling gesture tuning parameters, scaled to display density private float mSelfExpandVelocityPx; // classic value: 2000px/s private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up") @@ -491,6 +496,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } }; + private final Runnable mResetIndicationRunnable = new Runnable() { + @Override + public void run() { + mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase); + } + }; + @Override public void setZenMode(int mode) { super.setZenMode(mode); @@ -1047,16 +1059,22 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override public void addNotificationInternal(StatusBarNotification notification, Ranking ranking) { - if (DEBUG) Log.d(TAG, "addNotification score=" + notification.getScore()); - Entry shadeEntry = createNotificationViews(notification); - if (shadeEntry == null) { - return; - } + if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey()); if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(notification, ranking)) { // Forward the ranking so we can sort the new notification. mNotificationData.updateRanking(ranking); return; } + mIntercepted.remove(notification.getKey()); + displayNotification(notification, ranking); + } + + public void displayNotification(StatusBarNotification notification, + Ranking ranking) { + Entry shadeEntry = createNotificationViews(notification); + if (shadeEntry == null) { + return; + } if (mUseHeadsUp && shouldInterrupt(notification)) { if (DEBUG) Log.d(TAG, "launching notification in heads up mode"); Entry interruptionCandidate = new Entry(notification, null); @@ -1112,7 +1130,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override public void updateNotificationInternal(StatusBarNotification notification, Ranking ranking) { super.updateNotificationInternal(notification, ranking); - mIntercepted.update(notification); + // if we're here, then the notification is already in the shade + mIntercepted.remove(notification.getKey()); } @Override @@ -2960,11 +2979,24 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public void onUnlockHintStarted() { + mStatusBarView.removeCallbacks(mResetIndicationRunnable); mKeyguardIndicationTextView.switchIndication(R.string.keyguard_unlock); } - public void onUnlockHintFinished() { - mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase); + public void onHintFinished() { + + // Delay the reset a bit so the user can read the text. + mStatusBarView.postDelayed(mResetIndicationRunnable, HINT_RESET_DELAY_MS); + } + + public void onCameraHintStarted() { + mStatusBarView.removeCallbacks(mResetIndicationRunnable); + mKeyguardIndicationTextView.switchIndication(R.string.camera_hint); + } + + public void onPhoneHintStarted() { + mStatusBarView.removeCallbacks(mResetIndicationRunnable); + mKeyguardIndicationTextView.switchIndication(R.string.phone_hint); } public void onTrackingStopped(boolean expand) { diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 22ecd33c4e5a..b2b421714058 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -258,17 +258,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { */ private NetworkStateTracker mNetTrackers[]; - /** - * Holds references to all NetworkAgentInfos claiming to support the legacy - * NetworkType. We used to have a static set of of NetworkStateTrackers - * for each network type. This is the new model. - * Supports synchronous inspection of state. - * These are built out at startup such that an unsupported network - * doesn't get an ArrayList instance, making this a tristate: - * unsupported, supported but not active and active. - */ - private ArrayList<NetworkAgentInfo> mNetworkAgentInfoForType[]; - /* Handles captive portal check on a network */ private CaptivePortalTracker mCaptivePortalTracker; @@ -516,6 +505,118 @@ public class ConnectivityService extends IConnectivityManager.Stub { private static final int UID_UNUSED = -1; + /** + * Implements support for the legacy "one network per network type" model. + * + * We used to have a static array of NetworkStateTrackers, one for each + * network type, but that doesn't work any more now that we can have, + * for example, more that one wifi network. This class stores all the + * NetworkAgentInfo objects that support a given type, but the legacy + * API will only see the first one. + * + * It serves two main purposes: + * + * 1. Provide information about "the network for a given type" (since this + * API only supports one). + * 2. Send legacy connectivity change broadcasts. Broadcasts are sent if + * the first network for a given type changes, or if the default network + * changes. + */ + private class LegacyTypeTracker { + /** + * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS). + * Each list holds references to all NetworkAgentInfos that are used to + * satisfy requests for that network type. + * + * This array is built out at startup such that an unsupported network + * doesn't get an ArrayList instance, making this a tristate: + * unsupported, supported but not active and active. + * + * The actual lists are populated when we scan the network types that + * are supported on this device. + */ + private ArrayList<NetworkAgentInfo> mTypeLists[]; + + public LegacyTypeTracker() { + mTypeLists = (ArrayList<NetworkAgentInfo>[]) + new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1]; + } + + public void addSupportedType(int type) { + if (mTypeLists[type] != null) { + throw new IllegalStateException( + "legacy list for type " + type + "already initialized"); + } + mTypeLists[type] = new ArrayList<NetworkAgentInfo>(); + } + + private boolean isDefaultNetwork(NetworkAgentInfo nai) { + return mNetworkForRequestId.get(mDefaultRequest.requestId) == nai; + } + + public boolean isTypeSupported(int type) { + return isNetworkTypeValid(type) && mTypeLists[type] != null; + } + + public NetworkAgentInfo getNetworkForType(int type) { + if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) { + return mTypeLists[type].get(0); + } else { + return null; + } + } + + public void add(int type, NetworkAgentInfo nai) { + if (!isTypeSupported(type)) { + return; // Invalid network type. + } + if (VDBG) log("Adding agent " + nai + " for legacy network type " + type); + + ArrayList<NetworkAgentInfo> list = mTypeLists[type]; + if (list.contains(nai)) { + loge("Attempting to register duplicate agent for type " + type + ": " + nai); + return; + } + + if (list.isEmpty() || isDefaultNetwork(nai)) { + if (VDBG) log("Sending connected broadcast for type " + type + + "isDefaultNetwork=" + isDefaultNetwork(nai)); + sendLegacyNetworkBroadcast(nai, true, type); + } + list.add(nai); + } + + public void remove(NetworkAgentInfo nai) { + if (VDBG) log("Removing agent " + nai); + for (int type = 0; type < mTypeLists.length; type++) { + ArrayList<NetworkAgentInfo> list = mTypeLists[type]; + if (list == null || list.isEmpty()) { + continue; + } + + boolean wasFirstNetwork = false; + if (list.get(0).equals(nai)) { + // This network was the first in the list. Send broadcast. + wasFirstNetwork = true; + } + list.remove(nai); + + if (wasFirstNetwork || isDefaultNetwork(nai)) { + if (VDBG) log("Sending disconnected broadcast for type " + type + + "isDefaultNetwork=" + isDefaultNetwork(nai)); + sendLegacyNetworkBroadcast(nai, false, type); + } + + if (!list.isEmpty() && wasFirstNetwork) { + if (VDBG) log("Other network available for type " + type + + ", sending connected broadcast"); + sendLegacyNetworkBroadcast(list.get(0), false, type); + } + } + } + } + private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(); + public ConnectivityService(Context context, INetworkManagementService netd, INetworkStatsService statsService, INetworkPolicyManager policyManager) { // Currently, omitting a NetworkFactory will create one internally @@ -531,7 +632,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); - mDefaultRequest = new NetworkRequest(netCap, true, nextNetworkRequestId()); + mDefaultRequest = new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId()); NetworkRequestInfo nri = new NetworkRequestInfo(null, mDefaultRequest, new Binder(), NetworkRequestInfo.REQUEST); mNetworkRequests.put(mDefaultRequest, nri); @@ -587,9 +688,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { mNetTransitionWakeLockTimeout = mContext.getResources().getInteger( com.android.internal.R.integer.config_networkTransitionTimeout); - mNetworkAgentInfoForType = (ArrayList<NetworkAgentInfo>[]) - new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1]; - mNetTrackers = new NetworkStateTracker[ ConnectivityManager.MAX_NETWORK_TYPE+1]; mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1]; @@ -644,7 +742,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { "radio " + n.radio + " in network type " + n.type); continue; } - mNetworkAgentInfoForType[n.type] = new ArrayList<NetworkAgentInfo>(); + mLegacyTypeTracker.addSupportedType(n.type); mNetConfigs[n.type] = n; mNetworksDefined++; @@ -3125,11 +3223,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { } else { loge("Error connecting NetworkAgent"); NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo); - try { - mNetworkAgentInfoForType[nai.networkInfo.getType()].remove(nai); - } catch (NullPointerException e) {} if (nai != null) { mNetworkForNetId.remove(nai.network.netId); + mLegacyTypeTracker.remove(nai); } } } @@ -3160,10 +3256,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED); mNetworkAgentInfos.remove(msg.replyTo); updateClat(null, nai.linkProperties, nai); - try { - mNetworkAgentInfoForType[nai.networkInfo.getType()].remove(nai); - } catch (NullPointerException e) {} - + mLegacyTypeTracker.remove(nai); mNetworkForNetId.remove(nai.network.netId); // Since we've lost the network, go through all the requests that // it was satisfying and see if any other factory can satisfy them. @@ -3173,7 +3266,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId); if (VDBG) { log(" checking request " + request + ", currentNetwork = " + - currentNetwork != null ? currentNetwork.name() : "null"); + (currentNetwork != null ? currentNetwork.name() : "null")); } if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) { mNetworkForRequestId.remove(request.requestId); @@ -3223,6 +3316,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (bestNetwork != null) { if (VDBG) log("using " + bestNetwork.name()); bestNetwork.addRequest(nri.request); + int legacyType = nri.request.legacyType; + if (legacyType != TYPE_NONE) { + mLegacyTypeTracker.add(legacyType, bestNetwork); + } notifyNetworkCallback(bestNetwork, nri); score = bestNetwork.currentScore; } @@ -5300,7 +5397,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { @Override public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities, - Messenger messenger, int timeoutSec, IBinder binder, boolean legacy) { + Messenger messenger, int timeoutSec, IBinder binder, int legacyType) { if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) == false) { enforceConnectivityInternalPermission(); @@ -5312,7 +5409,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { throw new IllegalArgumentException("Bad timeout specified"); } NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities( - networkCapabilities), legacy, nextNetworkRequestId()); + networkCapabilities), legacyType, nextNetworkRequestId()); if (DBG) log("requestNetwork for " + networkRequest); NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder, NetworkRequestInfo.REQUEST); @@ -5338,7 +5435,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { enforceAccessPermission(); NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities( - networkCapabilities), false, nextNetworkRequestId()); + networkCapabilities), TYPE_NONE, nextNetworkRequestId()); if (DBG) log("listenForNetwork for " + networkRequest); NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder, NetworkRequestInfo.LISTEN); @@ -5420,11 +5517,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { private void handleRegisterNetworkAgent(NetworkAgentInfo na) { if (VDBG) log("Got NetworkAgent Messenger"); mNetworkAgentInfos.put(na.messenger, na); - try { - mNetworkAgentInfoForType[na.networkInfo.getType()].add(na); - } catch (NullPointerException e) { - loge("registered NetworkAgent for unsupported type: " + na); - } mNetworkForNetId.put(na.network.netId, na); na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger); NetworkInfo networkInfo = na.networkInfo; @@ -5681,6 +5773,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { } mNetworkForRequestId.put(nri.request.requestId, newNetwork); newNetwork.addRequest(nri.request); + int legacyType = nri.request.legacyType; + if (legacyType != TYPE_NONE) { + mLegacyTypeTracker.add(legacyType, newNetwork); + } keep = true; // TODO - this could get expensive if we have alot of requests for this // network. Think about if there is a way to reduce this. Push @@ -5694,6 +5790,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } else { setDefaultDnsSystemProperties(new ArrayList<InetAddress>()); } + mLegacyTypeTracker.add(newNetwork.networkInfo.getType(), newNetwork); } } } @@ -5828,13 +5925,53 @@ public class ConnectivityService extends IConnectivityManager.Stub { // } else if (nai.networkMonitor.isEvaluating()) { // notifyType = NetworkCallbacks.callCallbackForRequest(request, nai, notifyType); // } - if (nri.request.needsBroadcasts) { - // TODO -// sendNetworkBroadcast(nai, notifyType); - } callCallbackForRequest(nri, nai, notifyType); } + private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, boolean connected, int type) { + if (connected) { + NetworkInfo info = new NetworkInfo(nai.networkInfo); + info.setType(type); + sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay()); + } else { + NetworkInfo info = new NetworkInfo(nai.networkInfo); + info.setType(type); + Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); + intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); + intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType()); + if (info.isFailover()) { + intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); + nai.networkInfo.setFailover(false); + } + if (info.getReason() != null) { + intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason()); + } + if (info.getExtraInfo() != null) { + intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo()); + } + NetworkAgentInfo newDefaultAgent = null; + if (nai.networkRequests.get(mDefaultRequest.requestId) != null) { + newDefaultAgent = mNetworkForRequestId.get(mDefaultRequest.requestId); + if (newDefaultAgent != null) { + intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, + newDefaultAgent.networkInfo); + } else { + intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); + } + } + intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, + mDefaultInetConditionPublished); + final Intent immediateIntent = new Intent(intent); + immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE); + sendStickyBroadcast(immediateIntent); + sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay()); + if (newDefaultAgent != null) { + sendConnectedBroadcastDelayed(newDefaultAgent.networkInfo, + getConnectivityChangeDelay()); + } + } + } + protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) { if (VDBG) log("notifyType " + notifyType + " for " + networkAgent.name()); for (int i = 0; i < networkAgent.networkRequests.size(); i++) { @@ -5843,76 +5980,33 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (VDBG) log(" sending notification for " + nr); callCallbackForRequest(nri, networkAgent, notifyType); } - if (networkAgent.needsBroadcasts) { - if (notifyType == ConnectivityManager.CALLBACK_AVAILABLE) { - sendConnectedBroadcastDelayed(networkAgent.networkInfo, - getConnectivityChangeDelay()); - } else if (notifyType == ConnectivityManager.CALLBACK_LOST) { - NetworkInfo info = new NetworkInfo(networkAgent.networkInfo); - Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); - intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); - intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType()); - if (info.isFailover()) { - intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); - networkAgent.networkInfo.setFailover(false); - } - if (info.getReason() != null) { - intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason()); - } - if (info.getExtraInfo() != null) { - intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo()); - } - NetworkAgentInfo newDefaultAgent = null; - if (networkAgent.networkRequests.get(mDefaultRequest.requestId) != null) { - newDefaultAgent = mNetworkForRequestId.get(mDefaultRequest.requestId); - if (newDefaultAgent != null) { - intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, - newDefaultAgent.networkInfo); - } else { - intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); - } - } - intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, - mDefaultInetConditionPublished); - final Intent immediateIntent = new Intent(intent); - immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE); - sendStickyBroadcast(immediateIntent); - sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay()); - if (newDefaultAgent != null) { - sendConnectedBroadcastDelayed(newDefaultAgent.networkInfo, - getConnectivityChangeDelay()); - } - } - } } private LinkProperties getLinkPropertiesForTypeInternal(int networkType) { - ArrayList<NetworkAgentInfo> list = mNetworkAgentInfoForType[networkType]; - if (list == null) return null; - try { - return new LinkProperties(list.get(0).linkProperties); - } catch (IndexOutOfBoundsException e) { - return new LinkProperties(); - } + NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); + return (nai != null) ? + new LinkProperties(nai.linkProperties) : + new LinkProperties(); } private NetworkInfo getNetworkInfoForType(int networkType) { - ArrayList<NetworkAgentInfo> list = mNetworkAgentInfoForType[networkType]; - if (list == null) return null; - try { - return new NetworkInfo(list.get(0).networkInfo); - } catch (IndexOutOfBoundsException e) { - return new NetworkInfo(networkType, 0, "Unknown", ""); + if (!mLegacyTypeTracker.isTypeSupported(networkType)) + return null; + + NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); + if (nai != null) { + NetworkInfo result = new NetworkInfo(nai.networkInfo); + result.setType(networkType); + return result; + } else { + return new NetworkInfo(networkType, 0, "Unknown", ""); } } private NetworkCapabilities getNetworkCapabilitiesForType(int networkType) { - ArrayList<NetworkAgentInfo> list = mNetworkAgentInfoForType[networkType]; - if (list == null) return null; - try { - return new NetworkCapabilities(list.get(0).networkCapabilities); - } catch (IndexOutOfBoundsException e) { - return new NetworkCapabilities(); - } + NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); + return (nai != null) ? + new NetworkCapabilities(nai.networkCapabilities) : + new NetworkCapabilities(); } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index e9f968377f9f..b03c247e80dc 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -45,18 +45,6 @@ public class NetworkAgentInfo { public int currentScore; public final NetworkMonitor networkMonitor; - /** - * Indicates we need to send CONNECTIVITY_ACTION broadcasts for this network. - * For example the built-in default network request and any requsts coming from - * the deprecated startUsingNetworkFeature API will have this set. Networks - * responding to the new requestNetwork API will rely on point to point callbacks. - * - * Gets set if any legacy requests get affiliated with this network and - * stays set for life so we send disconnected bcasts to match the connected, - * even if the legacy request has moved on. - */ - public boolean needsBroadcasts = false; - // The list of NetworkRequests being satisfied by this Network. public final SparseArray<NetworkRequest> networkRequests = new SparseArray<NetworkRequest>(); public final ArrayList<NetworkRequest> networkLingered = new ArrayList<NetworkRequest>(); @@ -78,8 +66,6 @@ public class NetworkAgentInfo { } public void addRequest(NetworkRequest networkRequest) { - if (networkRequest.needsBroadcasts) needsBroadcasts = true; - networkRequests.put(networkRequest.requestId, networkRequest); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index cb78a45131c9..5f3744391b21 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1486,6 +1486,11 @@ public class NotificationManagerService extends SystemService { pkg, opPkg, id, tag, callingUid, callingPid, score, notification, user); NotificationRecord r = new NotificationRecord(n); + NotificationRecord old = mNotificationsByKey.get(n.getKey()); + if (old != null) { + // Retain ranking information from previous record + r.copyRankingInformation(old); + } if (!mSignalExtractors.isEmpty()) { for (NotificationSignalExtractor extractor : mSignalExtractors) { try { @@ -1514,15 +1519,6 @@ public class NotificationManagerService extends SystemService { } synchronized (mNotificationList) { - applyZenModeLocked(r); - - // Should this notification make noise, vibe, or use the LED? - final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD) && - !r.isIntercepted(); - if (DBG || r.isIntercepted()) Slog.v(TAG, - "pkg=" + pkg + " canInterrupt=" + canInterrupt + - " intercept=" + r.isIntercepted()); - NotificationRecord old = null; int index = indexOfNotificationLocked(n.getKey()); if (index < 0) { mNotificationList.add(r); @@ -1534,12 +1530,18 @@ public class NotificationManagerService extends SystemService { // Make sure we don't lose the foreground service state. notification.flags |= old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE; - // Retain ranking information from previous record - r.copyRankingInformation(old); mNotificationsByKey.remove(old.sbn.getKey()); } mNotificationsByKey.put(n.getKey(), r); + applyZenModeLocked(r); + // Should this notification make noise, vibe, or use the LED? + final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD) && + !r.isIntercepted(); + if (DBG || r.isIntercepted()) Slog.v(TAG, + "pkg=" + pkg + " canInterrupt=" + canInterrupt + + " intercept=" + r.isIntercepted()); + Collections.sort(mNotificationList, mRankingComparator); // Ensure if this is a foreground service that the proper additional |