CMSDK: Create Quick Settings Tile API.

Create a simple CustomTile object with builder which lets a 3rd party
  application publish a quick settings tile to the status bar panel.

  An example CustomTile build:

      CustomTile customTile = new CustomTile.Builder(mContext)
             .setLabel("custom label")
             .setContentDescription("custom description")
             .setOnClickIntent(pendingIntent)
             .setOnClickUri(Uri.parse("custom uri"))
             .setIcon(R.drawable.ic_launcher)
             .build();

  Which can be published to the status bar panel via CMStatusBarManager#publishTile.

  The CustomTile contains a click intent and click uri which can be
  sent or broadcasted when the CustomQSTile's handleClick is fired.

  This implementation closely mirrors that of NotificationManager#notify for
  notifications. In that each CMStatusBarManager#publishTile can have an appended
  id which can be kept by the 3rd party application to either update the tile with,
  or to remove the tile via CMStatusBarManager#removeTile.

Change-Id: I4b8a50e4e53ef2ececc9c7fc9c8d0ec6acfd0c0e
This commit is contained in:
Adnan Begovic
2015-04-23 23:16:27 -07:00
parent 42e54529ed
commit aa8614e39b
15 changed files with 2385 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
/**
* 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.app;
/**
* Constants to be used with {@link android.content.Context#getSystemService}
* to retrieve published system services
*/
public class CMContextConstants {
/**
* @hide
*/
private CMContextConstants() {
// Empty constructor
}
/**
* Use with {@link android.content.Context#getSystemService} to retrieve a
* {@link cyanogenmod.app.CMStatusBarManager} for informing the user of
* background events.
*
* @see android.content.Context#getSystemService
* @see cyanogenmod.app.CMStatusBarManager
*/
public static final String CM_STATUS_BAR_SERVICE = "cmstatusbar";
}

View File

