summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/net/ConnectivityManager.java20
-rw-r--r--core/java/android/net/IConnectivityManager.aidl2
-rw-r--r--core/java/android/net/NetworkInfo.java9
-rw-r--r--core/java/android/net/NetworkRequest.java22
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java5
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.pngbin0 -> 1054 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.pngbin0 -> 1050 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.pngbin0 -> 985 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.pngbin0 -> 1070 bytes
-rw-r--r--packages/SystemUI/res/layout/recents_nav_bar_scrim.xml23
-rw-r--r--packages/SystemUI/res/values/config.xml15
-rw-r--r--packages/SystemUI/res/values/dimens.xml13
-rw-r--r--packages/SystemUI/res/values/strings.xml6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardPageSwipeHelper.java98
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java133
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java48
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java288
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkAgentInfo.java14
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java24
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
new file mode 100644
index 000000000000..6cd1176c5fdc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.png
Binary files differ
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
new file mode 100644
index 000000000000..7237f0991028
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.png
Binary files differ
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
new file mode 100644
index 000000000000..8d56a1d41b4c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.png
Binary files differ
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
new file mode 100644
index 000000000000..aed300bd197c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.png
Binary files differ
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