summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdnan Begovic <adnan@cyngn.com>2015-12-01 16:34:10 -0800
committerAdnan Begovic <adnan@cyngn.com>2015-12-07 15:24:06 -0800
commitcf6674d766fe683e52e5c58e63152e9abd6ece89 (patch)
tree3b97dd23035ab50586b3ab55c9a824771cd7c4b7
parent95cce6e3e8586592511c83ebde6edb51ee6fdd0f (diff)
downloadframeworks_base-cf6674d766fe683e52e5c58e63152e9abd6ece89.zip
frameworks_base-cf6674d766fe683e52e5c58e63152e9abd6ece89.tar.gz
frameworks_base-cf6674d766fe683e52e5c58e63152e9abd6ece89.tar.bz2
SystemUi: Reintroduce custom qs tiles management.
Change-Id: I88dbf3911d4783de7c3f231aa57c51ce43bc8ae6
-rw-r--r--packages/SystemUI/AndroidManifest_cm.xml2
-rw-r--r--packages/SystemUI/res/layout/qs_custom_detail.xml57
-rw-r--r--packages/SystemUI/res/layout/qs_detail.xml10
-rw-r--r--packages/SystemUI/res/values/cm_strings.xml3
-rw-r--r--packages/SystemUI/res/values/cm_styles.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTile.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java177
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java90
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java6
17 files changed, 505 insertions, 0 deletions
diff --git a/packages/SystemUI/AndroidManifest_cm.xml b/packages/SystemUI/AndroidManifest_cm.xml
index a3ee433..187d3dc 100644
--- a/packages/SystemUI/AndroidManifest_cm.xml
+++ b/packages/SystemUI/AndroidManifest_cm.xml
@@ -21,6 +21,8 @@
<uses-permission android:name="cyanogenmod.permission.WRITE_SETTINGS" />
<uses-permission android:name="cyanogenmod.permission.WRITE_SECURE_SETTINGS" />
+ <!-- Quick Settings Tile Listener -->
+ <uses-permission android:name="cyanogenmod.permission.BIND_CUSTOM_TILE_LISTENER_SERVICE"/>
<!-- Development shortcut -->
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
diff --git a/packages/SystemUI/res/layout/qs_custom_detail.xml b/packages/SystemUI/res/layout/qs_custom_detail.xml
new file mode 100644
index 0000000..f7a002e
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_custom_detail.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="8dp">
+
+ <LinearLayout android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="horizontal">
+
+ <ImageView android:id="@+id/custom_qs_tile_icon"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:layout_marginEnd="12dp" />
+
+ <LinearLayout android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:orientation="vertical">
+
+ <TextView android:id="@+id/custom_qs_tile_title"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary"/>
+
+ <TextView android:id="@+id/custom_qs_tile_package "
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="2dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemSub"/>
+
+ <TextView android:id="@+id/custom_qs_tile_content_description"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="2dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemSub" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index ddff0f0..14ecd33 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -44,6 +44,16 @@
android:focusable="true" />
<TextView
+ android:id="@android:id/button3"
+ style="@style/QSBorderlessButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:minWidth="88dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailButton"
+ android:focusable="true" />
+
+ <TextView
android:id="@android:id/button1"
style="@style/QSBorderlessButton"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values/cm_strings.xml b/packages/SystemUI/res/values/cm_strings.xml
index 7b56807..0750700 100644
--- a/packages/SystemUI/res/values/cm_strings.xml
+++ b/packages/SystemUI/res/values/cm_strings.xml
@@ -85,4 +85,7 @@
<!-- Screen pinning dialog description (for devices without navbar) -->
<string name="screen_pinning_description_no_navbar">This keeps it in view until you unpin. Touch and hold the Back button to unpin.</string>
+
+ <string name="quick_settings_custom_tile_detail_title">Custom Tile</string>
+ <string name="quick_settings_remove">Remove tile</string>
</resources>
diff --git a/packages/SystemUI/res/values/cm_styles.xml b/packages/SystemUI/res/values/cm_styles.xml
index 36d8614..8caa89d 100644
--- a/packages/SystemUI/res/values/cm_styles.xml
+++ b/packages/SystemUI/res/values/cm_styles.xml
@@ -37,4 +37,8 @@
<item name="android:textColor">@color/status_bar_temperature_location_text_color</item>
</style>
+ <style name="TextAppearance.QS.DetailItemSub">
+ <item name="android:textSize">@dimen/qs_detail_item_secondary_text_size</item>
+ </style>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 1cdaeb8..7d9b48b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -47,6 +47,7 @@ import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import java.util.ArrayList;
import java.util.Collection;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import cyanogenmod.providers.CMSettings;
/** View that represents the quick settings tile panel. **/
@@ -56,6 +57,7 @@ public class QSPanel extends ViewGroup {
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
protected View mDetail;
protected ViewGroup mDetailContent;
+ protected TextView mDetailRemoveButton;
protected TextView mDetailSettingsButton;
protected TextView mDetailDoneButton;
protected View mBrightnessView;
@@ -96,6 +98,7 @@ public class QSPanel extends ViewGroup {
protected void setupViews() {
mDetail = LayoutInflater.from(mContext).inflate(R.layout.qs_detail, this, false);
mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content);
+ mDetailRemoveButton = (TextView) mDetail.findViewById(android.R.id.button3);
mDetailSettingsButton = (TextView) mDetail.findViewById(android.R.id.button2);
mDetailDoneButton = (TextView) mDetail.findViewById(android.R.id.button1);
updateDetailText();
@@ -146,6 +149,7 @@ public class QSPanel extends ViewGroup {
protected void updateDetailText() {
mDetailDoneButton.setText(R.string.quick_settings_done);
mDetailSettingsButton.setText(R.string.quick_settings_more_settings);
+ mDetailRemoveButton.setText(R.string.quick_settings_remove);
}
public void setBrightnessMirror(BrightnessMirrorController c) {
@@ -197,6 +201,7 @@ public class QSPanel extends ViewGroup {
super.onConfigurationChanged(newConfig);
FontSizeUtils.updateFontSize(mDetailDoneButton, R.dimen.qs_detail_button_text_size);
FontSizeUtils.updateFontSize(mDetailSettingsButton, R.dimen.qs_detail_button_text_size);
+ FontSizeUtils.updateFontSize(mDetailRemoveButton, R.dimen.qs_detail_button_text_size);
// We need to poke the detail views as well as they might not be attached to the view
// hierarchy but reused at a later point.
@@ -422,6 +427,16 @@ public class QSPanel extends ViewGroup {
}
});
+ final StatusBarPanelCustomTile customTile = detailAdapter.getCustomTile();
+ mDetailRemoveButton.setVisibility(customTile != null ? VISIBLE : GONE);
+ mDetailRemoveButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHost.collapsePanels();
+ mHost.removeCustomTile(customTile);
+ }
+ });
+
mDetailContent.removeAllViews();
mDetail.bringToFront();
mDetailContent.addView(r.detailView);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 6fa304d..cdc68f2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -40,6 +40,7 @@ import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import java.util.Collection;
import java.util.Objects;
@@ -105,6 +106,7 @@ public abstract class QSTile<TState extends State> implements Listenable {
Boolean getToggleState();
View createDetailView(Context context, View convertView, ViewGroup parent);
Intent getSettingsIntent();
+ StatusBarPanelCustomTile getCustomTile();
void setToggleState(boolean state);
int getMetricsCategory();
}
@@ -319,6 +321,7 @@ public abstract class QSTile<TState extends State> implements Listenable {
}
public interface Host {
+ void removeCustomTile(StatusBarPanelCustomTile customTile);
void startActivityDismissingKeyguard(Intent intent);
void warn(String message, Throwable t);
void collapsePanels();
@@ -357,6 +360,42 @@ public abstract class QSTile<TState extends State> implements Listenable {
}
}
+ protected class ExternalIcon extends AnimationIcon {
+ private Context mPackageContext;
+ private String mPkg;
+ private int mResId;
+
+ public ExternalIcon(String pkg, int resId) {
+ super(resId);
+ mPkg = pkg;
+ mResId = resId;
+ }
+
+ @Override
+ public Drawable getDrawable(Context context) {
+ // Get the drawable from the package context
+ Drawable d = null;
+ try {
+ d = super.getDrawable(getPackageContext());
+ } catch (Throwable t) {
+ Log.w(TAG, "Error creating package context" + mPkg + " id=" + mResId, t);
+ }
+ return d;
+ }
+
+ private Context getPackageContext() {
+ if (mPackageContext == null) {
+ try {
+ mPackageContext = mContext.createPackageContext(mPkg, 0);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error creating package context" + mPkg, t);
+ return null;
+ }
+ }
+ return mPackageContext;
+ }
+ }
+
public static class ResourceIcon extends Icon {
private static final SparseArray<Icon> ICONS = new SparseArray<Icon>();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 5cc3f3f..70a27ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -33,6 +33,7 @@ import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.BluetoothController;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import java.util.Collection;
import java.util.Set;
@@ -190,6 +191,11 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
}
@Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
public void setToggleState(boolean state) {
MetricsLogger.action(mContext, MetricsLogger.QS_BLUETOOTH_TOGGLE, state);
mController.setBluetoothEnabled(state);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 4da3cd9..f83bbf4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -33,6 +33,7 @@ import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import java.util.LinkedHashMap;
import java.util.Set;
@@ -183,6 +184,11 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
}
@Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
public void setToggleState(boolean state) {
// noop
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index c99d70a..426cf4b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -37,6 +37,7 @@ import com.android.systemui.statusbar.policy.NetworkController.MobileDataControl
import com.android.systemui.statusbar.policy.NetworkController.MobileDataController.DataUsageInfo;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.statusbar.policy.SignalCallbackAdapter;
+import cyanogenmod.app.StatusBarPanelCustomTile;
/** Quick settings tile: Cellular **/
public class CellularTile extends QSTile<QSTile.SignalState> {
@@ -247,6 +248,10 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
};
private final class CellularDetailAdapter implements DetailAdapter {
+ @Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
@Override
public int getTitle() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java
new file mode 100644
index 0000000..88e5666
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java
@@ -0,0 +1,177 @@
+/*
+ * 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 com.android.systemui.qs.tiles;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import com.android.internal.logging.MetricsLogger;
+import cyanogenmod.app.CustomTile;
+import cyanogenmod.app.StatusBarPanelCustomTile;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+
+public class CustomQSTile extends QSTile<QSTile.State> {
+
+ private PendingIntent mOnClick;
+ private Uri mOnClickUri;
+ private int mCurrentUserId;
+ private StatusBarPanelCustomTile mTile;
+ private CustomQSDetailAdapter mDetailAdapter;
+
+ public CustomQSTile(Host host, StatusBarPanelCustomTile tile) {
+ super(host);
+ refreshState(tile);
+ mDetailAdapter = new CustomQSDetailAdapter();
+ }
+
+ @Override
+ public DetailAdapter getDetailAdapter() {
+ return mDetailAdapter;
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ }
+
+ @Override
+ protected State newTileState() {
+ return new State();
+ }
+
+ @Override
+ protected void handleUserSwitch(int newUserId) {
+ super.handleUserSwitch(newUserId);
+ mCurrentUserId = newUserId;
+ }
+
+ public void update(StatusBarPanelCustomTile customTile) {
+ refreshState(customTile);
+ }
+
+ @Override
+ protected void handleLongClick() {
+ showDetail(true);
+ }
+
+ @Override
+ protected void handleClick() {
+ try {
+ if (mOnClick != null) {
+ if (mOnClick.isActivity()) {
+ mHost.collapsePanels();
+ }
+ mOnClick.send();
+ } else if (mOnClickUri != null) {
+ final Intent intent = new Intent().setData(mOnClickUri);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
+ }
+ } catch (Throwable t) {
+ Log.w(TAG, "Error sending click intent", t);
+ }
+ }
+
+ @Override
+ protected void handleUpdateState(State state, Object arg) {
+ if (arg instanceof StatusBarPanelCustomTile) {
+ mTile = (StatusBarPanelCustomTile) arg;
+ }
+ final CustomTile customTile = mTile.getCustomTile();
+ state.visible = true;
+ state.contentDescription = customTile.contentDescription;
+ state.label = customTile.label;
+ final int iconId = customTile.icon;
+ if (iconId != 0) {
+ final String iconPackage = mTile.getPackage();
+ if (!TextUtils.isEmpty(iconPackage)) {
+ state.icon = new ExternalIcon(iconPackage, iconId);
+ }
+ }
+ mOnClick = customTile.onClick;
+ mOnClickUri = customTile.onClickUri;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsLogger.DONT_TRACK_ME_BRO;
+ }
+
+ private class CustomQSDetailAdapter implements DetailAdapter {
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_custom_tile_detail_title;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return null;
+ }
+
+
+ @Override
+ public Intent getSettingsIntent() {
+ return mTile.getCustomTile().onSettingsClick;
+ }
+
+ @Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return mTile;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+ // noop
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsLogger.DONT_TRACK_ME_BRO;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ LinearLayout rootView = (LinearLayout) LayoutInflater.from(context)
+ .inflate(R.layout.qs_custom_detail, parent, false);
+ ImageView imageView = (ImageView) rootView.findViewById(R.id.custom_qs_tile_icon);
+ TextView customTileTitle = (TextView) rootView.findViewById(R.id.custom_qs_tile_title);
+ TextView customTilePkg = (TextView) rootView
+ .findViewById(R.id.custom_qs_tile_package);
+ TextView customTileContentDesc = (TextView) rootView
+ .findViewById(R.id.custom_qs_tile_content_description);
+
+ // icon is cached in state, fetch it
+ imageView.setImageDrawable(getState().icon.getDrawable(mContext));
+ customTileTitle.setText(mTile.getCustomTile().label);
+ customTilePkg.setText(mTile.getPackage());
+ customTileContentDesc.setText(mTile.getCustomTile().contentDescription);
+ return rootView;
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index afe42b9..6c40486 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -38,6 +38,7 @@ import com.android.systemui.SysUIToast;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.volume.ZenModePanel;
+import cyanogenmod.app.StatusBarPanelCustomTile;
/** Quick settings tile: Do not disturb **/
public class DndTile extends QSTile<QSTile.BooleanState> {
@@ -249,6 +250,11 @@ public class DndTile extends QSTile<QSTile.BooleanState> {
}
@Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
public void setToggleState(boolean state) {
MetricsLogger.action(mContext, MetricsLogger.QS_DND_TOGGLE, state);
if (!state) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index d90072e..b3e1701 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -37,6 +37,7 @@ import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.SignalCallbackAdapter;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import java.util.List;
@@ -256,6 +257,11 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
}
@Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
public Boolean getToggleState() {
return mState.enabled;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java b/packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java
new file mode 100644
index 0000000..5db1f98
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java
@@ -0,0 +1,67 @@
+/*
+ * 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 com.android.systemui.statusbar;
+
+import cyanogenmod.app.StatusBarPanelCustomTile;
+
+import android.util.ArrayMap;
+
+/**
+ * Custom tile data to keep track of created 3rd party tiles
+ */
+public class CustomTileData {
+ public static final class Entry {
+ public String key;
+ public StatusBarPanelCustomTile statusBarPanelCustomTile;
+
+ public Entry(StatusBarPanelCustomTile sbc) {
+ this.key = sbc.getKey();
+ }
+ }
+
+ private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
+
+ public ArrayMap<String, Entry> getEntries() {
+ return mEntries;
+ }
+
+ public void add(Entry entry) {
+ mEntries.put(entry.key, entry);
+ }
+
+ public Entry remove(String key) {
+ Entry removed = mEntries.remove(key);
+ if (removed == null) return null;
+ return removed;
+ }
+
+ public Entry get(String key) {
+ return mEntries.get(key);
+ }
+
+ public Entry get(int i) {
+ return mEntries.valueAt(i);
+ }
+
+ public void clear() {
+ mEntries.clear();
+ }
+
+ public int size() {
+ return mEntries.size();
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index a748aa3..f2445ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -17,12 +17,16 @@
package com.android.systemui.statusbar.phone;
import android.app.ActivityManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -35,6 +39,7 @@ import com.android.systemui.qs.tiles.BluetoothTile;
import com.android.systemui.qs.tiles.CastTile;
import com.android.systemui.qs.tiles.CellularTile;
import com.android.systemui.qs.tiles.ColorInversionTile;
+import com.android.systemui.qs.tiles.CustomQSTile;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.EditTile;
import com.android.systemui.qs.tiles.FlashlightTile;
@@ -43,6 +48,7 @@ import com.android.systemui.qs.tiles.IntentTile;
import com.android.systemui.qs.tiles.LocationTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.qs.tiles.WifiTile;
+import com.android.systemui.statusbar.CustomTileData;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.FlashlightController;
@@ -56,6 +62,8 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import cyanogenmod.app.CustomTileListenerService;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import cyanogenmod.providers.CMSettings;
import java.util.ArrayList;
@@ -88,6 +96,9 @@ public class QSTileHost implements QSTile.Host, Tunable {
private final UserSwitcherController mUserSwitcherController;
private final KeyguardMonitor mKeyguard;
private final SecurityController mSecurity;
+ private Handler mHandler;
+
+ private CustomTileData mCustomTileData;
private Callback mCallback;
@@ -111,11 +122,22 @@ public class QSTileHost implements QSTile.Host, Tunable {
mUserSwitcherController = userSwitcher;
mKeyguard = keyguard;
mSecurity = security;
+ mCustomTileData = new CustomTileData();
final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(),
Process.THREAD_PRIORITY_BACKGROUND);
ht.start();
mLooper = ht.getLooper();
+ mHandler = new Handler();
+
+ // Set up the initial notification state.
+ try {
+ mCustomTileListenerService.registerAsSystemService(mContext,
+ new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
+ UserHandle.USER_ALL);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to register custom tile listener", e);
+ }
TunerService.get(mContext).addTunableByProvider(this, CMSettings.Secure.QS_TILES, true);
}
@@ -164,6 +186,12 @@ public class QSTileHost implements QSTile.Host, Tunable {
}
@Override
+ public void removeCustomTile(StatusBarPanelCustomTile customTile) {
+ mCustomTileListenerService.removeCustomTile(customTile.getPackage(),
+ customTile.getTag(), customTile.getId());
+ }
+
+ @Override
public void warn(String message, Throwable t) {
// already logged
}
@@ -363,4 +391,66 @@ public class QSTileHost implements QSTile.Host, Tunable {
else if (spec.equals("edit")) return R.string.quick_settings_edit_label;
return 0;
}
+
+ private final CustomTileListenerService mCustomTileListenerService =
+ new CustomTileListenerService() {
+ @Override
+ public void onListenerConnected() {
+ //Connected
+ }
+ @Override
+ public void onCustomTilePosted(final StatusBarPanelCustomTile sbc) {
+ if (DEBUG) Log.d(TAG, "onCustomTilePosted: " + sbc.getCustomTile());
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ boolean isUpdate = mCustomTileData.get(sbc.getKey()) != null;
+ if (isUpdate) {
+ updateCustomTile(sbc);
+ } else {
+ addCustomTile(sbc);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onCustomTileRemoved(final StatusBarPanelCustomTile sbc) {
+ if (DEBUG) Log.d(TAG, "onCustomTileRemoved: " + sbc.getCustomTile());
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ removeCustomTileSysUi(sbc.getKey());
+ }
+ });
+ }
+ };
+
+ private void updateCustomTile(StatusBarPanelCustomTile sbc) {
+ if (mTiles.containsKey(sbc.getKey())) {
+ QSTile<?> tile = mTiles.get(sbc.getKey());
+ if (tile instanceof CustomQSTile) {
+ CustomQSTile qsTile = (CustomQSTile) tile;
+ qsTile.update(sbc);
+ }
+ }
+ }
+
+ private void addCustomTile(StatusBarPanelCustomTile sbc) {
+ mCustomTileData.add(new CustomTileData.Entry(sbc));
+ mTiles.put(sbc.getKey(), new CustomQSTile(this, sbc));
+ if (mCallback != null) {
+ mCallback.onTilesChanged();
+ }
+ }
+
+ private void removeCustomTileSysUi(String key) {
+ if (mTiles.containsKey(key)) {
+ mTiles.remove(key);
+ mCustomTileData.remove(key);
+ if (mCallback != null) {
+ mCallback.onTilesChanged();
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index b8293f3..3e5152e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -75,6 +75,7 @@ import com.android.systemui.tuner.TunerService;
import java.text.NumberFormat;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import cyanogenmod.providers.CMSettings;
/**
@@ -749,6 +750,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
if (mEditing) {
mQsPanelCallback.onShowingDetail(new QSTile.DetailAdapter() {
@Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
public int getTitle() {
return R.string.quick_settings_edit_label;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 3e8d4e9..38fb275 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -53,6 +53,7 @@ import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.tiles.UserDetailView;
import com.android.systemui.statusbar.phone.SystemUIDialog;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -587,6 +588,11 @@ public class UserSwitcherController {
}
@Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
public Boolean getToggleState() {
return null;
}