Merge "More QS Tile modes in the API"
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35802,10 +35802,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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33637,10 +33637,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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
* <li>When a tile should be up to date and listing will be indicated by
|
||||
* {@link #onStartListening()} and {@link #onStopListening()}.</li>
|
||||
*
|
||||
* <li>When the user removes a tile from Quick Settings {@link #onStopListening()}
|
||||
* <li>When the user removes a tile from Quick Settings {@link #onTileRemoved()}
|
||||
* will be called.</li>
|
||||
* </ul>
|
||||
* <p>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}.
|
||||
* <p>
|
||||
* 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}.
|
||||
* <p>
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<QSTile.State> {
|
||||
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<QSTile.State> {
|
||||
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<QSTile.State> {
|
||||
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<QSTile.State> {
|
||||
|
||||
@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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<TileServiceManager> SERVICE_SORT =
|
||||
new Comparator<TileServiceManager>() {
|
||||
@Override
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user