@@ -0,0 +1,215 @@
/**
* 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.app;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
import cyanogenmod.app.ICMStatusBarManager;
/**
* The CMStatusBarManager allows you to publish and remove CustomTiles within the
* Quick Settings Panel.
*
* <p>
* Each of the publish methods takes an int id parameter and optionally a
* {@link String} tag parameter, which may be {@code null}. These parameters
* are used to form a pair (tag, id), or ({@code null}, id) if tag is
* unspecified. This pair identifies this custom tile from your app to the
* system, so that pair should be unique within your app. If you call one
* of the publish methods with a (tag, id) pair that is currently active and
* a new set of custom tile parameters, it will be updated. For example,
* if you pass a new custom tile icon, the old icon in the panel will
* be replaced with the new one. This is also the same tag and id you pass
* to the {@link #removeTile(int)} or {@link #removeTile(String, int)} method to clear
* this custom tile.
*
* <p>
* To get the instance of this class, utilize CMStatusBarManager#getInstance(Context context)
*
* @see cyanogenmod.app.CustomTile
*/
public class CMStatusBarManager {
private static final String TAG = "CMStatusBarManager";
private static boolean localLOGV = false;
private Context mContext;
private static ICMStatusBarManager sService;
private static CMStatusBarManager sCMStatusBarManagerInstance;
private CMStatusBarManager(Context context) {
Context appContext = context.getApplicationContext();
if (appContext != null) {
mContext = appContext;
} else {
mContext = context;
}
sService = getService();
}
/**
* Get or create an instance of the {@link cyanogenmod.app.CMStatusBarManager}
* @param context
* @return {@link cyanogenmod.app.CMStatusBarManager}
*/
public static CMStatusBarManager getInstance(Context context) {
if (sCMStatusBarManagerInstance == null) {
sCMStatusBarManagerInstance = new CMStatusBarManager(context);
}
return sCMStatusBarManagerInstance;
}
/**
* Post a custom tile to be shown in the status bar panel. If a custom tile with
* the same id has already been posted by your application and has not yet been removed, it
* will be replaced by the updated information.
*
* @param id An identifier for this customTile unique within your
* application.
* @param customTile A {@link CustomTile} object describing what to show the user.
* Must not be null.
*/
public void publishTile(int id, CustomTile customTile) {
publishTile(null, id, customTile);
}
/**
* Post a custom tile to be shown in the status bar panel. If a custom tile with
* the same tag and id has already been posted by your application and has not yet been
* removed, it will be replaced by the updated information.
*
* @param tag A string identifier for this custom tile. May be {@code null}.
* @param id An identifier for this custom tile. The pair (tag, id) must be unique
* within your application.
* @param customTile A {@link cyanogenmod.app.CustomTile} object describing what to
* show the user. Must not be null.
*/
public void publishTile(String tag, int id, CustomTile customTile) {
if (sService == null) {
Log.w(TAG, "not connected to CMStatusBarManagerService");
return;
}
int[] idOut = new int[1];
String pkg = mContext.getPackageName();
if (localLOGV) Log.v(TAG, pkg + ": create(" + id + ", " + customTile + ")");
try {
sService.createCustomTileWithTag(pkg, mContext.getOpPackageName(), tag, id,
customTile, idOut, UserHandle.myUserId());
if (id != idOut[0]) {
Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
}
} catch (RemoteException e) {
Slog.w("CMStatusBarManager", "warning: no cm status bar service");
}
}
/**
* Similar to {@link cyanogenmod.app.CMStatusBarManager#publishTile(int id, cyanogenmod.app.CustomTile)},
* however lets you specify a {@link android.os.UserHandle}
* @param tag A string identifier for this custom tile. May be {@code null}.
* @param id An identifier for this custom tile. The pair (tag, id) must be unique
* within your application.
* @param customTile A {@link cyanogenmod.app.CustomTile} object describing what to
* show the user. Must not be null.
* @param user A user handle to publish the tile as.
*/
public void publishTileAsUser(String tag, int id, CustomTile customTile, UserHandle user) {
if (sService == null) {
Log.w(TAG, "not connected to CMStatusBarManagerService");
return;
}
int[] idOut = new int[1];
String pkg = mContext.getPackageName();
if (localLOGV) Log.v(TAG, pkg + ": create(" + id + ", " + customTile + ")");
try {
sService.createCustomTileWithTag(pkg, mContext.getOpPackageName(), tag, id,
customTile, idOut, user.getIdentifier());
if (id != idOut[0]) {
Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
}
} catch (RemoteException e) {
Slog.w("CMStatusBarManager", "warning: no cm status bar service");
}
}
/**
* Remove a custom tile that's currently published to the StatusBarPanel.
* @param id The identifier for the custom tile to be removed.
*/
public void removeTile(int id) {
removeTile(null, id);
}
/**
* Remove a custom tile that's currently published to the StatusBarPanel.
* @param tag The string identifier for the custom tile to be removed.
* @param id The identifier for the custom tile to be removed.
*/
public void removeTile(String tag, int id) {
if (sService == null) {
Log.w(TAG, "not connected to CMStatusBarManagerService");
return;
}
String pkg = mContext.getPackageName();
if (localLOGV) Log.v(TAG, pkg + ": remove(" + id + ")");
try {
sService.removeCustomTileWithTag(pkg, tag, id, UserHandle.myUserId());
} catch (RemoteException e) {
Slog.w("CMStatusBarManager", "warning: no cm status bar service");
}
}
/**
* Similar to {@link cyanogenmod.app.CMStatusBarManager#removeTile(String tag, int id)} however lets you
* specific a {@link android.os.UserHandle}
* @param tag The string identifier for the custom tile to be removed.
* @param id The identifier for the custom tile to be removed.
* @param user The user handle to remove the tile from.
*/
public void removeTileAsUser(String tag, int id, UserHandle user) {
if (sService == null) {
Log.w(TAG, "not connected to CMStatusBarManagerService");
return;
}
String pkg = mContext.getPackageName();
if (localLOGV) Log.v(TAG, pkg + ": remove(" + id + ")");
try {
sService.removeCustomTileWithTag(pkg, tag, id, user.getIdentifier());
} catch (RemoteException e) {
}
}
/** @hide */
public ICMStatusBarManager getService() {
if (sService != null) {
return sService;
}
IBinder b = ServiceManager.getService(CMContextConstants.CM_STATUS_BAR_SERVICE);
sService = ICMStatusBarManager.Stub.asInterface(b);
return sService;
}
}

