ExtViews: Add callbacks for ExtView->Host communication

Adds an interface for the KeyguardExternalViewProviderService to
communicate with the host in SystemUI.  This includes handling
notifying the host when the provider service has died.

Change-Id: Icd185da289913b84da09707f1d8a2f4f4ff86bae
This commit is contained in:
d34d 2015-12-21 14:06:50 -08:00 committed by Clark Scheff
parent f2741cb04c
commit 8cc5a55f82
4 changed files with 194 additions and 1 deletions

View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2015 The CyanogenMod 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.
*/
package cyanogenmod.externalviews;
import android.content.Intent;
/** @hide */
interface IKeyguardExternalViewCallbacks {
oneway void dismiss();
oneway void dismissAndStartActivity(in Intent intent);
oneway void collapseNotificationPanel();
oneway void setInteractivity(boolean isInteractive);
}

View File

@ -18,6 +18,8 @@ package cyanogenmod.externalviews;
import android.graphics.Rect;
import cyanogenmod.externalviews.IKeyguardExternalViewCallbacks;
/** @hide */
interface IKeyguardExternalViewProvider
{
@ -35,6 +37,9 @@ interface IKeyguardExternalViewProvider
oneway void onScreenTurnedOn();
oneway void onScreenTurnedOff();
oneway void registerCallback(in IKeyguardExternalViewCallbacks callback);
oneway void unregisterCallback(in IKeyguardExternalViewCallbacks callback);
void alterWindow(in int x, in int y, in int width, in int height, in boolean visible,
in Rect clipRect);
}

View File

