diff options
15 files changed, 290 insertions, 113 deletions
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index d0ba4b81c973..5d5d2b384e04 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -92,6 +92,11 @@ interface INetworkManagementService 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 7198e522f3ae..0a8a01f2dfe9 100644 --- a/core/java/android/widget/ActionMenuView.java +++ b/core/java/android/widget/ActionMenuView.java @@ -429,7 +429,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo } 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 1ac4dd8e78de..c68bfcaa5bc2 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -386,21 +386,21 @@ public class ImageView extends View { */ @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 4410f2544624..34b9dcb9366f 100644 --- a/core/java/com/android/internal/app/ToolbarActionBar.java +++ b/core/java/com/android/internal/app/ToolbarActionBar.java @@ -40,7 +40,6 @@ import com.android.internal.widget.ToolbarWidgetWrapper; 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 class ToolbarActionBar extends ActionBar { }; 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 @@ public class ToolbarActionBar extends ActionBar { @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 @@ public class ToolbarActionBar extends ActionBar { @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 @@ public class ToolbarActionBar extends ActionBar { @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 @@ public class ToolbarActionBar extends ActionBar { @Override public void setBackgroundDrawable(@Nullable Drawable d) { - mToolbar.setBackground(d); + mDecorToolbar.setBackgroundDrawable(d); } @Override @@ -290,12 +288,12 @@ public class ToolbarActionBar extends ActionBar { @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 @@ public class ToolbarActionBar extends ActionBar { @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 @@ public class ToolbarActionBar extends ActionBar { 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 @@ public class ToolbarActionBar extends ActionBar { } mClosingActionMenu = true; - mToolbar.dismissPopupMenus(); + mDecorToolbar.dismissPopupMenus(); if (mWindowCallback != null) { mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu); } @@ -536,7 +534,7 @@ public class ToolbarActionBar extends ActionBar { @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 b9a85e59eb96..654d08b40763 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -1341,6 +1341,22 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { 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 f89f0b7d6ef7..fb413b573d2e 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.ViewGroup; 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 @@ public interface DecorToolbar { 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 324a6c998683..054ca30c71f4 100644 --- a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java +++ b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java @@ -657,4 +657,36 @@ public class ToolbarWidgetWrapper implements DecorToolbar { 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 d74c8ea40b8c..6315037e00f6 100644 --- a/docs/html/training/wearables/notifications/pages.jd +++ b/docs/html/training/wearables/notifications/pages.jd @@ -57,15 +57,14 @@ Notification secondPageNotification = .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 b8cdc4b4d60d..1ac80c14f458 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -166,6 +166,7 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand @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 5d5ea027f72a..0ca5810f1002 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -25,10 +25,12 @@ import android.graphics.PixelFormat; 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.Surface; 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 @@ public abstract class TvInputService extends Service { * 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 @@ public abstract class TvInputService extends Service { * @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 @@ public abstract class TvInputService extends Service { * @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 @@ public abstract class TvInputService extends Service { * @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 @@ public abstract class TvInputService extends Service { trackIdSet.clear(); // TODO: Validate the track list. - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -383,7 +398,7 @@ public abstract class TvInputService extends Service { * @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 @@ public abstract class TvInputService extends Service { * @see #notifyVideoUnavailable */ public void notifyVideoAvailable() { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -436,7 +451,7 @@ public abstract class TvInputService extends Service { || 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 @@ public abstract class TvInputService extends Service { * @see TvInputManager */ public void notifyContentAllowed() { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -515,7 +530,7 @@ public abstract class TvInputService extends Service { * @see TvInputManager */ public void notifyContentBlocked(final TvContentRating rating) { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -544,7 +559,7 @@ public abstract class TvInputService extends Service { 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 @@ public abstract class TvInputService extends Service { * 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 @@ public abstract class TvInputService extends Service { * @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 @@ public abstract class TvInputService extends Service { 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 @@ public abstract class TvInputService extends Service { 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 @@ public abstract class TvInputService extends Service { 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 @@ public abstract class TvInputService extends Service { } } } - 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 @@ public abstract class TvInputService extends Service { 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 @@ public abstract class TvInputService extends Service { } return; } - sessionImpl.setSessionCallback(cb); ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this, sessionImpl, channel); if (sessionImpl instanceof HardwareSession) { @@ -1300,9 +1381,10 @@ public abstract class TvInputService extends Service { 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 @@ public abstract class TvInputService extends Service { } 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 a956151f7b50..6fd67580226f 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 @@ public class DozeParameters { 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 0ddda8a3ab12..0cf2d054acad 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 @@ public abstract class PanelView extends FrameLayout { || 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 d03a15458b69..0f033d71bbc9 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -940,6 +940,17 @@ public class NetworkManagementService extends INetworkManagementService.Stub } @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 c7a2ce1d9a39..576556b30648 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 @@ public class Nat464Xlat extends BaseNetworkObserver { // 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 @@ public class Nat464Xlat extends BaseNetworkObserver { 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 @@ public class Nat464Xlat extends BaseNetworkObserver { 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 @@ public class Nat464Xlat extends BaseNetworkObserver { } 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 22ab1dbc01a0..f9a85dfd4929 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 @@ public class PackageManagerService extends IPackageManager.Stub { if (DEBUG_PREFERRED) { Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions"); } - mSettings.writePackageRestrictionsLPr(userId); + scheduleWritePackageRestrictionsLocked(userId); } } } @@ -11566,7 +11566,7 @@ public class PackageManagerService extends IPackageManager.Stub { + 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 @@ public class PackageManagerService extends IPackageManager.Stub { int user = UserHandle.getCallingUserId(); if (clearPackagePreferredActivitiesLPw(packageName, user)) { - mSettings.writePackageRestrictionsLPr(user); - scheduleWriteSettingsLocked(); + scheduleWritePackageRestrictionsLocked(user); } } } @@ -11733,8 +11732,7 @@ public class PackageManagerService extends IPackageManager.Stub { int user = UserHandle.getCallingUserId(); clearPackagePreferredActivitiesLPw(null, user); mSettings.readDefaultPreferredAppsLPw(this, user); - mSettings.writePackageRestrictionsLPr(user); - scheduleWriteSettingsLocked(); + scheduleWritePackageRestrictionsLocked(user); } } @@ -11786,7 +11784,7 @@ public class PackageManagerService extends IPackageManager.Stub { filter.dump(new LogPrinter(Log.INFO, TAG), " "); mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter( new PersistentPreferredActivity(filter, activity)); - mSettings.writePackageRestrictionsLPr(userId); + scheduleWritePackageRestrictionsLocked(userId); } } @@ -11828,7 +11826,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if (changed) { - mSettings.writePackageRestrictionsLPr(userId); + scheduleWritePackageRestrictionsLocked(userId); } } } @@ -11849,7 +11847,7 @@ public class PackageManagerService extends IPackageManager.Stub { 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 @@ public class PackageManagerService extends IPackageManager.Stub { resolver.removeFilter(filter); } } - mSettings.writePackageRestrictionsLPr(sourceUserId); + scheduleWritePackageRestrictionsLocked(sourceUserId); } } |