View File

@@ -0,0 +1,19 @@
/**
* 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.app;
parcelable CustomTile;

View File

@@ -0,0 +1,296 @@
/**
* 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.app;
import android.app.PendingIntent;
import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
/**
* A class that represents a quick settings tile
*
* <p>The {@link cyanogenmod.app.CustomTile.Builder} has been added to make it
* easier to construct CustomTiles.</p>
*/
public class CustomTile implements Parcelable {
/**
* An optional intent to execute when the custom tile entry is clicked. If
* this is an activity, it must include the
* {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires
* that you take care of task management
**/
public PendingIntent onClick;
/**
* An optional Uri to be parsed and broadcast on tile click
**/
public Uri onClickUri;
/**
* A label specific to the quick settings tile to be created
*/
public String label;
/**
* A content description for the custom tile state
*/
public String contentDescription;
/**
* An icon to represent the custom tile
*/
public int icon;
/**
* Unflatten the CustomTile from a parcel.
*/
public CustomTile(Parcel parcel)
{
if (parcel.readInt() != 0) {
this.onClick = PendingIntent.CREATOR.createFromParcel(parcel);
}
if (parcel.readInt() != 0) {
this.onClickUri = Uri.CREATOR.createFromParcel(parcel);
}
if (parcel.readInt() != 0) {
this.label = parcel.readString();
}
if (parcel.readInt() != 0) {
this.contentDescription = parcel.readString();
}
this.icon = parcel.readInt();
}
/**
* Constructs a CustomTile object with default values.
* You might want to consider using {@link cyanogenmod.app.CustomTile.Builder} instead.
*/
public CustomTile()
{
// Empty constructor
}
@Override
public CustomTile clone() {
CustomTile that = new CustomTile();
cloneInto(that);
return that;
}
@Override
public String toString() {
StringBuilder b = new StringBuilder();
String NEW_LINE = System.getProperty("line.separator");
if (onClickUri != null) {
b.append("onClickUri=" + onClickUri.toString() + NEW_LINE);
}
if (onClick != null) {
b.append("onClick=" + onClick.toString() + NEW_LINE);
}
if (!TextUtils.isEmpty(label)) {
b.append("label=" + label + NEW_LINE);
}
if (!TextUtils.isEmpty(contentDescription)) {
b.append("contentDescription=" + contentDescription + NEW_LINE);
}
b.append("icon=" + icon + NEW_LINE);
return b.toString();
}
/**
* Copy all of this into that
* @hide
*/
public void cloneInto(CustomTile that) {
that.onClick = this.onClick;
that.onClickUri = this.onClickUri;
that.label = this.label;
that.contentDescription = this.contentDescription;
that.icon = this.icon;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
if (onClick != null) {
out.writeInt(1);
onClick.writeToParcel(out, 0);
} else {
out.writeInt(0);
}
if (onClickUri != null) {
out.writeInt(1);
onClickUri.writeToParcel(out, 0);
} else {
out.writeInt(0);
}
if (label != null) {
out.writeInt(1);
out.writeString(label);
} else {
out.writeInt(0);
}
if (contentDescription != null) {
out.writeInt(1);
out.writeString(contentDescription);
} else {
out.writeInt(0);
}
out.writeInt(icon);
}
/**
* Parcelable.Creator that instantiates CustomTile objects
*/
public static final Creator<CustomTile> CREATOR =
new Creator<CustomTile>() {
public CustomTile createFromParcel(Parcel in) {
return new CustomTile(in);
}
@Override
public CustomTile[] newArray(int size) {
return new CustomTile[size];
}
};
/**
* Builder class for {@link cyanogenmod.app.CustomTile} objects.
*
* Provides a convenient way to set the various fields of a {@link cyanogenmod.app.CustomTile}
*
* <p>Example:
*
* <pre class="prettyprint">
* CustomTile customTile = new CustomTile.Builder(mContext)
* .setLabel("custom label")
* .setContentDescription("custom description")
* .setOnClickIntent(pendingIntent)
* .setOnClickUri(Uri.parse("custom uri"))
* .setIcon(R.drawable.ic_launcher)
* .build();
* </pre>
*/
public static class Builder {
private PendingIntent mOnClick;
private Uri mOnClickUri;
private String mLabel;
private String mContentDescription;
private int mIcon;
private Context mContext;
/**
* Constructs a new Builder with the defaults:
*/
public Builder(Context context) {
mContext = context;
}
/**
* Set the label for the custom tile
* @param label a string to be used for the custom tile label
* @return {@link cyanogenmod.app.CustomTile.Builder}
*/
public Builder setLabel(String label) {
mLabel = label;
return this;
}
/**
* Set the label for the custom tile
* @param id a string resource id to be used for the custom tile label
* @return {@link cyanogenmod.app.CustomTile.Builder}
*/
public Builder setLabel(int id) {
mLabel = mContext.getString(id);
return this;
}
/**
* Set the content description for the custom tile
* @param contentDescription a string to explain content
* @return {@link cyanogenmod.app.CustomTile.Builder}
*/
public Builder setContentDescription(String contentDescription) {
mContentDescription = contentDescription;
return this;
}
/**
* Set the content description for the custom tile
* @param id a string resource id to explain content
* @return {@link cyanogenmod.app.CustomTile.Builder}
*/
public Builder setContentDescription(int id) {
mContentDescription = mContext.getString(id);
return this;
}
/**
* Set a {@link android.app.PendingIntent} to be fired on custom tile click
* @param intent
* @return {@link cyanogenmod.app.CustomTile.Builder}
*/
public Builder setOnClickIntent(PendingIntent intent) {
mOnClick = intent;
return this;
}
/**
* Set a {@link android.net.Uri} to be broadcasted in an intent on custom tile click
* @param uri
* @return {@link cyanogenmod.app.CustomTile.Builder}
*/
public Builder setOnClickUri(Uri uri) {
mOnClickUri = uri;
return this;
}
/**
* Set an icon for the custom tile to be presented to the user
* @param drawableId
* @return {@link cyanogenmod.app.CustomTile.Builder}
*/
public Builder setIcon(int drawableId) {
mIcon = drawableId;
return this;
}
/**
* Create a {@link cyanogenmod.app.CustomTile} object
* @return {@link cyanogenmod.app.CustomTile}
*/
public CustomTile build() {
CustomTile tile = new CustomTile();
tile.onClick = mOnClick;
tile.onClickUri = mOnClickUri;
tile.label = mLabel;
tile.contentDescription = mContentDescription;
tile.icon = mIcon;
return tile;
}
}
}

