From fe8f6826ce3c2beeb1fce54c67978ce69f849407 Mon Sep 17 00:00:00 2001 From: Jason Monk Date: Mon, 21 Dec 2015 15:12:01 -0500 Subject: [PATCH] More QS Tile modes in the API Allow tiles to request when they are bound instead of doing it automatically for them when in the listening state. Only one of these modes is allowed for a given tile, meaning it can either push updates when it thinks they matter, or it can be told when to update. Change-Id: I165b39dddb836df90d253aeb5ebea48e62ea0dae --- api/current.txt | 5 +- api/system-current.txt | 5 +- api/test-current.txt | 5 +- .../service/quicksettings/IQSService.aidl | 1 + .../service/quicksettings/IQSTileService.aidl | 1 + .../android/service/quicksettings/Tile.java | 32 +++---- .../service/quicksettings/TileService.java | 90 ++++++++++++++++++- .../systemui/qs/external/CustomTile.java | 41 +++++---- .../qs/external/QSTileServiceWrapper.java | 11 +++ .../qs/external/TileLifecycleManager.java | 18 +++- .../qs/external/TileServiceManager.java | 40 ++++++++- .../systemui/qs/external/TileServices.java | 56 +++++++++++- .../external/TileLifecycleManagerTests.java | 74 +++++++++------ .../qs/external/TileServiceManagerTests.java | 8 ++ 14 files changed, 316 insertions(+), 71 deletions(-) diff --git a/api/current.txt b/api/current.txt index 30d302093272b..1a8185a3f8b21 100644 --- a/api/current.txt +++ b/api/current.txt @@ -33631,10 +33631,13 @@ package android.service.quicksettings { method public void onClick(); method public void onStartListening(); method public void onStopListening(); - method public void onTileAdded(); + method public int onTileAdded(); method public void onTileRemoved(); + method public static final void requestListeningState(android.content.Context, android.content.ComponentName); method public final void showDialog(android.app.Dialog); field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; + field public static final int TILE_MODE_ACTIVE = 2; // 0x2 + field public static final int TILE_MODE_PASSIVE = 1; // 0x1 } } diff --git a/api/system-current.txt b/api/system-current.txt index d7393b738d140..7e30350c5e700 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -35805,10 +35805,13 @@ package android.service.quicksettings { method public void onClick(); method public void onStartListening(); method public void onStopListening(); - method public void onTileAdded(); + method public int onTileAdded(); method public void onTileRemoved(); + method public static final void requestListeningState(android.content.Context, android.content.ComponentName); method public final void showDialog(android.app.Dialog); field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; + field public static final int TILE_MODE_ACTIVE = 2; // 0x2 + field public static final int TILE_MODE_PASSIVE = 1; // 0x1 } } diff --git a/api/test-current.txt b/api/test-current.txt index 9058fe7d8b888..db9cc984fb0ac 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -33634,10 +33634,13 @@ package android.service.quicksettings { method public void onClick(); method public void onStartListening(); method public void onStopListening(); - method public void onTileAdded(); + method public int onTileAdded(); method public void onTileRemoved(); + method public static final void requestListeningState(android.content.Context, android.content.ComponentName); method public final void showDialog(android.app.Dialog); field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; + field public static final int TILE_MODE_ACTIVE = 2; // 0x2 + field public static final int TILE_MODE_PASSIVE = 1; // 0x1 } } diff --git a/core/java/android/service/quicksettings/IQSService.aidl b/core/java/android/service/quicksettings/IQSService.aidl index 7e70501de39b6..75da82fc43c0c 100644 --- a/core/java/android/service/quicksettings/IQSService.aidl +++ b/core/java/android/service/quicksettings/IQSService.aidl @@ -24,4 +24,5 @@ import android.service.quicksettings.Tile; interface IQSService { void updateQsTile(in Tile tile); void onShowDialog(in Tile tile); + void setTileMode(in ComponentName component, int mode); } diff --git a/core/java/android/service/quicksettings/IQSTileService.aidl b/core/java/android/service/quicksettings/IQSTileService.aidl index 63a4c5e30df9c..4997f754d2a78 100644 --- a/core/java/android/service/quicksettings/IQSTileService.aidl +++ b/core/java/android/service/quicksettings/IQSTileService.aidl @@ -22,6 +22,7 @@ import android.service.quicksettings.IQSService; * @hide */ oneway interface IQSTileService { + void setQSService(in IQSService service); void setQSTile(in Tile tile); void onTileAdded(); void onTileRemoved(); diff --git a/core/java/android/service/quicksettings/Tile.java b/core/java/android/service/quicksettings/Tile.java index a53fc59d362cf..6104913642f8a 100644 --- a/core/java/android/service/quicksettings/Tile.java +++ b/core/java/android/service/quicksettings/Tile.java @@ -37,11 +37,12 @@ public final class Tile implements Parcelable { private static final String TAG = "Tile"; private ComponentName mComponentName; - private IQSService mService; private Icon mIcon; private CharSequence mLabel; private CharSequence mContentDescription; + private IQSService mService; + /** * @hide */ @@ -52,8 +53,14 @@ public final class Tile implements Parcelable { /** * @hide */ - public Tile(ComponentName componentName, IQSService service) { + public Tile(ComponentName componentName) { mComponentName = componentName; + } + + /** + * @hide + */ + public void setService(IQSService service) { mService = service; } @@ -64,6 +71,13 @@ public final class Tile implements Parcelable { return mComponentName; } + /** + * @hide + */ + public IQSService getQsService() { + return mService; + } + /** * Gets the current icon for the tile. */ @@ -137,21 +151,8 @@ public final class Tile implements Parcelable { } } - /** - * @hide - * Notifies the IQSService that this tile is showing a dialog. - */ - void onShowDialog() { - try { - mService.onShowDialog(this); - } catch (RemoteException e) { - Log.e(TAG, "Couldn't onShowDialog"); - } - } - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeStrongInterface(mService); if (mComponentName != null) { dest.writeByte((byte) 1); mComponentName.writeToParcel(dest, flags); @@ -169,7 +170,6 @@ public final class Tile implements Parcelable { } private void readFromParcel(Parcel source) { - mService = IQSService.Stub.asInterface(source.readStrongBinder()); if (source.readByte() != 0) { mComponentName = ComponentName.CREATOR.createFromParcel(source); } else { diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java index 55fe4cd901e10..1e134c7efaba6 100644 --- a/core/java/android/service/quicksettings/TileService.java +++ b/core/java/android/service/quicksettings/TileService.java @@ -15,8 +15,11 @@ */ package android.service.quicksettings; +import android.Manifest; import android.app.Dialog; import android.app.Service; +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.IBinder; @@ -42,7 +45,7 @@ import android.view.WindowManager; *
  • When a tile should be up to date and listing will be indicated by * {@link #onStartListening()} and {@link #onStopListening()}.
  • * - *
  • When the user removes a tile from Quick Settings {@link #onStopListening()} + *
  • When the user removes a tile from Quick Settings {@link #onTileRemoved()} * will be called.
  • * *

    TileService will be detected by tiles that match the {@value #ACTION_QS_TILE} @@ -71,11 +74,48 @@ public class TileService extends Service { */ public static final String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; + /** + * The tile mode hasn't been set yet. + * @hide + */ + public static final int TILE_MODE_UNSET = 0; + + /** + * Constant to be returned by {@link #onTileAdded}. + *

    + * Passive mode is the default mode for tiles. The System will tell the tile + * when it is most important to update by putting it in the listening state. + */ + public static final int TILE_MODE_PASSIVE = 1; + + /** + * Constant to be returned by {@link #onTileAdded}. + *

    + * Active mode is for tiles which already listen and keep track of their state in their + * own process. These tiles may request to send an update to the System while their process + * is alive using {@link #requestListeningState}. The System will only bind these tiles + * on its own when a click needs to occur. + */ + public static final int TILE_MODE_ACTIVE = 2; + + /** + * Used to notify SysUI that Listening has be requested. + * @hide + */ + public static final String ACTION_REQUEST_LISTENING + = "android.service.quicksettings.action.REQUEST_LISTENING"; + + /** + * @hide + */ + public static final String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT"; + private final H mHandler = new H(Looper.getMainLooper()); private boolean mListening = false; private Tile mTile; private IBinder mToken; + private IQSService mService; @Override public void onDestroy() { @@ -92,8 +132,12 @@ public class TileService extends Service { * Note that this is not guaranteed to be called between {@link #onCreate()} * and {@link #onStartListening()}, it will only be called when the tile is added * and not on subsequent binds. + * + * @see #TILE_MODE_PASSIVE + * @see #TILE_MODE_ACTIVE */ - public void onTileAdded() { + public int onTileAdded() { + return TILE_MODE_PASSIVE; } /** @@ -138,7 +182,10 @@ public class TileService extends Service { dialog.getWindow().getAttributes().token = mToken; dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_QS_DIALOG); dialog.show(); - getQsTile().onShowDialog(); + try { + mService.onShowDialog(mTile); + } catch (RemoteException e) { + } } /** @@ -155,6 +202,11 @@ public class TileService extends Service { @Override public IBinder onBind(Intent intent) { return new IQSTileService.Stub() { + @Override + public void setQSService(IQSService service) throws RemoteException { + mHandler.obtainMessage(H.MSG_SET_SERVICE, service).sendToTarget(); + } + @Override public void setQSTile(Tile tile) throws RemoteException { mHandler.obtainMessage(H.MSG_SET_TILE, tile).sendToTarget(); @@ -194,6 +246,7 @@ public class TileService extends Service { private static final int MSG_TILE_ADDED = 4; private static final int MSG_TILE_REMOVED = 5; private static final int MSG_TILE_CLICKED = 6; + private static final int MSG_SET_SERVICE = 7; public H(Looper looper) { super(looper); @@ -202,11 +255,28 @@ public class TileService extends Service { @Override public void handleMessage(Message msg) { switch (msg.what) { + case MSG_SET_SERVICE: + mService = (IQSService) msg.obj; + if (mTile != null) { + mTile.setService(mService); + } + break; case MSG_SET_TILE: mTile = (Tile) msg.obj; + if (mService != null && mTile != null) { + mTile.setService(mService); + } break; case MSG_TILE_ADDED: - TileService.this.onTileAdded(); + int mode = TileService.this.onTileAdded(); + if (mService == null) { + return; + } + try { + mService.setTileMode(new ComponentName(TileService.this, + TileService.this.getClass()), mode); + } catch (RemoteException e) { + } break; case MSG_TILE_REMOVED: TileService.this.onTileRemoved(); @@ -230,4 +300,16 @@ public class TileService extends Service { } } } + + /** + * Requests that a tile be put in the listening state so it can send an update. + * + * This method is only applicable to tiles that return {@link #TILE_MODE_ACTIVE} from + * {@link #onTileAdded()}, and will do nothing otherwise. + */ + public static final void requestListeningState(Context context, ComponentName component) { + Intent intent = new Intent(ACTION_REQUEST_LISTENING); + intent.putExtra(EXTRA_COMPONENT, component); + context.sendBroadcast(intent, Manifest.permission.BIND_QUICK_SETTINGS_TILE); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java index e622e1154396b..2e5a0b2775526 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java @@ -24,6 +24,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.service.quicksettings.IQSTileService; import android.service.quicksettings.Tile; +import android.service.quicksettings.TileService; import android.util.Log; import android.view.IWindowManager; import android.view.WindowManager; @@ -59,7 +60,7 @@ public class CustomTile extends QSTile { mComponent = ComponentName.unflattenFromString(action); mServiceManager = host.getTileServices().getTileWrapper(this); mService = mServiceManager.getTileService(); - mTile = new Tile(mComponent, host.getTileServices()); + mTile = new Tile(mComponent); try { PackageManager pm = mContext.getPackageManager(); ServiceInfo info = pm.getServiceInfo(mComponent, 0); @@ -68,6 +69,11 @@ public class CustomTile extends QSTile { mTile.setLabel(info.loadLabel(pm)); } catch (Exception e) { } + try { + mService.setQSTile(mTile); + } catch (RemoteException e) { + // Called through wrapper, won't happen here. + } } public ComponentName getComponent() { @@ -94,9 +100,10 @@ public class CustomTile extends QSTile { mListening = listening; try { if (listening) { - mServiceManager.setBindRequested(true); - mService.setQSTile(mTile); - mService.onStartListening(); + if (mServiceManager.getType() == TileService.TILE_MODE_PASSIVE) { + mServiceManager.setBindRequested(true); + mService.onStartListening(); + } } else { mService.onStopListening(); if (mIsTokenGranted && !mIsShowingDialog) { @@ -139,20 +146,20 @@ public class CustomTile extends QSTile { @Override protected void handleClick() { - if (mService != null) { - try { - if (DEBUG) Log.d(TAG, "Adding token"); - mWindowManager.addWindowToken(mToken, WindowManager.LayoutParams.TYPE_QS_DIALOG); - mIsTokenGranted = true; - } catch (RemoteException e) { + try { + if (DEBUG) Log.d(TAG, "Adding token"); + mWindowManager.addWindowToken(mToken, WindowManager.LayoutParams.TYPE_QS_DIALOG); + mIsTokenGranted = true; + } catch (RemoteException e) { + } + try { + if (mServiceManager.getType() == TileService.TILE_MODE_ACTIVE) { + mServiceManager.setBindRequested(true); + mService.onStartListening(); } - try { - mService.onClick(mToken); - } catch (RemoteException e) { - // Called through wrapper, won't happen here. - } - } else { - Log.e(TAG, "Click with no service " + getTileSpec()); + mService.onClick(mToken); + } catch (RemoteException e) { + // Called through wrapper, won't happen here. } MetricsLogger.action(mContext, getMetricsCategory(), mComponent.getPackageName()); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java index d656686b88a56..d41cdde37958b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java @@ -16,6 +16,7 @@ package com.android.systemui.qs.external; import android.os.IBinder; +import android.service.quicksettings.IQSService; import android.service.quicksettings.IQSTileService; import android.service.quicksettings.Tile; import android.util.Log; @@ -93,4 +94,14 @@ public class QSTileServiceWrapper { return false; } } + + public boolean setQSService(IQSService service) { + try { + mService.setQSService(service); + return true; + } catch (Exception e) { + Log.d(TAG, "Caught exception from TileService", e); + return false; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java index 500ee1941bd9d..41fce9f1fb987 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java @@ -29,6 +29,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; +import android.service.quicksettings.IQSService; import android.service.quicksettings.IQSTileService; import android.service.quicksettings.Tile; import android.support.annotation.VisibleForTesting; @@ -74,6 +75,7 @@ public class TileLifecycleManager extends BroadcastReceiver implements private boolean mBound; @VisibleForTesting boolean mReceiverRegistered; + private IQSService mService; public TileLifecycleManager(Handler handler, Context context, Intent intent, UserHandle user) { mContext = context; @@ -82,6 +84,10 @@ public class TileLifecycleManager extends BroadcastReceiver implements mUser = user; } + public ComponentName getComponent() { + return mIntent.getComponent(); + } + public boolean hasPendingClick() { synchronized (mQueuedMessages) { return mQueuedMessages.contains(MSG_ON_CLICK); @@ -108,6 +114,7 @@ public class TileLifecycleManager extends BroadcastReceiver implements if (DEBUG) Log.d(TAG, "Unbinding service " + mIntent); // Give it another chance next time it needs to be bound, out of kindness. mBindTryCount = 0; + mWrapper = null; mContext.unbindService(this); } } @@ -122,6 +129,8 @@ public class TileLifecycleManager extends BroadcastReceiver implements service.linkToDeath(this, 0); } catch (RemoteException e) { } + setQSService(mService); + setQSTile(mTile); handlePendingMessages(); } @@ -145,7 +154,6 @@ public class TileLifecycleManager extends BroadcastReceiver implements } if (mListening) { if (DEBUG) Log.d(TAG, "Handling pending onStartListening"); - setQSTile(mTile); onStartListening(); } if (queue.contains(MSG_ON_CLICK)) { @@ -272,6 +280,14 @@ public class TileLifecycleManager extends BroadcastReceiver implements } } + @Override + public void setQSService(IQSService service) { + mService = service; + if (mWrapper == null || !mWrapper.setQSService(service)) { + handleDeath(); + } + } + @Override public void onTileAdded() { if (DEBUG) Log.d(TAG, "onTileAdded"); diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java index ca589df5ed3fd..2f77a303c36cc 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.os.Handler; import android.os.UserHandle; import android.service.quicksettings.IQSTileService; +import android.service.quicksettings.TileService; import android.support.annotation.VisibleForTesting; import android.util.Log; @@ -38,6 +39,9 @@ public class TileServiceManager { private static final String TAG = "TileServiceManager"; + @VisibleForTesting + static final String PREFS_FILE = "CustomTileModes"; + private final TileServices mServices; private final TileLifecycleManager mStateManager; private final Handler mHandler; @@ -47,6 +51,7 @@ public class TileServiceManager { private int mPriority; private boolean mJustBound; private long mLastUpdate; + private int mType; TileServiceManager(TileServices tileServices, Handler handler, ComponentName component) { this(tileServices, handler, new TileLifecycleManager(handler, @@ -60,6 +65,25 @@ public class TileServiceManager { mServices = tileServices; mHandler = handler; mStateManager = tileLifecycleManager; + mType = tileServices.getContext().getSharedPreferences(PREFS_FILE, 0) + .getInt(tileLifecycleManager.getComponent().flattenToString(), + TileService.TILE_MODE_UNSET); + mStateManager.setQSService(tileServices); + if (mType == TileService.TILE_MODE_UNSET) { + bindService(); + mStateManager.onTileAdded(); + } + } + + public int getType() { + return mType; + } + + public void setType(int type) { + mServices.getContext().getSharedPreferences(PREFS_FILE, 0).edit() + .putInt(mStateManager.getComponent().flattenToString(), type).commit(); + mType = type; + mServices.recalculateBindAllowance(); } public IQSTileService getTileService() { @@ -70,17 +94,22 @@ public class TileServiceManager { if (mBindRequested == bindRequested) return; mBindRequested = bindRequested; if (mBindAllowed && mBindRequested && !mBound) { + mHandler.removeCallbacks(mUnbind); bindService(); } else { mServices.recalculateBindAllowance(); } if (mBound && !mBindRequested) { - // TODO: Schedule unbind. + mHandler.postDelayed(mUnbind, UNBIND_DELAY); } } public void setLastUpdate(long lastUpdate) { mLastUpdate = lastUpdate; + if (mBound && mType == TileService.TILE_MODE_ACTIVE) { + mStateManager.onStopListening(); + setBindRequested(false); + } mServices.recalculateBindAllowance(); } @@ -148,6 +177,15 @@ public class TileServiceManager { return mPriority; } + private final Runnable mUnbind = new Runnable() { + @Override + public void run() { + if (mBound && !mBindRequested) { + unbindService(); + } + } + }; + @VisibleForTesting final Runnable mJustBoundOver = new Runnable() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java index d110d978293ab..00f76990c1e83 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java @@ -15,15 +15,21 @@ */ package com.android.systemui.qs.external; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Binder; import android.os.Handler; import android.os.Looper; +import android.os.RemoteException; import android.service.quicksettings.IQSService; import android.service.quicksettings.Tile; +import android.service.quicksettings.TileService; import android.util.ArrayMap; +import android.util.Log; import com.android.systemui.statusbar.phone.QSTileHost; import java.util.ArrayList; @@ -48,6 +54,8 @@ public class TileServices extends IQSService.Stub { public TileServices(QSTileHost host, Looper looper) { mHost = host; mContext = mHost.getContext(); + mContext.registerReceiver(mRequestListeningReceiver, + new IntentFilter(TileService.ACTION_REQUEST_LISTENING)); mHandler = new Handler(looper); } @@ -121,12 +129,44 @@ public class TileServices extends IQSService.Stub { } } + private void requestListening(ComponentName component) { + synchronized (mServices) { + CustomTile customTile = getTileForComponent(component); + if (customTile == null) { + Log.d("TileServices", "Couldn't find tile for " + component); + return; + } + TileServiceManager service = mServices.get(customTile); + if (service.getType() != TileService.TILE_MODE_ACTIVE) { + return; + } + service.setBindRequested(true); + try { + service.getTileService().onStartListening(); + } catch (RemoteException e) { + } + } + } + + @Override + public void setTileMode(ComponentName component, int mode) { + verifyCaller(component.getPackageName()); + CustomTile customTile = getTileForComponent(component); + if (customTile != null) { + synchronized (mServices) { + mServices.get(customTile).setType(mode); + } + } + } + @Override public void updateQsTile(Tile tile) { verifyCaller(tile.getComponentName().getPackageName()); CustomTile customTile = getTileForComponent(tile.getComponentName()); if (customTile != null) { - mServices.get(customTile).setLastUpdate(System.currentTimeMillis()); + synchronized (mServices) { + mServices.get(customTile).setLastUpdate(System.currentTimeMillis()); + } customTile.updateState(tile); customTile.refreshState(); } @@ -143,9 +183,21 @@ public class TileServices extends IQSService.Stub { } private CustomTile getTileForComponent(ComponentName component) { - return mTiles.get(component); + synchronized (mServices) { + return mTiles.get(component); + } } + private final BroadcastReceiver mRequestListeningReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (TileService.ACTION_REQUEST_LISTENING.equals(intent.getAction())) { + requestListening( + (ComponentName) intent.getParcelableExtra(TileService.EXTRA_COMPONENT)); + } + } + }; + private static final Comparator SERVICE_SORT = new Comparator() { @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java index 059421136086c..6ebf488937f91 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java @@ -15,6 +15,7 @@ */ package com.android.systemui.qs.external; +import android.app.Service; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -23,9 +24,13 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Handler; import android.os.HandlerThread; +import android.os.IBinder; import android.os.Process; +import android.os.RemoteException; import android.os.UserHandle; -import android.service.quicksettings.TileService; +import android.service.quicksettings.IQSService; +import android.service.quicksettings.IQSTileService; +import android.service.quicksettings.Tile; import android.test.AndroidTestCase; import android.util.ArraySet; import android.util.Log; @@ -238,9 +243,49 @@ public class TileLifecycleManagerTests extends AndroidTestCase { } }; - public static class FakeTileService extends TileService { + public static class FakeTileService extends Service { public static final String ACTION_KILL = "com.android.systemui.test.KILL"; + @Override + public IBinder onBind(Intent intent) { + return new IQSTileService.Stub() { + + @Override + public void setQSService(IQSService service) { + + } + + @Override + public void setQSTile(Tile tile) throws RemoteException { + } + + @Override + public void onTileAdded() throws RemoteException { + sendCallback("onTileAdded"); + } + + @Override + public void onTileRemoved() throws RemoteException { + sendCallback("onTileRemoved"); + } + + @Override + public void onStartListening() throws RemoteException { + sendCallback("onStartListening"); + } + + @Override + public void onStopListening() throws RemoteException { + sendCallback("onStopListening"); + } + + @Override + public void onClick(IBinder iBinder) throws RemoteException { + sendCallback("onClick"); + } + }; + } + @Override public void onCreate() { super.onCreate(); @@ -255,31 +300,6 @@ public class TileLifecycleManagerTests extends AndroidTestCase { sendCallback("onDestroy"); } - @Override - public void onTileAdded() { - sendCallback("onTileAdded"); - } - - @Override - public void onTileRemoved() { - sendCallback("onTileRemoved"); - } - - @Override - public void onStartListening() { - sendCallback("onStartListening"); - } - - @Override - public void onStopListening() { - sendCallback("onStopListening"); - } - - @Override - public void onClick() { - sendCallback("onClick"); - } - private void sendCallback(String callback) { Log.d("TileLifecycleManager", "Relaying: " + callback); sendBroadcast(new Intent(TILE_UPDATE_BROADCAST) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java index c4f686e98cf5c..4586c2813f727 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java @@ -15,8 +15,10 @@ */ package com.android.systemui.qs.external; +import android.content.ComponentName; import android.os.Handler; import android.os.HandlerThread; +import android.service.quicksettings.TileService; import com.android.systemui.SysuiTestCase; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; @@ -36,7 +38,13 @@ public class TileServiceManagerTests extends SysuiTestCase { mThread.start(); mHandler = new Handler(mThread.getLooper()); mTileServices = Mockito.mock(TileServices.class); + Mockito.when(mTileServices.getContext()).thenReturn(mContext); mTileLifecycle = Mockito.mock(TileLifecycleManager.class); + ComponentName componentName = new ComponentName(mContext, + TileServiceManagerTests.class); + Mockito.when(mTileLifecycle.getComponent()).thenReturn(componentName); + mContext.getSharedPreferences(TileServiceManager.PREFS_FILE, 0).edit() + .putInt(componentName.flattenToString(), TileService.TILE_MODE_PASSIVE).commit(); mTileServiceManager = new TileServiceManager(mTileServices, mHandler, mTileLifecycle); }