Merge "Ensure we don't pass null values in to Theme.resolveAttributes" into lmp-mr1-dev
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index d0ba4b8..5d5d2b3 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -92,6 +92,11 @@
void enableIpv6(String iface);
/**
+ * Enables or enables IPv6 ND offload.
+ */
+ void setInterfaceIpv6NdOffload(String iface, boolean enable);
+
+ /**
* Retrieves the network routes currently configured on the specified
* interface
*/
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 7198e52..0a8a01f 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -429,7 +429,7 @@
}
final int childCount = getChildCount();
- final int midVertical = (top + bottom) / 2;
+ final int midVertical = (bottom - top) / 2;
final int dividerWidth = getDividerWidth();
int overflowWidth = 0;
int nonOverflowWidth = 0;
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 1ac4dd8..c68bfca 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -386,21 +386,21 @@
*/
@android.view.RemotableViewMethod
public void setImageResource(int resId) {
- if (mUri != null || mResource != resId) {
- final int oldWidth = mDrawableWidth;
- final int oldHeight = mDrawableHeight;
+ // The resource configuration may have changed, so we should always
+ // try to load the resource even if the resId hasn't changed.
+ final int oldWidth = mDrawableWidth;
+ final int oldHeight = mDrawableHeight;
- updateDrawable(null);
- mResource = resId;
- mUri = null;
+ updateDrawable(null);
+ mResource = resId;
+ mUri = null;
- resolveUri();
+ resolveUri();
- if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
- requestLayout();
- }
- invalidate();
+ if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
+ requestLayout();
}
+ invalidate();
}
/**
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index 4410f25..34b9dcb 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -40,7 +40,6 @@
import java.util.ArrayList;
public class ToolbarActionBar extends ActionBar {
- private Toolbar mToolbar;
private DecorToolbar mDecorToolbar;
private boolean mToolbarMenuPrepared;
private Window.Callback mWindowCallback;
@@ -66,7 +65,6 @@
};
public ToolbarActionBar(Toolbar toolbar, CharSequence title, Window.Callback windowCallback) {
- mToolbar = toolbar;
mDecorToolbar = new ToolbarWidgetWrapper(toolbar, false);
mWindowCallback = new ToolbarCallbackWrapper(windowCallback);
mDecorToolbar.setWindowCallback(mWindowCallback);
@@ -91,8 +89,8 @@
@Override
public void setCustomView(int resId) {
- final LayoutInflater inflater = LayoutInflater.from(mToolbar.getContext());
- setCustomView(inflater.inflate(resId, mToolbar, false));
+ final LayoutInflater inflater = LayoutInflater.from(mDecorToolbar.getContext());
+ setCustomView(inflater.inflate(resId, mDecorToolbar.getViewGroup(), false));
}
@Override
@@ -132,17 +130,17 @@
@Override
public void setElevation(float elevation) {
- mToolbar.setElevation(elevation);
+ mDecorToolbar.getViewGroup().setElevation(elevation);
}
@Override
public float getElevation() {
- return mToolbar.getElevation();
+ return mDecorToolbar.getViewGroup().getElevation();
}
@Override
public Context getThemedContext() {
- return mToolbar.getContext();
+ return mDecorToolbar.getContext();
}
@Override
@@ -152,12 +150,12 @@
@Override
public void setHomeAsUpIndicator(Drawable indicator) {
- mToolbar.setNavigationIcon(indicator);
+ mDecorToolbar.setNavigationIcon(indicator);
}
@Override
public void setHomeAsUpIndicator(int resId) {
- mToolbar.setNavigationIcon(resId);
+ mDecorToolbar.setNavigationIcon(resId);
}
@Override
@@ -280,7 +278,7 @@
@Override
public void setBackgroundDrawable(@Nullable Drawable d) {
- mToolbar.setBackground(d);
+ mDecorToolbar.setBackgroundDrawable(d);
}
@Override
@@ -290,12 +288,12 @@
@Override
public CharSequence getTitle() {
- return mToolbar.getTitle();
+ return mDecorToolbar.getTitle();
}
@Override
public CharSequence getSubtitle() {
- return mToolbar.getSubtitle();
+ return mDecorToolbar.getSubtitle();
}
@Override
@@ -389,44 +387,44 @@
@Override
public int getHeight() {
- return mToolbar.getHeight();
+ return mDecorToolbar.getHeight();
}
@Override
public void show() {
// TODO: Consider a better transition for this.
// Right now use no automatic transition so that the app can supply one if desired.
- mToolbar.setVisibility(View.VISIBLE);
+ mDecorToolbar.setVisibility(View.VISIBLE);
}
@Override
public void hide() {
// TODO: Consider a better transition for this.
// Right now use no automatic transition so that the app can supply one if desired.
- mToolbar.setVisibility(View.GONE);
+ mDecorToolbar.setVisibility(View.GONE);
}
@Override
public boolean isShowing() {
- return mToolbar.getVisibility() == View.VISIBLE;
+ return mDecorToolbar.getVisibility() == View.VISIBLE;
}
@Override
public boolean openOptionsMenu() {
- return mToolbar.showOverflowMenu();
+ return mDecorToolbar.showOverflowMenu();
}
@Override
public boolean invalidateOptionsMenu() {
- mToolbar.removeCallbacks(mMenuInvalidator);
- mToolbar.postOnAnimation(mMenuInvalidator);
+ mDecorToolbar.getViewGroup().removeCallbacks(mMenuInvalidator);
+ mDecorToolbar.getViewGroup().postOnAnimation(mMenuInvalidator);
return true;
}
@Override
public boolean collapseActionView() {
- if (mToolbar.hasExpandedActionView()) {
- mToolbar.collapseActionView();
+ if (mDecorToolbar.hasExpandedActionView()) {
+ mDecorToolbar.collapseActionView();
return true;
}
return false;
@@ -434,10 +432,10 @@
void populateOptionsMenu() {
if (!mMenuCallbackSet) {
- mToolbar.setMenuCallbacks(new ActionMenuPresenterCallback(), new MenuBuilderCallback());
+ mDecorToolbar.setMenuCallbacks(new ActionMenuPresenterCallback(), new MenuBuilderCallback());
mMenuCallbackSet = true;
}
- final Menu menu = mToolbar.getMenu();
+ final Menu menu = mDecorToolbar.getMenu();
final MenuBuilder mb = menu instanceof MenuBuilder ? (MenuBuilder) menu : null;
if (mb != null) {
mb.stopDispatchingItemsChanged();
@@ -518,7 +516,7 @@
}
mClosingActionMenu = true;
- mToolbar.dismissPopupMenus();
+ mDecorToolbar.dismissPopupMenus();
if (mWindowCallback != null) {
mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu);
}
@@ -536,7 +534,7 @@
@Override
public void onMenuModeChange(MenuBuilder menu) {
if (mWindowCallback != null) {
- if (mToolbar.isOverflowMenuShowing()) {
+ if (mDecorToolbar.isOverflowMenuShowing()) {
mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu);
} else if (mWindowCallback.onPreparePanel(Window.FEATURE_OPTIONS_PANEL,
null, menu)) {
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index b9a85e5..654d08b 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -1341,6 +1341,22 @@
updateHomeAccessibility(mUpGoerFive.isEnabled());
}
+ @Override
+ public void setMenuCallbacks(MenuPresenter.Callback presenterCallback,
+ MenuBuilder.Callback menuBuilderCallback) {
+ if (mActionMenuPresenter != null) {
+ mActionMenuPresenter.setCallback(presenterCallback);
+ }
+ if (mOptionsMenu != null) {
+ mOptionsMenu.setCallback(menuBuilderCallback);
+ }
+ }
+
+ @Override
+ public Menu getMenu() {
+ return mOptionsMenu;
+ }
+
static class SavedState extends BaseSavedState {
int expandedMenuItemId;
boolean isOverflowOpen;
diff --git a/core/java/com/android/internal/widget/DecorToolbar.java b/core/java/com/android/internal/widget/DecorToolbar.java
index f89f0b7..fb413b5 100644
--- a/core/java/com/android/internal/widget/DecorToolbar.java
+++ b/core/java/com/android/internal/widget/DecorToolbar.java
@@ -27,6 +27,8 @@
import android.view.Window;
import android.widget.AdapterView;
import android.widget.SpinnerAdapter;
+
+import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuPresenter;
/**
@@ -93,4 +95,11 @@
void setDefaultNavigationIcon(Drawable icon);
void saveHierarchyState(SparseArray<Parcelable> toolbarStates);
void restoreHierarchyState(SparseArray<Parcelable> toolbarStates);
+ void setBackgroundDrawable(Drawable d);
+ int getHeight();
+ void setVisibility(int visible);
+ int getVisibility();
+ void setMenuCallbacks(MenuPresenter.Callback presenterCallback,
+ MenuBuilder.Callback menuBuilderCallback);
+ Menu getMenu();
}
diff --git a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
index 324a6c9..054ca30 100644
--- a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
+++ b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
@@ -657,4 +657,36 @@
mToolbar.restoreHierarchyState(toolbarStates);
}
+ @Override
+ public void setBackgroundDrawable(Drawable d) {
+ //noinspection deprecation
+ mToolbar.setBackgroundDrawable(d);
+ }
+
+ @Override
+ public int getHeight() {
+ return mToolbar.getHeight();
+ }
+
+ @Override
+ public void setVisibility(int visible) {
+ mToolbar.setVisibility(visible);
+ }
+
+ @Override
+ public int getVisibility() {
+ return mToolbar.getVisibility();
+ }
+
+ @Override
+ public void setMenuCallbacks(MenuPresenter.Callback presenterCallback,
+ MenuBuilder.Callback menuBuilderCallback) {
+ mToolbar.setMenuCallbacks(presenterCallback, menuBuilderCallback);
+ }
+
+ @Override
+ public Menu getMenu() {
+ return mToolbar.getMenu();
+ }
+
}
diff --git a/docs/html/training/wearables/notifications/pages.jd b/docs/html/training/wearables/notifications/pages.jd
index d74c8ea..6315037 100644
--- a/docs/html/training/wearables/notifications/pages.jd
+++ b/docs/html/training/wearables/notifications/pages.jd
@@ -57,15 +57,14 @@
.setStyle(secondPageStyle)
.build();
-// Add second page with wearable extender and extend the main notification
-Notification twoPageNotification =
- new WearableExtender()
- .addPage(secondPageNotification)
- .extend(notificationBuilder)
- .build();
+// Extend the notification builder with the second page
+Notification notification = notificationBuilder
+ .extend(new NotificationCompat.WearableExtender()
+ .addPage(secondPageNotification))
+ .build();
// Issue the notification
notificationManager =
NotificationManagerCompat.from(this);
-notificationManager.notify(notificationId, twoPageNotification);
+notificationManager.notify(notificationId, notification);
</pre>
\ No newline at end of file
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index b8cdc4b..1ac80c1 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -166,6 +166,7 @@
@Override
public void release() {
+ mTvInputSessionImpl.scheduleOverlayViewCleanup();
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_RELEASE));
}
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 5d5ea02..0ca5810 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -25,10 +25,12 @@
import android.graphics.Rect;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.text.TextUtils;
@@ -44,10 +46,12 @@
import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.CaptioningManager;
+import android.widget.FrameLayout;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -241,16 +245,25 @@
* Base class for derived classes to implement to provide a TV input session.
*/
public abstract static class Session implements KeyEvent.Callback {
+ private static final int DETACH_OVERLAY_VIEW_TIMEOUT = 5000;
private final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState();
private final WindowManager mWindowManager;
final Handler mHandler;
private WindowManager.LayoutParams mWindowParams;
private Surface mSurface;
+ private Context mContext;
+ private FrameLayout mOverlayViewContainer;
private View mOverlayView;
+ private OverlayViewCleanUpTask mOverlayViewCleanUpTask;
private boolean mOverlayViewEnabled;
private IBinder mWindowToken;
private Rect mOverlayFrame;
+
+ private Object mLock = new Object();
+ // @GuardedBy("mLock")
private ITvInputSessionCallback mSessionCallback;
+ // @GuardedBy("mLock")
+ private List<Runnable> mPendingActions = new ArrayList<>();
/**
* Creates a new Session.
@@ -258,6 +271,7 @@
* @param context The context of the application
*/
public Session(Context context) {
+ mContext = context;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mHandler = new Handler(context.getMainLooper());
}
@@ -295,11 +309,12 @@
* @param eventArgs Optional arguments of the event.
* @hide
*/
+ @SystemApi
public void notifySessionEvent(final String eventType, final Bundle eventArgs) {
if (eventType == null) {
throw new IllegalArgumentException("eventType should not be null.");
}
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -318,7 +333,7 @@
* @param channelUri The URI of a channel.
*/
public void notifyChannelRetuned(final Uri channelUri) {
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -355,7 +370,7 @@
trackIdSet.clear();
// TODO: Validate the track list.
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -383,7 +398,7 @@
* @see #onSelectTrack
*/
public void notifyTrackSelected(final int type, final String trackId) {
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -404,7 +419,7 @@
* @see #notifyVideoUnavailable
*/
public void notifyVideoAvailable() {
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -436,7 +451,7 @@
|| reason > TvInputManager.VIDEO_UNAVAILABLE_REASON_END) {
throw new IllegalArgumentException("Unknown reason: " + reason);
}
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -475,7 +490,7 @@
* @see TvInputManager
*/
public void notifyContentAllowed() {
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -515,7 +530,7 @@
* @see TvInputManager
*/
public void notifyContentBlocked(final TvContentRating rating) {
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -544,7 +559,7 @@
if (left > right || top > bottm) {
throw new IllegalArgumentException("Invalid parameter");
}
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -846,12 +861,18 @@
* session.
*/
void release() {
- removeOverlayView(true);
onRelease();
if (mSurface != null) {
mSurface.release();
mSurface = null;
}
+ synchronized(mLock) {
+ mSessionCallback = null;
+ mPendingActions.clear();
+ }
+ // Removes the overlay view lastly so that any hanging on the main thread can be handled
+ // in {@link #scheduleOverlayViewCleanup}.
+ removeOverlayView(true);
}
/**
@@ -936,9 +957,8 @@
* @param frame A position of the overlay view.
*/
void createOverlayView(IBinder windowToken, Rect frame) {
- if (mOverlayView != null) {
- mWindowManager.removeView(mOverlayView);
- mOverlayView = null;
+ if (mOverlayViewContainer != null) {
+ removeOverlayView(false);
}
if (DEBUG) Log.d(TAG, "create overlay view(" + frame + ")");
mWindowToken = windowToken;
@@ -951,6 +971,15 @@
if (mOverlayView == null) {
return;
}
+ if (mOverlayViewCleanUpTask != null) {
+ mOverlayViewCleanUpTask.cancel(true);
+ mOverlayViewCleanUpTask = null;
+ }
+ // Creates a container view to check hanging on the overlay view detaching.
+ // Adding/removing the overlay view to/from the container make the view attach/detach
+ // logic run on the main thread.
+ mOverlayViewContainer = new FrameLayout(mContext);
+ mOverlayViewContainer.addView(mOverlayView);
// TvView's window type is TYPE_APPLICATION_MEDIA and we want to create
// an overlay window above the media window but below the application window.
int type = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
@@ -967,7 +996,7 @@
WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
mWindowParams.gravity = Gravity.START | Gravity.TOP;
mWindowParams.token = windowToken;
- mWindowManager.addView(mOverlayView, mWindowParams);
+ mWindowManager.addView(mOverlayViewContainer, mWindowParams);
}
/**
@@ -984,33 +1013,51 @@
onOverlayViewSizeChanged(frame.right - frame.left, frame.bottom - frame.top);
}
mOverlayFrame = frame;
- if (!mOverlayViewEnabled || mOverlayView == null) {
+ if (!mOverlayViewEnabled || mOverlayViewContainer == null) {
return;
}
mWindowParams.x = frame.left;
mWindowParams.y = frame.top;
mWindowParams.width = frame.right - frame.left;
mWindowParams.height = frame.bottom - frame.top;
- mWindowManager.updateViewLayout(mOverlayView, mWindowParams);
+ mWindowManager.updateViewLayout(mOverlayViewContainer, mWindowParams);
}
/**
* Removes the current overlay view.
*/
void removeOverlayView(boolean clearWindowToken) {
- if (DEBUG) Log.d(TAG, "removeOverlayView(" + mOverlayView + ")");
+ if (DEBUG) Log.d(TAG, "removeOverlayView(" + mOverlayViewContainer + ")");
if (clearWindowToken) {
mWindowToken = null;
mOverlayFrame = null;
}
- if (mOverlayView != null) {
- mWindowManager.removeView(mOverlayView);
+ if (mOverlayViewContainer != null) {
+ // Removes the overlay view from the view hierarchy in advance so that it can be
+ // cleaned up in the {@link OverlayViewCleanUpTask} if the remove process is
+ // hanging.
+ mOverlayViewContainer.removeView(mOverlayView);
mOverlayView = null;
+ mWindowManager.removeView(mOverlayViewContainer);
+ mOverlayViewContainer = null;
mWindowParams = null;
}
}
/**
+ * Schedules a task which checks whether the overlay view is detached and kills the process
+ * if it is not. Note that this method is expected to be called in a non-main thread.
+ */
+ void scheduleOverlayViewCleanup() {
+ View overlayViewParent = mOverlayViewContainer;
+ if (overlayViewParent != null) {
+ mOverlayViewCleanUpTask = new OverlayViewCleanUpTask();
+ mOverlayViewCleanUpTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
+ overlayViewParent);
+ }
+ }
+
+ /**
* Takes care of dispatching incoming input events and tells whether the event was handled.
*/
int dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
@@ -1039,37 +1086,70 @@
}
}
}
- if (mOverlayView == null || !mOverlayView.isAttachedToWindow()) {
+ if (mOverlayViewContainer == null || !mOverlayViewContainer.isAttachedToWindow()) {
return TvInputManager.Session.DISPATCH_NOT_HANDLED;
}
- if (!mOverlayView.hasWindowFocus()) {
- mOverlayView.getViewRootImpl().windowFocusChanged(true, true);
+ if (!mOverlayViewContainer.hasWindowFocus()) {
+ mOverlayViewContainer.getViewRootImpl().windowFocusChanged(true, true);
}
- if (isNavigationKey && mOverlayView.hasFocusable()) {
+ if (isNavigationKey && mOverlayViewContainer.hasFocusable()) {
// If mOverlayView has focusable views, navigation key events should be always
// handled. If not, it can make the application UI navigation messed up.
// For example, in the case that the left-most view is focused, a left key event
// will not be handled in ViewRootImpl. Then, the left key event will be handled in
// the application during the UI navigation of the TV input.
- mOverlayView.getViewRootImpl().dispatchInputEvent(event);
+ mOverlayViewContainer.getViewRootImpl().dispatchInputEvent(event);
return TvInputManager.Session.DISPATCH_HANDLED;
} else {
- mOverlayView.getViewRootImpl().dispatchInputEvent(event, receiver);
+ mOverlayViewContainer.getViewRootImpl().dispatchInputEvent(event, receiver);
return TvInputManager.Session.DISPATCH_IN_PROGRESS;
}
}
- private void setSessionCallback(ITvInputSessionCallback callback) {
- mSessionCallback = callback;
+ private void initialize(ITvInputSessionCallback callback) {
+ synchronized(mLock) {
+ mSessionCallback = callback;
+ for (Runnable runnable : mPendingActions) {
+ runnable.run();
+ }
+ mPendingActions.clear();
+ }
}
- private final void runOnMainThread(Runnable action) {
- if (mHandler.getLooper().isCurrentThread() && mSessionCallback != null) {
- action.run();
- } else {
- // Posts the runnable if this is not called from the main thread or the session
- // is not initialized yet.
- mHandler.post(action);
+ private final void executeOrPostRunnable(Runnable action) {
+ synchronized(mLock) {
+ if (mSessionCallback == null) {
+ // The session is not initialized yet.
+ mPendingActions.add(action);
+ } else {
+ if (mHandler.getLooper().isCurrentThread()) {
+ action.run();
+ } else {
+ // Posts the runnable if this is not called from the main thread
+ mHandler.post(action);
+ }
+ }
+ }
+ }
+
+ private final class OverlayViewCleanUpTask extends AsyncTask<View, Void, Void> {
+ @Override
+ protected Void doInBackground(View... views) {
+ View overlayViewParent = views[0];
+ try {
+ Thread.sleep(DETACH_OVERLAY_VIEW_TIMEOUT);
+ } catch (InterruptedException e) {
+ return null;
+ }
+ if (isCancelled()) {
+ return null;
+ }
+ if (overlayViewParent.isAttachedToWindow()) {
+ Log.e(TAG, "Time out on releasing overlay view. Killing "
+ + overlayViewParent.getContext().getPackageName());
+ Process.killProcess(Process.myPid());
+ }
+ return null;
}
}
}
@@ -1125,13 +1205,15 @@
mHardwareSession = session;
SomeArgs args = SomeArgs.obtain();
if (session != null) {
- args.arg1 = mProxySession;
- args.arg2 = mProxySessionCallback;
- args.arg3 = session.getToken();
+ args.arg1 = HardwareSession.this;
+ args.arg2 = mProxySession;
+ args.arg3 = mProxySessionCallback;
+ args.arg4 = session.getToken();
} else {
args.arg1 = null;
- args.arg2 = mProxySessionCallback;
- args.arg3 = null;
+ args.arg2 = null;
+ args.arg3 = mProxySessionCallback;
+ args.arg4 = null;
onRelease();
}
mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_SESSION_CREATED, args)
@@ -1269,7 +1351,6 @@
}
return;
}
- sessionImpl.setSessionCallback(cb);
ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this,
sessionImpl, channel);
if (sessionImpl instanceof HardwareSession) {
@@ -1300,9 +1381,10 @@
proxySession.mHardwareSessionCallback, mServiceHandler);
} else {
SomeArgs someArgs = SomeArgs.obtain();
- someArgs.arg1 = stub;
- someArgs.arg2 = cb;
- someArgs.arg3 = null;
+ someArgs.arg1 = sessionImpl;
+ someArgs.arg2 = stub;
+ someArgs.arg3 = cb;
+ someArgs.arg4 = null;
mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_SESSION_CREATED,
someArgs).sendToTarget();
}
@@ -1310,14 +1392,18 @@
}
case DO_NOTIFY_SESSION_CREATED: {
SomeArgs args = (SomeArgs) msg.obj;
- ITvInputSession stub = (ITvInputSession) args.arg1;
- ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg2;
- IBinder hardwareSessionToken = (IBinder) args.arg3;
+ Session sessionImpl = (Session) args.arg1;
+ ITvInputSession stub = (ITvInputSession) args.arg2;
+ ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg3;
+ IBinder hardwareSessionToken = (IBinder) args.arg4;
try {
cb.onSessionCreated(stub, hardwareSessionToken);
} catch (RemoteException e) {
Log.e(TAG, "error in onSessionCreated");
}
+ if (sessionImpl != null) {
+ sessionImpl.initialize(cb);
+ }
args.recycle();
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index a956151..6fd6758 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -48,6 +48,7 @@
pw.print(" getDisplayStateSupported(): "); pw.println(getDisplayStateSupported());
pw.print(" getPulseDuration(): "); pw.println(getPulseDuration());
pw.print(" getPulseInDuration(): "); pw.println(getPulseInDuration());
+ pw.print(" getPulseInDelay(): "); pw.println(getPulseInDelay());
pw.print(" getPulseInVisibleDuration(): "); pw.println(getPulseVisibleDuration());
pw.print(" getPulseOutDuration(): "); pw.println(getPulseOutDuration());
pw.print(" getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion());
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 0ddda8a..0cf2d05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -284,7 +284,7 @@
|| mInitialOffsetOnTouch == 0f)) {
mTouchSlopExceeded = true;
if (waitForTouchSlop && !mTracking) {
- if (!mJustPeeked) {
+ if (!mJustPeeked && mInitialOffsetOnTouch != 0f) {
mInitialOffsetOnTouch = mExpandedHeight;
mInitialTouchX = x;
mInitialTouchY = y;
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index d03a154..0f033d71 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -940,6 +940,17 @@
}
@Override
+ public void setInterfaceIpv6NdOffload(String iface, boolean enable) {
+ mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+ try {
+ mConnector.execute(
+ "interface", "ipv6ndoffload", iface, (enable ? "enable" : "disable"));
+ } catch (NativeDaemonConnectorException e) {
+ throw e.rethrowAsParcelableException();
+ }
+ }
+
+ @Override
public void addRoute(int netId, RouteInfo route) {
modifyRoute("add", "" + netId, route);
}
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index c7a2ce1..576556b 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -17,6 +17,7 @@
package com.android.server.connectivity;
import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_WIFI;
import java.net.Inet4Address;
@@ -53,7 +54,7 @@
// ConnectivityService Handler for LinkProperties updates.
private final Handler mHandler;
- // The network we're running on.
+ // The network we're running on, and its type.
private final NetworkAgentInfo mNetwork;
// Internal state variables.
@@ -90,8 +91,9 @@
final boolean connected = nai.networkInfo.isConnected();
final boolean hasIPv4Address =
(nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false;
- // Only support clat on mobile for now.
- return netType == TYPE_MOBILE && connected && !hasIPv4Address;
+ // Only support clat on mobile and wifi for now, because these are the only IPv6-only
+ // networks we can connect to.
+ return connected && !hasIPv4Address && (netType == TYPE_MOBILE || netType == TYPE_WIFI);
}
/**
@@ -211,23 +213,41 @@
return stacked;
}
+ private LinkAddress getLinkAddress(String iface) {
+ try {
+ InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
+ return config.getLinkAddress();
+ } catch(RemoteException|IllegalStateException e) {
+ Slog.e(TAG, "Error getting link properties: " + e);
+ return null;
+ }
+ }
+
+ private void maybeSetIpv6NdOffload(String iface, boolean on) {
+ if (mNetwork.networkInfo.getType() != TYPE_WIFI) {
+ return;
+ }
+ try {
+ Slog.d(TAG, (on ? "En" : "Dis") + "abling ND offload on " + iface);
+ mNMService.setInterfaceIpv6NdOffload(iface, on);
+ } catch(RemoteException|IllegalStateException e) {
+ Slog.w(TAG, "Changing IPv6 ND offload on " + iface + "failed: " + e);
+ }
+ }
+
@Override
public void interfaceAdded(String iface) {
// Called by the InterfaceObserver on its own thread, so can race with stop().
if (isStarted() && mIface.equals(iface)) {
Slog.i(TAG, "interface " + iface + " added, mIsRunning " + mIsRunning + "->true");
- LinkAddress clatAddress;
- try {
- InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
- clatAddress = config.getLinkAddress();
- } catch(RemoteException e) {
- Slog.e(TAG, "Error getting link properties: " + e);
- return;
- }
-
if (!mIsRunning) {
+ LinkAddress clatAddress = getLinkAddress(iface);
+ if (clatAddress == null) {
+ return;
+ }
mIsRunning = true;
+ maybeSetIpv6NdOffload(mBaseIface, false);
LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
lp.addStackedLink(makeLinkProperties(clatAddress));
Slog.i(TAG, "Adding stacked link " + mIface + " on top of " + mBaseIface);
@@ -255,6 +275,7 @@
} catch (RemoteException|IllegalStateException e) {
// Well, we tried.
}
+ maybeSetIpv6NdOffload(mBaseIface, true);
LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
lp.removeStackedLink(mIface);
clear();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 22ab1db..f9a85df 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3266,7 +3266,7 @@
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions");
}
- mSettings.writePackageRestrictionsLPr(userId);
+ scheduleWritePackageRestrictionsLocked(userId);
}
}
}
@@ -11566,7 +11566,7 @@
+ userId + ":");
filter.dump(new LogPrinter(Log.INFO, TAG), " ");
pir.addFilter(new PreferredActivity(filter, match, set, activity, always));
- mSettings.writePackageRestrictionsLPr(userId);
+ scheduleWritePackageRestrictionsLocked(userId);
}
}
@@ -11682,8 +11682,7 @@
int user = UserHandle.getCallingUserId();
if (clearPackagePreferredActivitiesLPw(packageName, user)) {
- mSettings.writePackageRestrictionsLPr(user);
- scheduleWriteSettingsLocked();
+ scheduleWritePackageRestrictionsLocked(user);
}
}
}
@@ -11733,8 +11732,7 @@
int user = UserHandle.getCallingUserId();
clearPackagePreferredActivitiesLPw(null, user);
mSettings.readDefaultPreferredAppsLPw(this, user);
- mSettings.writePackageRestrictionsLPr(user);
- scheduleWriteSettingsLocked();
+ scheduleWritePackageRestrictionsLocked(user);
}
}
@@ -11786,7 +11784,7 @@
filter.dump(new LogPrinter(Log.INFO, TAG), " ");
mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter(
new PersistentPreferredActivity(filter, activity));
- mSettings.writePackageRestrictionsLPr(userId);
+ scheduleWritePackageRestrictionsLocked(userId);
}
}
@@ -11828,7 +11826,7 @@
}
if (changed) {
- mSettings.writePackageRestrictionsLPr(userId);
+ scheduleWritePackageRestrictionsLocked(userId);
}
}
}
@@ -11849,7 +11847,7 @@
CrossProfileIntentFilter filter = new CrossProfileIntentFilter(intentFilter,
ownerPackage, UserHandle.getUserId(callingUid), targetUserId, flags);
mSettings.editCrossProfileIntentResolverLPw(sourceUserId).addFilter(filter);
- mSettings.writePackageRestrictionsLPr(sourceUserId);
+ scheduleWritePackageRestrictionsLocked(sourceUserId);
}
}
@@ -11873,7 +11871,7 @@
resolver.removeFilter(filter);
}
}
- mSettings.writePackageRestrictionsLPr(sourceUserId);
+ scheduleWritePackageRestrictionsLocked(sourceUserId);
}
}