View File

@@ -0,0 +1,194 @@
/**
* 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.app;
import android.annotation.SdkConstant;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import cyanogenmod.app.ICustomTileListener;
import cyanogenmod.app.ICMStatusBarManager;
import org.cyanogenmod.internal.statusbar.IStatusBarCustomTileHolder;
/**
* A service that receives calls from the system when new custom tiles are
* posted or removed.
* <p>To extend this class, you must declare the service in your manifest file with
* the TODO: add permission
* and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
* <pre>
* &lt;service android:name=".CustomTileListener"
* android:label="&#64;string/service_name"
* android:permission="TODO: Add me">
* &lt;intent-filter>
* &lt;action android:name="cyanogenmod.app.CustomTileListenerService" />
* &lt;/intent-filter>
* &lt;/service></pre>
*/
public class CustomTileListenerService extends Service {
private final String TAG = CustomTileListenerService.class.getSimpleName()
+ "[" + getClass().getSimpleName() + "]";
/**
* The {@link android.content.Intent} that must be declared as handled by the service.
*/
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
public static final String SERVICE_INTERFACE
= "cyanogenmod.app.CustomTileListenerService";
private ICustomTileListenerWrapper mWrapper = null;
private ICMStatusBarManager mStatusBarService;
/** Only valid after a successful call to (@link registerAsService}. */
private int mCurrentUser;
@Override
public IBinder onBind(Intent intent) {
if (mWrapper == null) {
mWrapper = new ICustomTileListenerWrapper();
}
return mWrapper;
}
private final ICMStatusBarManager getStatusBarInterface() {
if (mStatusBarService == null) {
mStatusBarService = ICMStatusBarManager.Stub.asInterface(
ServiceManager.getService(CMContextConstants.CM_STATUS_BAR_SERVICE));
}
return mStatusBarService;
}
/**
* Directly register this service with the StatusBar Manager.
*
* <p>Only system services may use this call. It will fail for non-system callers.
* Apps should ask the user to add their listener in Settings.
*
* @param context Context required for accessing resources. Since this service isn't
* launched as a real Service when using this method, a context has to be passed in.
* @param componentName the component that will consume the custom tile information
* @param currentUser the user to use as the stream filter
* @hide
*/
public void registerAsSystemService(Context context, ComponentName componentName,
int currentUser) throws RemoteException {
if (mWrapper == null) {
mWrapper = new ICustomTileListenerWrapper();
}
ICMStatusBarManager statusBarInterface = getStatusBarInterface();
statusBarInterface.registerListener(mWrapper, componentName, currentUser);
mCurrentUser = currentUser;
}
/**
* Directly unregister this service from the StatusBar Manager.
*
* <P>This method will fail for listeners that were not registered
* with (@link registerAsService).
* @hide
*/
public void unregisterAsSystemService() throws RemoteException {
if (mWrapper != null) {
ICMStatusBarManager statusBarInterface = getStatusBarInterface();
statusBarInterface.unregisterListener(mWrapper, mCurrentUser);
}
}
private class ICustomTileListenerWrapper extends ICustomTileListener.Stub {
@Override
public void onListenerConnected() {
synchronized (mWrapper) {
try {
CustomTileListenerService.this.onListenerConnected();
} catch (Throwable t) {
Log.w(TAG, "Error running onListenerConnected", t);
}
}
}
@Override
public void onCustomTilePosted(IStatusBarCustomTileHolder sbcHolder) {
StatusBarPanelCustomTile sbc;
try {
sbc = sbcHolder.get();
} catch (RemoteException e) {
Log.w(TAG, "onCustomTilePosted: Error receiving StatusBarPanelCustomTile", e);
return;
}
synchronized (mWrapper) {
try {
CustomTileListenerService.this.onCustomTilePosted(sbc);
} catch (Throwable t) {
Log.w(TAG, "Error running onCustomTilePosted", t);
}
}
}
@Override
public void onCustomTileRemoved(IStatusBarCustomTileHolder sbcHolder) {
StatusBarPanelCustomTile sbc;
try {
sbc = sbcHolder.get();
} catch (RemoteException e) {
Log.w(TAG, "onCustomTileRemoved: Error receiving StatusBarPanelCustomTile", e);
return;
}
synchronized (mWrapper) {
try {
CustomTileListenerService.this.onCustomTileRemoved(sbc);
} catch (Throwable t) {
Log.w(TAG, "Error running onCustomTileRemoved", t);
}
}
}
}
/**
* Implement this method to learn about new custom tiles as they are posted by apps.
*
* @param sbc A data structure encapsulating the original {@link cyanogenmod.app.CustomTile}
* object as well as its identifying information (tag and id) and source
* (package name).
*/
public void onCustomTilePosted(StatusBarPanelCustomTile sbc) {
// optional
}
/**
* Implement this method to learn when custom tiles are removed.
*
* @param sbc A data structure encapsulating at least the original information (tag and id)
* and source (package name) used to post the {@link cyanogenmod.app.CustomTile} that
* was just removed.
*/
public void onCustomTileRemoved(StatusBarPanelCustomTile sbc) {
// optional
}
/**
* Implement this method to learn about when the listener is enabled and connected to
* the status bar manager.
* at this time.
*/
public void onListenerConnected() {
// optional
}
}

