QS: Make themes a first class citizen again

Change-Id: Icd397a2ddd730ae525233b66288fde9a6798c221
TICKET: CYNGNOS-2670
diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/ThemeManagerService.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/ThemeManagerService.java
index 7b6054c..125df02 100644
--- a/cm/lib/main/java/org/cyanogenmod/platform/internal/ThemeManagerService.java
+++ b/cm/lib/main/java/org/cyanogenmod/platform/internal/ThemeManagerService.java
@@ -21,6 +21,7 @@
 import android.app.IActivityManager;
 import android.app.Notification;
 import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.app.WallpaperManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -55,6 +56,8 @@
 import com.android.server.SystemService;
 
 import cyanogenmod.app.CMContextConstants;
+import cyanogenmod.app.CMStatusBarManager;
+import cyanogenmod.app.CustomTile;
 import cyanogenmod.providers.CMSettings;
 import cyanogenmod.providers.ThemesContract.MixnMatchColumns;
 import cyanogenmod.providers.ThemesContract.ThemesColumns;
@@ -64,6 +67,8 @@
 import cyanogenmod.themes.ThemeChangeRequest;
 
 import org.cyanogenmod.internal.util.ImageUtils;
+import org.cyanogenmod.internal.util.QSConstants;
+import org.cyanogenmod.internal.util.QSUtils;
 import org.cyanogenmod.internal.util.ThemeUtils;
 import org.cyanogenmod.platform.internal.AppsFailureReceiver;
 
@@ -97,6 +102,8 @@
     private static final String CM_SETUPWIZARD_PACKAGE = "com.cyanogenmod.setupwizard";
     private static final String MANAGED_PROVISIONING_PACKAGE = "com.android.managedprovisioning";
 
+    private static final String CATEGORY_THEME_CHOOSER = "cyanogenmod.intent.category.APP_THEMES";
+
     // Defines a min and max compatible api level for themes on this system.
     private static final int MIN_COMPATIBLE_VERSION = 21;
 
@@ -264,6 +271,8 @@
             }
             registerAppsFailureReceiver();
             processInstalledThemes();
+        } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
+            publishThemesTile();
         }
     }
 
@@ -1116,6 +1125,39 @@
         return SYSTEM_DEFAULT;
     }
 
