From 2c5d3d5224b9c85845fef3ca97b285a76928c664 Mon Sep 17 00:00:00 2001 From: d34d Date: Thu, 24 Mar 2016 09:31:45 -0700 Subject: [PATCH] Add callbacks for window attachment Because we restrict the window type used for live lock screens to only one instance, we need to know when the current one is detached so that a new one can be added. Change-Id: I55cf79a8eeb962b53c01014ec97373403cd073b6 --- .../IKeyguardExternalViewCallbacks.aidl | 2 + .../externalviews/KeyguardExternalView.java | 55 ++++++++ .../KeyguardExternalViewProviderService.java | 131 +++++++++++++++++- 3 files changed, 186 insertions(+), 2 deletions(-) diff --git a/src/java/cyanogenmod/externalviews/IKeyguardExternalViewCallbacks.aidl b/src/java/cyanogenmod/externalviews/IKeyguardExternalViewCallbacks.aidl index e6331dd..3e0ed9f 100644 --- a/src/java/cyanogenmod/externalviews/IKeyguardExternalViewCallbacks.aidl +++ b/src/java/cyanogenmod/externalviews/IKeyguardExternalViewCallbacks.aidl @@ -24,4 +24,6 @@ interface IKeyguardExternalViewCallbacks { boolean requestDismissAndStartActivity(in Intent intent); oneway void collapseNotificationPanel(); oneway void setInteractivity(boolean isInteractive); + oneway void onAttachedToWindow(); + oneway void onDetachedFromWindow(); } diff --git a/src/java/cyanogenmod/externalviews/KeyguardExternalView.java b/src/java/cyanogenmod/externalviews/KeyguardExternalView.java index cf7b279..0c464d3 100644 --- a/src/java/cyanogenmod/externalviews/KeyguardExternalView.java +++ b/src/java/cyanogenmod/externalviews/KeyguardExternalView.java @@ -73,6 +73,8 @@ public class KeyguardExternalView extends View implements ViewTreeObserver.OnPre private KeyguardExternalViewCallbacks mCallback; + private OnWindowAttachmentChangedListener mWindowAttachmentListener; + public KeyguardExternalView(Context context, AttributeSet attrs) { this(context, attrs, null); } @@ -182,6 +184,20 @@ public class KeyguardExternalView extends View implements ViewTreeObserver.OnPre public void setInteractivity(boolean isInteractive) { mIsInteractive = isInteractive; } + + @Override + public void onAttachedToWindow() { + if (mWindowAttachmentListener != null) { + mWindowAttachmentListener.onAttachedToWindow(); + } + } + + @Override + public void onDetachedFromWindow() { + if (mWindowAttachmentListener != null) { + mWindowAttachmentListener.onDetachedFromWindow(); + } + } }; private void executeQueue() { @@ -230,6 +246,7 @@ public class KeyguardExternalView extends View implements ViewTreeObserver.OnPre @Override public void onDetachedFromWindow() { + super.onDetachedFromWindow(); performAction(new Runnable() { @Override public void run() { @@ -398,6 +415,34 @@ public class KeyguardExternalView extends View implements ViewTreeObserver.OnPre mCallback = null; } + /** + * Registers a {@link cyanogenmod.externalviews.KeyguardExternalView.OnWindowAttachmentChangedListener} + * for receiving events from the + * {@link cyanogenmod.externalviews.KeyguardExternalViewProviderService} + * @param listener The callback to register + * + * @hide + */ + public void registerOnWindowAttachmentChangedListener( + OnWindowAttachmentChangedListener listener) { + mWindowAttachmentListener = listener; + } + + /** + * Unregister a previously registered + * {@link cyanogenmod.externalviews.KeyguardExternalView.OnWindowAttachmentChangedListener} + * @param listener The callback to unregister + * + * @hide + */ + public void unregisterOnWindowAttachmentChangedListener( + OnWindowAttachmentChangedListener listener) { + if (mWindowAttachmentListener != listener) { + throw new IllegalArgumentException("Callback not registered"); + } + mWindowAttachmentListener = null; + } + /** * Callback interface for a {@link cyanogenmod.externalviews.KeyguardExternalViewProviderService} * to send events to the host's registered @@ -409,4 +454,14 @@ public class KeyguardExternalView extends View implements ViewTreeObserver.OnPre void collapseNotificationPanel(); void providerDied(); } + + /** + * Callback interface for changes to the containing window being attached and detached from the + * window manager. + * @hide + */ + public interface OnWindowAttachmentChangedListener { + void onAttachedToWindow(); + void onDetachedFromWindow(); + } } diff --git a/src/java/cyanogenmod/externalviews/KeyguardExternalViewProviderService.java b/src/java/cyanogenmod/externalviews/KeyguardExternalViewProviderService.java index 4f14408..540e58d 100644 --- a/src/java/cyanogenmod/externalviews/KeyguardExternalViewProviderService.java +++ b/src/java/cyanogenmod/externalviews/KeyguardExternalViewProviderService.java @@ -16,7 +16,6 @@ package cyanogenmod.externalviews; -import android.annotation.NonNull; import android.app.Service; import android.content.Context; import android.content.Intent; @@ -28,11 +27,18 @@ import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Log; +import android.view.ActionMode; import android.view.Gravity; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.SearchEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; import com.android.internal.policy.PhoneWindow; import java.util.concurrent.Callable; @@ -126,7 +132,8 @@ public abstract class KeyguardExternalViewProviderService extends Service { * This class provides an interface for the host and service to communicate to each other. */ protected abstract class Provider { - private final class ProviderImpl extends IKeyguardExternalViewProvider.Stub { + private final class ProviderImpl extends IKeyguardExternalViewProvider.Stub + implements Window.Callback { private final Window mWindow; private final WindowManager.LayoutParams mParams; @@ -138,6 +145,7 @@ public abstract class KeyguardExternalViewProviderService extends Service { public ProviderImpl(Provider provider) { mWindow = new PhoneWindow(KeyguardExternalViewProviderService.this); + mWindow.setCallback(this); ((ViewGroup) mWindow.getDecorView()).addView(onCreateView()); mParams = new WindowManager.LayoutParams(); @@ -316,6 +324,125 @@ public abstract class KeyguardExternalViewProviderService extends Service { mCallbacks.finishBroadcast(); } + // region Window callbacks + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + return false; + } + + @Override + public boolean dispatchKeyShortcutEvent(KeyEvent event) { + return false; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + return false; + } + + @Override + public boolean dispatchTrackballEvent(MotionEvent event) { + return false; + } + + @Override + public boolean dispatchGenericMotionEvent(MotionEvent event) { + return false; + } + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + return false; + } + + @Override + public View onCreatePanelView(int featureId) { + return null; + } + + @Override + public boolean onCreatePanelMenu(int featureId, Menu menu) { + return false; + } + + @Override + public boolean onPreparePanel(int featureId, View view, Menu menu) { + return false; + } + + @Override + public boolean onMenuOpened(int featureId, Menu menu) { + return false; + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + return false; + } + + @Override + public void onWindowAttributesChanged(WindowManager.LayoutParams attrs) {} + + @Override + public void onContentChanged() {} + + @Override + public void onWindowFocusChanged(boolean hasFocus) {} + + @Override + public void onAttachedToWindow() { + int N = mCallbacks.beginBroadcast(); + for(int i=0; i < N; i++) { + IKeyguardExternalViewCallbacks callback = mCallbacks.getBroadcastItem(0); + try { + callback.onAttachedToWindow(); + } catch(RemoteException e) { + } + } + mCallbacks.finishBroadcast(); + } + + @Override + public void onDetachedFromWindow() { + int N = mCallbacks.beginBroadcast(); + for(int i=0; i < N; i++) { + IKeyguardExternalViewCallbacks callback = mCallbacks.getBroadcastItem(0); + try { + callback.onDetachedFromWindow(); + } catch(RemoteException e) { + } + } + mCallbacks.finishBroadcast(); + } + + @Override + public void onPanelClosed(int featureId, Menu menu) {} + + @Override + public boolean onSearchRequested() { + return false; + } + + @Override + public boolean onSearchRequested(SearchEvent searchEvent) { + return false; + } + + @Override + public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) { + return null; + } + + @Override + public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) { + return null; + } + + @Override + public void onActionModeStarted(ActionMode mode) {} + + @Override + public void onActionModeFinished(ActionMode mode) {} } private final ProviderImpl mImpl = new ProviderImpl(this);