View File

@@ -0,0 +1,37 @@
/**
* 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.app;
import android.content.ComponentName;
import cyanogenmod.app.CustomTile;
import cyanogenmod.app.ICustomTileListener;
/** @hide */
interface ICMStatusBarManager {
// --- Methods below are for use by 3rd party applications to publish quick
// settings tiles to the status bar panel
// You need the PUBLISH_QUICK_SETTINGS_TILE permission
void createCustomTileWithTag(String pkg, String opPkg, String tag, int id,
in CustomTile tile, inout int[] idReceived, int userId);
void removeCustomTileWithTag(String pkg, String tag, int id, int userId);
// --- Methods below are for use by 3rd party applications
// You need the BIND_QUICK_SETTINGS_TILE_LISTENER permission
void registerListener(in ICustomTileListener listener, in ComponentName component, int userid);
void unregisterListener(in ICustomTileListener listener, int userid);
}

View File

@@ -0,0 +1,29 @@
/**
* 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.app;
import cyanogenmod.app.StatusBarPanelCustomTile;
import org.cyanogenmod.internal.statusbar.IStatusBarCustomTileHolder;
/** @hide */
oneway interface ICustomTileListener
{
void onListenerConnected();
void onCustomTilePosted(in IStatusBarCustomTileHolder customTileHolder);
void onCustomTileRemoved(in IStatusBarCustomTileHolder customTileHolder);
}