+    private void publishThemesTile() {
+        // This action should be performed as system
+        final int userId = UserHandle.myUserId();
+        long token = Binder.clearCallingIdentity();
+        try {
+            final UserHandle user = new UserHandle(userId);
+            final Context resourceContext = QSUtils.getQSTileContext(mContext, userId);
+
+            CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(mContext);
+            final PendingIntent chooserIntent = getThemeChooserPendingIntent();
+            CustomTile tile = new CustomTile.Builder(resourceContext)
+                    .setLabel(R.string.qs_themes_label)
+                    .setContentDescription(R.string.qs_themes_content_description)
+                    .setIcon(R.drawable.ic_qs_themes)
+                    .setOnClickIntent(chooserIntent)
+                    .setOnLongClickIntent(chooserIntent)
+                    .shouldCollapsePanel(true)
+                    .build();
+            statusBarManager.publishTileAsUser(QSConstants.DYNAMIC_TILE_THEMES,
+                    ThemeManagerService.class.hashCode(), tile, user);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private PendingIntent getThemeChooserPendingIntent() {
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(CATEGORY_THEME_CHOOSER);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        return PendingIntent.getActivity(mContext, ThemeManagerService.class.hashCode(),
+                intent, 0);
+    }
+
     private final IBinder mService = new IThemeService.Stub() {
         @Override
         public void requestThemeChangeUpdates(IThemeChangeListener listener)
diff --git a/cm/res/res/drawable/ic_qs_themes.xml b/cm/res/res/drawable/ic_qs_themes.xml
new file mode 100644
index 0000000..f8c6cfb
--- /dev/null
+++ b/cm/res/res/drawable/ic_qs_themes.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (c) 2016 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="64dp"
+    android:height="64dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21,5V3h-2v6c0,0.6-0.4,1-1,1s-1-0.4-1-1V3h-2v10c0,0.6-0.4,1-1,1s-1-0.4-1-1V7c0-0.6-0.4-1-1-1s-1,0.4-1,1v4
+c0,0.6-0.4,1-1,1s-1-0.4-1-1V8c0-0.6-0.4-1-1-1S7,7.4,7,8v8c0,0.6-0.4,1-1,1s-1-0.4-1-1V3H3v2H2v4h1v10c0,1.1,0.9,2,2,2h14
+c1.1,0,2-0.9,2-2V9h1V5H21z" />
+</vector>
\ No newline at end of file
diff --git a/cm/res/res/values/strings.xml b/cm/res/res/values/strings.xml
index 2c57e00..1551adf 100644
--- a/cm/res/res/values/strings.xml
+++ b/cm/res/res/values/strings.xml
@@ -218,4 +218,8 @@
     <string name="permlab_observe_audio_sessions">observe audio session changes</string>
     <string name="permdesc_observe_audio_sessions">Allows an app to observe audio streams being created and destroyed.</string>
 
+    <!-- QuickSettings: Themes tile -->
+    <string name="qs_themes_label">Themes</string>
+    <string name="qs_themes_content_description">Customize your theme</string>
+
 </resources>
diff --git a/cm/res/res/values/symbols.xml b/cm/res/res/values/symbols.xml
index fa31456..767f354 100644
--- a/cm/res/res/values/symbols.xml
+++ b/cm/res/res/values/symbols.xml
@@ -113,4 +113,9 @@
 
     <!-- External CM specific core services -->
     <java-symbol type="array" name="config_externalCMServices" />
+
+    <!-- Themes tile -->
+    <java-symbol type="string" name="qs_themes_label" />
+    <java-symbol type="string" name="qs_themes_content_description" />
+    <java-symbol type="drawable" name="ic_qs_themes" />
 </resources>
diff --git a/sdk/src/java/org/cyanogenmod/internal/logging/CMMetricsLogger.java b/sdk/src/java/org/cyanogenmod/internal/logging/CMMetricsLogger.java
index e3303d5..a059b3a 100644
--- a/sdk/src/java/org/cyanogenmod/internal/logging/CMMetricsLogger.java
+++ b/sdk/src/java/org/cyanogenmod/internal/logging/CMMetricsLogger.java
@@ -67,4 +67,5 @@
     public static final int TILE_BATTERY_SAVER = BASE + 40;
     public static final int TILE_CAFFEINE = BASE + 41;
     public static final int WEATHER_SETTINGS = BASE + 42;
+    public static final int TILE_THEMES = BASE + 43;
 }
diff --git a/sdk/src/java/org/cyanogenmod/internal/util/QSConstants.java b/sdk/src/java/org/cyanogenmod/internal/util/QSConstants.java
index c2cbc4d..c5e62eb 100644
--- a/sdk/src/java/org/cyanogenmod/internal/util/QSConstants.java
+++ b/sdk/src/java/org/cyanogenmod/internal/util/QSConstants.java
@@ -60,6 +60,7 @@
     public static final String DYNAMIC_TILE_SU = "su";
     public static final String DYNAMIC_TILE_ADB = "adb";
     public static final String DYNAMIC_TILE_LIVE_DISPLAY = "live_display";
+    public static final String DYNAMIC_TILE_THEMES = "themes";
 
     protected static final ArrayList<String> STATIC_TILES_AVAILABLE = new ArrayList<String>();
     protected static final ArrayList<String> DYNAMIC_TILES_AVAILBLE = new ArrayList<String>();
@@ -107,5 +108,6 @@
         DYNAMIC_TILES_AVAILBLE.add(DYNAMIC_TILE_NEXT_ALARM);
         DYNAMIC_TILES_AVAILBLE.add(DYNAMIC_TILE_SU);
         DYNAMIC_TILES_AVAILBLE.add(DYNAMIC_TILE_LIVE_DISPLAY);
+        DYNAMIC_TILES_AVAILBLE.add(DYNAMIC_TILE_THEMES);
     }
 }