@ -39,7 +39,7 @@ import java.util.LinkedList;
* @hide
*/
public class KeyguardExternalView extends View implements Application.ActivityLifecycleCallbacks,
ViewTreeObserver.OnPreDrawListener {
ViewTreeObserver.OnPreDrawListener, IBinder.DeathRecipient {
public static final String EXTRA_PERMISSION_LIST = "permissions_list";
public static final String CATEGORY_KEYGUARD_GRANT_PERMISSION
@ -50,7 +50,11 @@ public class KeyguardExternalView extends View implements Application.ActivityLi
private Context mContext;
private final ExternalViewProperties mExternalViewProperties;
private volatile IKeyguardExternalViewProvider mExternalViewProvider;
private IBinder mService;
private final Point mDisplaySize;
private boolean mIsInteractive;
private KeyguardExternalViewCallbacks mCallback;
public KeyguardExternalView(Context context, AttributeSet attrs) {
this(context, attrs, null);
@ -87,6 +91,10 @@ public class KeyguardExternalView extends View implements Application.ActivityLi
mExternalViewProvider = IKeyguardExternalViewProvider.Stub.asInterface(
IExternalViewProviderFactory.Stub.asInterface(service).
createExternalView(null));
mExternalViewProvider.registerCallback(
KeyguardExternalView.this.mKeyguardExternalViewCallbacks);
mService = service;
mService.linkToDeath(KeyguardExternalView.this, 0);
executeQueue();
} catch (RemoteException e) {
e.printStackTrace();
@ -95,7 +103,43 @@ public class KeyguardExternalView extends View implements Application.ActivityLi
@Override
public void onServiceDisconnected(ComponentName name) {
try {
mExternalViewProvider.unregisterCallback(
KeyguardExternalView.this.mKeyguardExternalViewCallbacks);
} catch (RemoteException e) {
}
mExternalViewProvider = null;
mService.unlinkToDeath(KeyguardExternalView.this, 0);
mService = null;
}
};
private final IKeyguardExternalViewCallbacks mKeyguardExternalViewCallbacks =
new IKeyguardExternalViewCallbacks.Stub() {
@Override
public void dismiss() throws RemoteException {
if (mCallback != null) {
mCallback.dismiss();
}
}
@Override
public void dismissAndStartActivity(Intent intent) throws RemoteException {
if (mCallback != null) {
mCallback.dismissAndStartActivity(intent);
}
}
@Override
public void collapseNotificationPanel() throws RemoteException {
if (mCallback != null) {
mCallback.collapseNotificationPanel();
}
}
@Override
public void setInteractivity(boolean isInteractive) {
mIsInteractive = isInteractive;
}
};
@ -239,6 +283,13 @@ public class KeyguardExternalView extends View implements Application.ActivityLi
});
}
@Override
public void binderDied() {
if (mCallback != null) {
mCallback.providerDied();
}
}
/**
* Sets the component of the ExternalViewProviderService to be used for this ExternalView.
* If a provider is already connected to this view, it is first unbound before binding to the
@ -315,4 +366,26 @@ public class KeyguardExternalView extends View implements Application.ActivityLi
}
});
}
public boolean isInteractive() {
return mIsInteractive;
}
public void registerKeyguardExternalViewCallback(KeyguardExternalViewCallbacks callback) {
mCallback = callback;
}
public void unregisterKeyguardExternalViewCallback(KeyguardExternalViewCallbacks callback) {
if (mCallback != callback) {
throw new IllegalArgumentException("Callback not registered");
}
mCallback = null;
}
public interface KeyguardExternalViewCallbacks {
public void dismiss();
public void dismissAndStartActivity(Intent intent);
public void collapseNotificationPanel();
public void providerDied();
}
}

View File

@ -24,6 +24,7 @@ import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
import android.view.Gravity;
@ -56,6 +57,12 @@ public abstract class KeyguardExternalViewProviderService extends Service {
mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_NOT_STICKY;
}
@Override
public final IBinder onBind(Intent intent) {
return new IExternalViewProviderFactory.Stub() {
@ -88,6 +95,9 @@ public abstract class KeyguardExternalViewProviderService extends Service {
private boolean mShouldShow = true;
private boolean mAskedShow = false;
private final RemoteCallbackList<IKeyguardExternalViewCallbacks> mCallbacks =
new RemoteCallbackList<IKeyguardExternalViewCallbacks>();
public ProviderImpl(Provider provider) {
mWindow = new PhoneWindow(KeyguardExternalViewProviderService.this);
((ViewGroup) mWindow.getDecorView()).addView(onCreateView());
@ -243,11 +253,71 @@ public abstract class KeyguardExternalViewProviderService extends Service {
});
}
@Override
public void registerCallback(IKeyguardExternalViewCallbacks callback) {
mCallbacks.register(callback);
}
@Override
public void unregisterCallback(IKeyguardExternalViewCallbacks callback) {
mCallbacks.unregister(callback);
}
private void updateVisibility() {
if (DEBUG) Log.d(TAG, "shouldShow = " + mShouldShow + " askedShow = " + mAskedShow);
mWindow.getDecorView().setVisibility(mShouldShow && mAskedShow ?
View.VISIBLE : View.GONE);
}
// callbacks from provider to host
protected final void dismiss() {
int N = mCallbacks.beginBroadcast();
for(int i=0; i < N; i++) {
IKeyguardExternalViewCallbacks callback = mCallbacks.getBroadcastItem(0);
try {
callback.dismiss();
} catch(RemoteException e) {
}
}
mCallbacks.finishBroadcast();
}
protected final void dismissAndStartActivity(final Intent intent) {
int N = mCallbacks.beginBroadcast();
for(int i=0; i < N; i++) {
IKeyguardExternalViewCallbacks callback = mCallbacks.getBroadcastItem(0);
try {
callback.dismissAndStartActivity(intent);
} catch(RemoteException e) {
}
}
mCallbacks.finishBroadcast();
}
protected final void collapseNotificationPanel() {
int N = mCallbacks.beginBroadcast();
for(int i=0; i < N; i++) {
IKeyguardExternalViewCallbacks callback = mCallbacks.getBroadcastItem(0);
try {
callback.collapseNotificationPanel();
} catch(RemoteException e) {
}
}
mCallbacks.finishBroadcast();
}
protected final void setInteractivity(final boolean isInteractive) {
int N = mCallbacks.beginBroadcast();
for(int i=0; i < N; i++) {
IKeyguardExternalViewCallbacks callback = mCallbacks.getBroadcastItem(0);
try {
callback.setInteractivity(isInteractive);
} catch(RemoteException e) {
}
}
mCallbacks.finishBroadcast();
}
}
private final ProviderImpl mImpl = new ProviderImpl(this);
@ -269,12 +339,30 @@ public abstract class KeyguardExternalViewProviderService extends Service {
protected void onStop() {}
protected void onDetach() {}
// keyguard events
protected abstract void onKeyguardShowing(boolean screenOn);
protected abstract void onKeyguardDismissed();
protected abstract void onBouncerShowing(boolean showing);
protected abstract void onScreenTurnedOn();
protected abstract void onScreenTurnedOff();
// callbacks from provider to host
protected final void dismiss() {
mImpl.dismiss();
}
protected final void dismissAndStartActivity(final Intent intent) {
mImpl.dismissAndStartActivity(intent);
}
protected final void collapseNotificationPanel() {
mImpl.collapseNotificationPanel();
}
protected final void setInteractivity(final boolean isInteractive) {
mImpl.setInteractivity(isInteractive);
}
/*package*/ final int getWindowType() {
return WindowManager.LayoutParams.TYPE_KEYGUARD_PANEL;
}