View File

@@ -0,0 +1,20 @@
/**
* 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.app;
parcelable StatusBarPanelCustomTile;

View File

@@ -0,0 +1,193 @@
/*
* 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.app;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
/**
* Class encapsulating a Custom Tile. Sent by the StatusBarManagerService to clients including
* the status bar panel and any {@link cyanogenmod.app.CustomTileListenerService} clients.
*/
public class StatusBarPanelCustomTile implements Parcelable {
private final String pkg;
private final int id;
private final String tag;
private final String key;
private final int uid;
private final String opPkg;
private final int initialPid;
private final CustomTile customTile;
private final UserHandle user;
private final long postTime;
public StatusBarPanelCustomTile(String pkg, String opPkg, int id, String tag, int uid,
int initialPid, CustomTile customTile, UserHandle user) {
this(pkg, opPkg, id, tag, uid, initialPid, customTile, user,
System.currentTimeMillis());
}
public StatusBarPanelCustomTile(String pkg, String opPkg, int id, String tag, int uid,
int initialPid, CustomTile customTile, UserHandle user,
long postTime) {
if (pkg == null) throw new NullPointerException();
if (customTile == null) throw new NullPointerException();
this.pkg = pkg;
this.opPkg = opPkg;
this.id = id;
this.tag = tag;
this.uid = uid;
this.initialPid = initialPid;
this.customTile = customTile;
this.user = user;
this.postTime = postTime;
this.key = key();
}
public StatusBarPanelCustomTile(Parcel in) {
this.pkg = in.readString();
this.opPkg = in.readString();
this.id = in.readInt();
if (in.readInt() != 0) {
this.tag = in.readString();
} else {
this.tag = null;
}
this.uid = in.readInt();
this.initialPid = in.readInt();
this.customTile = new CustomTile(in);
this.user = UserHandle.readFromParcel(in);
this.postTime = in.readLong();
this.key = key();
}
private String key() {
return user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid;
}
public static final Creator<StatusBarPanelCustomTile> CREATOR
= new Creator<StatusBarPanelCustomTile>()
{
public StatusBarPanelCustomTile createFromParcel(Parcel parcel)
{
return new StatusBarPanelCustomTile(parcel);
}
public StatusBarPanelCustomTile[] newArray(int size)
{
return new StatusBarPanelCustomTile[size];
}
};
/** The {@link cyanogenmod.app.CustomTile} supplied to
* {@link cyanogenmod.app.CMStatusBarManager#publishTile(int, cyanogenmod.app.CustomTile)}.
*/
public CustomTile getCustomTile() {
return customTile;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(this.pkg);
out.writeString(this.opPkg);
out.writeInt(this.id);
if (this.tag != null) {
out.writeInt(1);
out.writeString(this.tag);
} else {
out.writeInt(0);
}
out.writeInt(this.uid);
out.writeInt(this.initialPid);
this.customTile.writeToParcel(out, flags);
user.writeToParcel(out, flags);
out.writeLong(this.postTime);
}
@Override
public StatusBarPanelCustomTile clone() {
return new StatusBarPanelCustomTile(this.pkg, this.opPkg,
this.id, this.tag, this.uid, this.initialPid,
this.customTile.clone(), this.user, this.postTime);
}
/**
* Returns a userHandle for the instance of the app that posted this notification.
*/
public int getUserId() {
return this.user.getIdentifier();
}
/** The package of the app that posted the notification */
public String getPackage() {
return pkg;
}
/** The id supplied to CMStatusBarManager */
public int getId() {
return id;
}
/** The tag supplied to CMStatusBarManager or null if no tag was specified. */
public String getTag() {
return tag;
}
/**
* A unique instance key for this notification record.
*/
public String getKey() {
return key;
}
/** The notifying app's calling uid. @hide */
public int getUid() {
return uid;
}
/** The package used for AppOps tracking. @hide */
public String getOpPkg() {
return opPkg;
}
/** @hide */
public int getInitialPid() {
return initialPid;
}
/**
* The {@link android.os.UserHandle} for whom this CustomTile is intended.
*/
public UserHandle getUser() {
return user;
}
/** The time (in {@link System#currentTimeMillis} time) the CustomTile was published, */
public long getPostTime() {
return postTime;
}
}

View File

@@ -0,0 +1,53 @@
/**
* 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 org.cyanogenmod.internal.statusbar;
import android.os.UserHandle;
import com.android.internal.annotations.VisibleForTesting;
import cyanogenmod.app.CustomTile;
import cyanogenmod.app.StatusBarPanelCustomTile;
/**
* @hide
*/
public class ExternalQuickSettingsRecord {
public final StatusBarPanelCustomTile sbTile;
public boolean isUpdate;
public boolean isCanceled;
@VisibleForTesting
public ExternalQuickSettingsRecord(StatusBarPanelCustomTile tile) {
sbTile = tile;
}
public CustomTile getCustomTile() {
return sbTile.getCustomTile();
}
public UserHandle getUser() {
return sbTile.getUser();
}
public int getUserId() {
return sbTile.getUserId();
}
public String getKey() {
return sbTile.getKey();
}
}

View File

@@ -0,0 +1,25 @@
/**
* 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 org.cyanogenmod.internal.statusbar;
import cyanogenmod.app.StatusBarPanelCustomTile;
/** @hide */
interface IStatusBarCustomTileHolder {
/** Fetch the held StatusBarPanelCustomTile. This method should only be called once per Holder */
StatusBarPanelCustomTile get();
}