summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/org/cyanogenmod/themes/provider/AppReceiver.java65
-rw-r--r--src/org/cyanogenmod/themes/provider/PreferenceUtils.java66
-rw-r--r--src/org/cyanogenmod/themes/provider/ThemePackageHelper.java39
-rw-r--r--src/org/cyanogenmod/themes/provider/ThemesOpenHelper.java47
-rw-r--r--src/org/cyanogenmod/themes/provider/ThemesProvider.java37
-rw-r--r--src/org/cyanogenmod/themes/provider/util/ProviderUtils.java116
6 files changed, 219 insertions, 151 deletions
diff --git a/src/org/cyanogenmod/themes/provider/AppReceiver.java b/src/org/cyanogenmod/themes/provider/AppReceiver.java
index d979c96..2a6f85a 100644
--- a/src/org/cyanogenmod/themes/provider/AppReceiver.java
+++ b/src/org/cyanogenmod/themes/provider/AppReceiver.java
@@ -20,13 +20,9 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.ThemeManager;
-import android.database.Cursor;
import android.net.Uri;
-import android.provider.ThemesContract;
import android.util.Log;
-
-import java.util.Set;
+import org.cyanogenmod.themes.provider.util.ProviderUtils;
public class AppReceiver extends BroadcastReceiver {
public final static String TAG = AppReceiver.class.getName();
@@ -37,71 +33,38 @@ public class AppReceiver extends BroadcastReceiver {
final String pkgName = uri != null ? uri.getSchemeSpecificPart() : null;
final boolean isReplacing = intent.getExtras().getBoolean(Intent.EXTRA_REPLACING, false);
final String action = intent.getAction();
+ final boolean themeProcessing;
try {
if (Intent.ACTION_PACKAGE_ADDED.equals(action) && !isReplacing) {
- final boolean themeProcessing = isThemeBeingProcessed(context, pkgName);
- ThemePackageHelper.insertPackage(context, pkgName, !themeProcessing);
-
- if (themeProcessing) {
- // store this package name so we know it's being processed and it can be
- // added to the DB when ACTION_THEME_RESOURCES_CACHED is received
- PreferenceUtils.addThemeBeingProcessed(context, pkgName);
- }
+ themeProcessing = ProviderUtils.isThemeBeingProcessed(context, pkgName);
+ ThemePackageHelper.insertPackage(context, pkgName, themeProcessing);
} else if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
ThemePackageHelper.removePackage(context, pkgName);
} else if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
- final boolean themeProcessing = isThemeBeingProcessed(context, pkgName);
- if (themeExistsInProvider(context, pkgName)) {
- if (!themeProcessing) ThemePackageHelper.updatePackage(context, pkgName);
+ themeProcessing = ProviderUtils.isThemeBeingProcessed(context, pkgName);
+ if (ProviderUtils.themeExistsInProvider(context, pkgName)) {
+ ThemePackageHelper.updatePackage(context, pkgName, themeProcessing);
} else {
// Edge case where app was not a theme in previous install
- ThemePackageHelper.insertPackage(context, pkgName, !themeProcessing);
- }
-
- if (themeProcessing) {
- // store this package name so we know it's being processed and it can be
- // added or updated when ACTION_THEME_RESOURCES_CACHED is received
- PreferenceUtils.addThemeBeingProcessed(context, pkgName);
+ ThemePackageHelper.insertPackage(context, pkgName, themeProcessing);
}
} else if (Intent.ACTION_THEME_RESOURCES_CACHED.equals(action)) {
final String themePkgName = intent.getStringExtra(Intent.EXTRA_THEME_PACKAGE_NAME);
final int result = intent.getIntExtra(Intent.EXTRA_THEME_RESULT,
PackageManager.INSTALL_FAILED_THEME_UNKNOWN_ERROR);
- Set<String> processingThemes =
- PreferenceUtils.getInstalledThemesBeingProcessed(context);
- if (processingThemes != null &&
- processingThemes.contains(themePkgName) && result >= 0) {
- PreferenceUtils.removeThemeBeingProcessed(context, themePkgName);
- if (themeExistsInProvider(context, themePkgName)) {
- ThemePackageHelper.updatePackage(context, themePkgName);
+ if (result == 0) {
+ if (ProviderUtils.themeExistsInProvider(context, themePkgName)) {
+ ThemePackageHelper.updatePackage(context, themePkgName, false);
} else {
// Edge case where app was not a theme in previous install
- ThemePackageHelper.insertPackage(context, themePkgName, true);
+ ThemePackageHelper.insertPackage(context, themePkgName, false);
}
+ } else {
+ Log.e(TAG, "Unable to update theme " + themePkgName + ", result=" + result);
}
}
} catch(NameNotFoundException e) {
Log.e(TAG, "Unable to add package to theme's provider ", e);
}
}
-
- private static boolean themeExistsInProvider(Context context, String pkgName) {
- boolean exists = false;
- String[] projection = new String[] { ThemesContract.ThemesColumns.PKG_NAME };
- String selection = ThemesContract.ThemesColumns.PKG_NAME + "=?";
- String[] selectionArgs = new String[] { pkgName };
- Cursor c = context.getContentResolver().query(ThemesContract.ThemesColumns.CONTENT_URI,
- projection, selection, selectionArgs, null);
-
- if (c != null) {
- exists = c.getCount() >= 1;
- c.close();
- }
- return exists;
- }
-
- private boolean isThemeBeingProcessed(Context context, String pkgName) {
- ThemeManager tm = (ThemeManager) context.getSystemService(Context.THEME_SERVICE);
- return tm.isThemeBeingProcessed(pkgName);
- }
}
diff --git a/src/org/cyanogenmod/themes/provider/PreferenceUtils.java b/src/org/cyanogenmod/themes/provider/PreferenceUtils.java
deleted file mode 100644
index 09d62bb..0000000
--- a/src/org/cyanogenmod/themes/provider/PreferenceUtils.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2014 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.themes.provider;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-
-import java.util.HashSet;
-import java.util.Set;
-
-public class PreferenceUtils {
- public static final String PREF_INSTALLED_THEMES_PROCESSING = "installed_themes_processing";
-
- public static SharedPreferences getSharedPreferences(Context context) {
- if (context == null) return null;
- return context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
- }
-
- public static Set<String> getInstalledThemesBeingProcessed(Context context) {
- SharedPreferences prefs = getSharedPreferences(context);
- if (prefs == null) return null;
-
- return prefs.getStringSet(PREF_INSTALLED_THEMES_PROCESSING, null);
- }
-
- public static void addThemeBeingProcessed(Context context, String pkgName) {
- SharedPreferences prefs = getSharedPreferences(context);
- if (prefs != null) {
- Set<String> updatedThemes = new HashSet<String>();
- Set<String> current = prefs.getStringSet(PREF_INSTALLED_THEMES_PROCESSING, null);
- if (current != null) {
- updatedThemes.addAll(current);
- }
- if (updatedThemes.add(pkgName)) {
- prefs.edit().putStringSet(PREF_INSTALLED_THEMES_PROCESSING, updatedThemes).apply();
- }
- }
- }
-
- public static void removeThemeBeingProcessed(Context context, String pkgName) {
- SharedPreferences prefs = getSharedPreferences(context);
- if (prefs != null) {
- Set<String> updatedThemes = new HashSet<String>();
- Set<String> current = prefs.getStringSet(PREF_INSTALLED_THEMES_PROCESSING, null);
- if (current != null) {
- updatedThemes.addAll(current);
- }
- if (updatedThemes.remove(pkgName)) {
- prefs.edit().putStringSet(PREF_INSTALLED_THEMES_PROCESSING, updatedThemes).apply();
- }
- }
- }
-}
diff --git a/src/org/cyanogenmod/themes/provider/ThemePackageHelper.java b/src/org/cyanogenmod/themes/provider/ThemePackageHelper.java
index 053473e..254e658 100644
--- a/src/org/cyanogenmod/themes/provider/ThemePackageHelper.java
+++ b/src/org/cyanogenmod/themes/provider/ThemePackageHelper.java
@@ -15,6 +15,7 @@
*/
package org.cyanogenmod.themes.provider;
+import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageInfo;
@@ -31,7 +32,9 @@ import android.database.Cursor;
import android.provider.ThemesContract;
import android.provider.ThemesContract.MixnMatchColumns;
import android.provider.ThemesContract.ThemesColumns;
+import android.provider.ThemesContract.ThemesColumns.InstallState;
import android.util.Log;
+import org.cyanogenmod.themes.provider.util.ProviderUtils;
import java.io.IOException;
import java.util.Collections;
@@ -66,7 +69,7 @@ public class ThemePackageHelper {
"overlays/com.android.systemui");
}
- public static boolean insertPackage(Context context, String pkgName, boolean processPreviews)
+ public static boolean insertPackage(Context context, String pkgName, boolean isProcessing)
throws NameNotFoundException {
PackageInfo pi = context.getPackageManager().getPackageInfo(pkgName, 0);
if (pi == null)
@@ -74,18 +77,18 @@ public class ThemePackageHelper {
Map<String, Boolean> capabilities = getCapabilities(context, pkgName);
if (pi.themeInfo != null) {
- insertPackageInternal(context, pi, capabilities, processPreviews);
+ insertPackageInternal(context, pi, capabilities, isProcessing);
} else if (pi.isLegacyIconPackApk){
// We must be here because it is a legacy icon pack
capabilities = new HashMap<String, Boolean>();
capabilities.put(ThemesColumns.MODIFIES_ICONS, true);
- insertLegacyIconPackInternal(context, pi, capabilities,processPreviews);
+ insertLegacyIconPackInternal(context, pi, capabilities, isProcessing);
}
return true;
}
private static void insertPackageInternal(Context context, PackageInfo pi,
- Map<String, Boolean> capabilities, boolean processPreviews) {
+ Map<String, Boolean> capabilities, boolean isProcessing) {
ThemeInfo info = pi.themeInfo;
boolean isPresentableTheme = isPresentableTheme(capabilities);
@@ -100,8 +103,9 @@ public class ThemePackageHelper {
ThemeUtils.getDefaultThemePackageName(context).equals(pi.packageName) ? 1 : 0);
values.put(ThemesColumns.LAST_UPDATE_TIME, pi.lastUpdateTime);
values.put(ThemesColumns.INSTALL_TIME, pi.firstInstallTime);
- values.put(ThemesProvider.KEY_PROCESS_PREVIEWS, processPreviews);
values.put(ThemesColumns.TARGET_API, pi.applicationInfo.targetSdkVersion);
+ values.put(ThemesColumns.INSTALL_STATE, isProcessing ? InstallState.INSTALLING :
+ InstallState.INSTALLED);
// Insert theme capabilities
insertCapabilities(capabilities, values);
@@ -110,7 +114,7 @@ public class ThemePackageHelper {
}
private static void insertLegacyIconPackInternal(Context context, PackageInfo pi,
- Map<String, Boolean> capabilities, boolean processPreviews) {
+ Map<String, Boolean> capabilities, boolean isProcessing) {
PackageManager pm = context.getPackageManager();
CharSequence labelName = pm.getApplicationLabel(pi.applicationInfo);
if (labelName == null) labelName = context.getString(R.string.unknown_app_name);
@@ -123,8 +127,9 @@ public class ThemePackageHelper {
values.put(ThemesColumns.LAST_UPDATE_TIME, pi.lastUpdateTime);
values.put(ThemesColumns.INSTALL_TIME, pi.firstInstallTime);
values.put(ThemesColumns.IS_LEGACY_ICONPACK, 1);
- values.put(ThemesProvider.KEY_PROCESS_PREVIEWS, processPreviews);
values.put(ThemesColumns.TARGET_API, pi.applicationInfo.targetSdkVersion);
+ values.put(ThemesColumns.INSTALL_STATE, isProcessing ? InstallState.INSTALLING :
+ InstallState.INSTALLED);
// Insert theme capabilities
insertCapabilities(capabilities, values);
@@ -132,16 +137,17 @@ public class ThemePackageHelper {
context.getContentResolver().insert(ThemesColumns.CONTENT_URI, values);
}
- public static void updatePackage(Context context, String pkgName) throws NameNotFoundException {
+ public static void updatePackage(Context context, String pkgName, boolean isProcessing)
+ throws NameNotFoundException {
if (SYSTEM_DEFAULT.equals(pkgName)) {
updateSystemPackageInternal(context);
} else {
PackageInfo pi = context.getPackageManager().getPackageInfo(pkgName, 0);
Map<String, Boolean> capabilities = getCapabilities(context, pkgName);
if (pi.themeInfo != null) {
- updatePackageInternal(context, pi, capabilities);
+ updatePackageInternal(context, pi, capabilities, isProcessing);
} else if (pi.isLegacyIconPackApk) {
- updateLegacyIconPackInternal(context, pi, capabilities);
+ updateLegacyIconPackInternal(context, pi, capabilities, isProcessing);
}
// We should reapply any components that are currently applied for this theme.
@@ -150,7 +156,7 @@ public class ThemePackageHelper {
}
private static void updatePackageInternal(Context context, PackageInfo pi,
- Map<String, Boolean> capabilities) {
+ Map<String, Boolean> capabilities, boolean isProcessing) {
ThemeInfo info = pi.themeInfo;
boolean isPresentableTheme = ThemePackageHelper.isPresentableTheme(capabilities);
ContentValues values = new ContentValues();
@@ -164,6 +170,8 @@ public class ThemePackageHelper {
ThemeUtils.getDefaultThemePackageName(context).equals(pi.packageName) ? 1 : 0);
values.put(ThemesColumns.LAST_UPDATE_TIME, pi.lastUpdateTime);
values.put(ThemesColumns.INSTALL_TIME, pi.firstInstallTime);
+ values.put(ThemesColumns.INSTALL_STATE,
+ isProcessing ? InstallState.UPDATING : InstallState.INSTALLED);
// Insert theme capabilities
insertCapabilities(capabilities, values);
@@ -183,7 +191,7 @@ public class ThemePackageHelper {
}
private static void updateLegacyIconPackInternal(Context context, PackageInfo pi,
- Map<String, Boolean> capabilities) {
+ Map<String, Boolean> capabilities, boolean isProcessing) {
PackageManager pm = context.getPackageManager();
CharSequence labelName = pm.getApplicationLabel(pi.applicationInfo);
if (labelName == null) labelName = context.getString(R.string.unknown_app_name);
@@ -195,6 +203,8 @@ public class ThemePackageHelper {
values.put(ThemesColumns.DATE_CREATED, System.currentTimeMillis());
values.put(ThemesColumns.LAST_UPDATE_TIME, pi.lastUpdateTime);
values.put(ThemesColumns.INSTALL_TIME, pi.firstInstallTime);
+ values.put(ThemesColumns.INSTALL_STATE,
+ isProcessing ? InstallState.UPDATING : InstallState.INSTALLED);
String where = ThemesColumns.PKG_NAME + "=?";
String[] args = { pi.packageName };
@@ -240,7 +250,10 @@ public class ThemePackageHelper {
// Delete the theme from the db
String selection = ThemesColumns.PKG_NAME + "= ?";
String[] selectionArgs = { pkgToRemove };
- context.getContentResolver().delete(ThemesColumns.CONTENT_URI, selection, selectionArgs);
+ final ContentResolver resolver = context.getContentResolver();
+ if (resolver.delete(ThemesColumns.CONTENT_URI, selection, selectionArgs) > 0) {
+ ProviderUtils.sendThemeRemovedBroadcast(context, pkgToRemove);
+ }
}
/**
diff --git a/src/org/cyanogenmod/themes/provider/ThemesOpenHelper.java b/src/org/cyanogenmod/themes/provider/ThemesOpenHelper.java
index 7e747bc..b065f79 100644
--- a/src/org/cyanogenmod/themes/provider/ThemesOpenHelper.java
+++ b/src/org/cyanogenmod/themes/provider/ThemesOpenHelper.java
@@ -36,9 +36,9 @@ import android.util.Log;
public class ThemesOpenHelper extends SQLiteOpenHelper {
private static final String TAG = ThemesOpenHelper.class.getName();
- private static final int DATABASE_VERSION = 12;
+ private static final int DATABASE_VERSION = 13;
private static final String DATABASE_NAME = "themes.db";
- private static final String DEFAULT_PKG_NAME = ThemeConfig.SYSTEM_DEFAULT;
+ private static final String SYSTEM_THEME_PKG_NAME = ThemeConfig.SYSTEM_DEFAULT;
private Context mContext;
@@ -106,6 +106,10 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
upgradeToVersion12(db);
oldVersion = 12;
}
+ if (oldVersion == 12) {
+ upgradeToVersion13(db);
+ oldVersion = 13;
+ }
if (oldVersion != DATABASE_VERSION) {
Log.e(TAG, "Recreating db because unknown database version: " + oldVersion);
dropTables(db);
@@ -130,7 +134,7 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
// Add default value to mixnmatch for KEY_ALARM
ContentValues values = new ContentValues();
values.put(MixnMatchColumns.COL_KEY, ThemesContract.MixnMatchColumns.KEY_ALARM);
- values.put(MixnMatchColumns.COL_VALUE, DEFAULT_PKG_NAME);
+ values.put(MixnMatchColumns.COL_VALUE, SYSTEM_THEME_PKG_NAME);
db.insert(MixnMatchTable.TABLE_NAME, null, values);
}
@@ -149,20 +153,20 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
// change default package name to holo
String changeDefaultToSystem = String.format("UPDATE %s SET %s='%s' WHERE" +
" %s='%s'", ThemesTable.TABLE_NAME, ThemesColumns.PKG_NAME,
- DEFAULT_PKG_NAME, ThemesColumns.PKG_NAME, "default");
+ SYSTEM_THEME_PKG_NAME, ThemesColumns.PKG_NAME, "default");
db.execSQL(changeDefaultToSystem);
if (isSystemDefault(mContext)) {
// flag holo as default if
String makeHoloDefault = String.format("UPDATE %s SET %s=%d WHERE" +
" %s='%s'", ThemesTable.TABLE_NAME, ThemesColumns.IS_DEFAULT_THEME, 1,
- ThemesColumns.PKG_NAME, DEFAULT_PKG_NAME);
+ ThemesColumns.PKG_NAME, SYSTEM_THEME_PKG_NAME);
db.execSQL(makeHoloDefault);
}
// change any existing mixnmatch values set to "default" to "holo"
db.execSQL(String.format("UPDATE %s SET %s='%s' WHERE %s='%s'",
- MixnMatchTable.TABLE_NAME, MixnMatchColumns.COL_VALUE, DEFAULT_PKG_NAME,
+ MixnMatchTable.TABLE_NAME, MixnMatchColumns.COL_VALUE, SYSTEM_THEME_PKG_NAME,
MixnMatchColumns.COL_VALUE, "default"));
}
@@ -217,7 +221,7 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
final String pkgName = c.getString(0);
final boolean isLegacyTheme = c.getInt(1) == 1;
boolean hasSystemUi = false;
- if (DEFAULT_PKG_NAME.equals(pkgName) || isLegacyTheme) {
+ if (SYSTEM_THEME_PKG_NAME.equals(pkgName) || isLegacyTheme) {
hasSystemUi = true;
} else {
try {
@@ -262,7 +266,7 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
final String pkgName = c.getString(0);
final boolean isLegacyTheme = c.getInt(1) == 1;
boolean hasSystemUi = false;
- if (DEFAULT_PKG_NAME.equals(pkgName) || isLegacyTheme) {
+ if (SYSTEM_THEME_PKG_NAME.equals(pkgName) || isLegacyTheme) {
hasSystemUi = true;
} else {
try {
@@ -323,7 +327,7 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
while(c.moveToNext()) {
final String pkgName = c.getString(0);
int targetSdk = -1;
- if (DEFAULT_PKG_NAME.equals(pkgName)) {
+ if (SYSTEM_THEME_PKG_NAME.equals(pkgName)) {
// 0 is a special value used for the system theme, not to be confused with the
// default theme which may not be the same as the system theme.
targetSdk = 0;
@@ -354,7 +358,7 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
"WHERE %s='%s'",
ThemesTable.TABLE_NAME,
NEW_THEME_TITLE,
- DEFAULT_PKG_NAME,
+ SYSTEM_THEME_PKG_NAME,
ThemesColumns.PKG_NAME, PREV_SYSTEM_PKG_NAME);
db.execSQL(holoToSystem);
@@ -380,6 +384,18 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
}
}
+ private void upgradeToVersion13(SQLiteDatabase db) {
+ // add install_state column to themes db
+ String sql = String.format("ALTER TABLE %s ADD COLUMN %s INTEGER DEFAULT %d",
+ ThemesTable.TABLE_NAME, ThemesColumns.INSTALL_STATE,
+ ThemesColumns.InstallState.UNKNOWN);
+ db.execSQL(sql);
+
+ // we need to update any existing themes with their install state
+ db.execSQL(String.format("UPDATE %s SET %s='%d'", ThemesTable.TABLE_NAME,
+ ThemesColumns.INSTALL_STATE, ThemesColumns.InstallState.INSTALLED));
+ }
+
private void dropTables(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + ThemesTable.TABLE_NAME);
db.execSQL("DROP TABLE IF EXISTS " + MixnMatchTable.TABLE_NAME);
@@ -423,14 +439,16 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
ThemesColumns.IS_LEGACY_ICONPACK + " INTEGER DEFAULT 0, " +
ThemesColumns.LAST_UPDATE_TIME + " INTEGER DEFAULT 0, " +
ThemesColumns.INSTALL_TIME + " INTEGER DEFAULT 0, " +
- ThemesColumns.TARGET_API + " INTEGER DEFAULT 0" +
+ ThemesColumns.TARGET_API + " INTEGER DEFAULT 0," +
+ ThemesColumns.INSTALL_STATE + " INTEGER DEFAULT " +
+ ThemesColumns.InstallState.UNKNOWN +
")";
public static void insertSystemDefaults(SQLiteDatabase db, Context context) {
int isDefault = isSystemDefault(context) ? 1 : 0;
ContentValues values = new ContentValues();
values.put(ThemesColumns.TITLE, "System");
- values.put(ThemesColumns.PKG_NAME, DEFAULT_PKG_NAME);
+ values.put(ThemesColumns.PKG_NAME, SYSTEM_THEME_PKG_NAME);
values.put(ThemesColumns.PRIMARY_COLOR, 0xff33b5e5);
values.put(ThemesColumns.SECONDARY_COLOR, 0xff000000);
values.put(ThemesColumns.AUTHOR, "Android");
@@ -450,6 +468,7 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
values.put(ThemesColumns.IS_LEGACY_ICONPACK, 0);
values.put(ThemesColumns.MODIFIES_OVERLAYS, 1);
values.put(ThemesColumns.TARGET_API, Build.VERSION.SDK_INT);
+ values.put(ThemesColumns.INSTALL_STATE, ThemesColumns.InstallState.INSTALLED);
db.insert(TABLE_NAME, null, values);
}
}
@@ -466,7 +485,7 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
ContentValues values = new ContentValues();
for(String key : MixnMatchColumns.ROWS) {
values.put(MixnMatchColumns.COL_KEY, key);
- values.put(MixnMatchColumns.COL_VALUE, DEFAULT_PKG_NAME);
+ values.put(MixnMatchColumns.COL_VALUE, SYSTEM_THEME_PKG_NAME);
db.insert(TABLE_NAME, null, values);
}
}
@@ -533,7 +552,7 @@ public class ThemesOpenHelper extends SQLiteOpenHelper {
public static void insertDefaults(Context context) {
Intent intent = new Intent(context, PreviewGenerationService.class);
intent.setAction(PreviewGenerationService.ACTION_INSERT);
- intent.putExtra(PreviewGenerationService.EXTRA_PKG_NAME, DEFAULT_PKG_NAME);
+ intent.putExtra(PreviewGenerationService.EXTRA_PKG_NAME, SYSTEM_THEME_PKG_NAME);
intent.putExtra(PreviewGenerationService.EXTRA_HAS_SYSTEMUI, true);
intent.putExtra(PreviewGenerationService.EXTRA_HAS_ICONS, true);
intent.putExtra(PreviewGenerationService.EXTRA_HAS_STYLES, true);
diff --git a/src/org/cyanogenmod/themes/provider/ThemesProvider.java b/src/org/cyanogenmod/themes/provider/ThemesProvider.java
index 503d703..ae0a5af 100644
--- a/src/org/cyanogenmod/themes/provider/ThemesProvider.java
+++ b/src/org/cyanogenmod/themes/provider/ThemesProvider.java
@@ -17,6 +17,7 @@ package org.cyanogenmod.themes.provider;
import android.content.ContentProvider;
+import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -43,6 +44,7 @@ import android.util.Log;
import org.cyanogenmod.themes.provider.ThemesOpenHelper.MixnMatchTable;
import org.cyanogenmod.themes.provider.ThemesOpenHelper.PreviewsTable;
import org.cyanogenmod.themes.provider.ThemesOpenHelper.ThemesTable;
+import org.cyanogenmod.themes.provider.util.ProviderUtils;
import java.util.ArrayList;
import java.util.Collection;
@@ -150,9 +152,9 @@ public class ThemesProvider extends ContentProvider {
switch (uriType) {
case THEMES:
boolean processPreviews = true;
- if (values.containsKey(KEY_PROCESS_PREVIEWS)) {
- processPreviews = values.getAsBoolean(KEY_PROCESS_PREVIEWS);
- values.remove(KEY_PROCESS_PREVIEWS);
+ if (values.containsKey(ThemesColumns.INSTALL_STATE)) {
+ int state = values.getAsInteger(ThemesColumns.INSTALL_STATE);
+ processPreviews = state == ThemesColumns.InstallState.INSTALLING;
}
id = sqlDB.insert(ThemesOpenHelper.ThemesTable.TABLE_NAME, null, values);
if (processPreviews) {
@@ -185,8 +187,11 @@ public class ThemesProvider extends ContentProvider {
break;
default:
}
- getContext().getContentResolver().notifyChange(uri, null);
- return Uri.parse(MixnMatchColumns.CONTENT_URI + "/" + id);
+ if (id >= 0) {
+ ContentUris.withAppendedId(uri, id);
+ getContext().getContentResolver().notifyChange(uri, null);
+ }
+ return uri;
}
@Override
@@ -272,6 +277,8 @@ public class ThemesProvider extends ContentProvider {
case THEMES_ID:
String pkgName = values.getAsString(ThemesColumns.PKG_NAME);
final boolean updatePreviews = getShouldUpdatePreviews(sqlDB, pkgName);
+ final int oldInstallState =
+ ProviderUtils.getInstallStateForTheme(getContext(), pkgName);
rowsUpdated = sqlDB.update(ThemesTable.TABLE_NAME, values, selection, selectionArgs);
if (updateNotTriggeredByContentProvider(values) && updatePreviews) {
Intent intent = new Intent(getContext(), PreviewGenerationService.class);
@@ -295,6 +302,18 @@ public class ThemesProvider extends ContentProvider {
hasBootAni != null && hasBootAni);
getContext().startService(intent);
}
+ // Broadcast that the theme is installed if the previous state was INSTALLING and
+ // the new state is INSTALLED.
+ if (values.containsKey(ThemesColumns.INSTALL_STATE)) {
+ int newState = values.getAsInteger(ThemesColumns.INSTALL_STATE);
+ if (newState == ThemesColumns.InstallState.INSTALLED) {
+ if (oldInstallState == ThemesColumns.InstallState.INSTALLING) {
+ ProviderUtils.sendThemeInstalledBroadcast(getContext(), pkgName);
+ } else if (oldInstallState == ThemesColumns.InstallState.UPDATING) {
+ ProviderUtils.sendThemeUpdatedBroadcast(getContext(), pkgName);
+ }
+ }
+ }
getContext().getContentResolver().notifyChange(uri, null);
break;
case MIXNMATCH:
@@ -555,7 +574,9 @@ public class ThemesProvider extends ContentProvider {
private void insertThemes(Collection<PackageInfo> themesToInsert) {
for (PackageInfo themeInfo : themesToInsert) {
try {
- ThemePackageHelper.insertPackage(getContext(), themeInfo.packageName, true);
+ final Context context = getContext();
+ ThemePackageHelper.insertPackage(context, themeInfo.packageName,
+ ProviderUtils.isThemeBeingProcessed(context, themeInfo.packageName));
} catch (NameNotFoundException e) {
Log.e(TAG, "Unable to insert theme " + themeInfo.packageName, e);
}
@@ -565,7 +586,9 @@ public class ThemesProvider extends ContentProvider {
private void updateThemes(List<String> themesToUpdate) {
for (String pkgName : themesToUpdate) {
try {
- ThemePackageHelper.updatePackage(getContext(), pkgName);
+ final Context context = getContext();
+ ThemePackageHelper.updatePackage(context, pkgName,
+ ProviderUtils.isThemeBeingProcessed(context, pkgName));
} catch (NameNotFoundException e) {
Log.e(TAG, "Unable to update theme " + pkgName, e);
}
diff --git a/src/org/cyanogenmod/themes/provider/util/ProviderUtils.java b/src/org/cyanogenmod/themes/provider/util/ProviderUtils.java
new file mode 100644
index 0000000..a07d0ba
--- /dev/null
+++ b/src/org/cyanogenmod/themes/provider/util/ProviderUtils.java
@@ -0,0 +1,116 @@
+/*
+ * 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.themes.provider.util;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.ThemeManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ThemesContract;
+import android.provider.ThemesContract.ThemesColumns;
+
+public class ProviderUtils {
+ /**
+ * Convenience method for determining if a theme exists in the provider
+ * @param context
+ * @param pkgName
+ * @return True if the theme exists, false otherwise
+ */
+ public static boolean themeExistsInProvider(Context context, String pkgName) {
+ boolean exists = false;
+ String[] projection = new String[] { ThemesColumns.PKG_NAME };
+ String selection = ThemesColumns.PKG_NAME + "=?";
+ String[] selectionArgs = new String[] { pkgName };
+ Cursor c = context.getContentResolver().query(ThemesColumns.CONTENT_URI,
+ projection, selection, selectionArgs, null);
+
+ if (c != null) {
+ exists = c.getCount() >= 1;
+ c.close();
+ }
+ return exists;
+ }
+
+ /**
+ * Queries the {@link android.content.res.ThemeManager} to check if the theme is currently
+ * being processed by {@link com.android.server.ThemeService}
+ * @param context
+ * @param pkgName
+ * @return True if the theme is being processed or queued up for processing
+ */
+ public static boolean isThemeBeingProcessed(Context context, String pkgName) {
+ ThemeManager tm = (ThemeManager) context.getSystemService(Context.THEME_SERVICE);
+ return tm.isThemeBeingProcessed(pkgName);
+ }
+
+ /**
+ * Convenience method for getting the install state of a theme in the provider
+ * @param context
+ * @param pkgName
+ * @return
+ */
+ public static int getInstallStateForTheme(Context context, String pkgName) {
+ String[] projection = new String[] { ThemesColumns.INSTALL_STATE };
+ String selection = ThemesColumns.PKG_NAME + "=?";
+ String[] selectionArgs = new String[] { pkgName };
+ Cursor c = context.getContentResolver().query(ThemesColumns.CONTENT_URI,
+ projection, selection, selectionArgs, null);
+
+ int state = ThemesColumns.InstallState.UNKNOWN;
+ if (c != null) {
+ if (c.moveToFirst()) {
+ state = c.getInt(c.getColumnIndex(ThemesColumns.INSTALL_STATE));
+ }
+ c.close();
+ }
+ return state;
+ }
+
+ /**
+ * Sends the {@link android.provider.ThemesContract.Intent#ACTION_THEME_INSTALLED} action
+ * @param context
+ * @param pkgName
+ */
+ public static void sendThemeInstalledBroadcast(Context context, String pkgName) {
+ Intent intent = new Intent(ThemesContract.Intent.ACTION_THEME_INSTALLED,
+ Uri.fromParts(ThemesContract.Intent.URI_SCHEME_PACKAGE, pkgName, null));
+ context.sendBroadcast(intent, Manifest.permission.READ_THEMES);
+ }
+
+ /**
+ * Sends the {@link android.provider.ThemesContract.Intent#ACTION_THEME_UPDATED} action
+ * @param context
+ * @param pkgName
+ */
+ public static void sendThemeUpdatedBroadcast(Context context, String pkgName) {
+ Intent intent = new Intent(ThemesContract.Intent.ACTION_THEME_UPDATED,
+ Uri.fromParts(ThemesContract.Intent.URI_SCHEME_PACKAGE, pkgName, null));
+ context.sendBroadcast(intent, Manifest.permission.READ_THEMES);
+ }
+
+ /**
+ * Sends the {@link android.provider.ThemesContract.Intent#ACTION_THEME_REMOVED} action
+ * @param context
+ * @param pkgName
+ */
+ public static void sendThemeRemovedBroadcast(Context context, String pkgName) {
+ Intent intent = new Intent(ThemesContract.Intent.ACTION_THEME_REMOVED,
+ Uri.fromParts(ThemesContract.Intent.URI_SCHEME_PACKAGE, pkgName, null));
+ context.sendBroadcast(intent, Manifest.permission.READ_THEMES);
+ }
+}