diff --git a/src/java/cyanogenmod/app/ThemeComponent.java b/src/java/cyanogenmod/app/ThemeComponent.java new file mode 100644 index 0000000..d3f6625 --- /dev/null +++ b/src/java/cyanogenmod/app/ThemeComponent.java @@ -0,0 +1,38 @@ +/* + * 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; + +/** + * The id value here matches the framework. Unknown is given a -1 value since future + * framework components will always be positive. + * @hide + */ +public enum ThemeComponent { + UNKNOWN(-1), + OVERLAY(0), + BOOT_ANIM(1), + WALLPAPER(2), + LOCKSCREEN(3), + FONT(4), + ICON(5), + SOUND(6); + + public int id; + ThemeComponent(int id) { + this.id = id; + } + +} diff --git a/src/java/cyanogenmod/app/ThemeVersion.java b/src/java/cyanogenmod/app/ThemeVersion.java new file mode 100644 index 0000000..d4c45e6 --- /dev/null +++ b/src/java/cyanogenmod/app/ThemeVersion.java @@ -0,0 +1,203 @@ +/* + * 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.Build; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +public class ThemeVersion { + private static final String THEME_VERSION_CLASS_NAME = "android.content.ThemeVersion"; + private static final String THEME_VERSION_FIELD_NAME = "THEME_VERSION"; + private static final String MIN_SUPPORTED_THEME_VERSION_FIELD_NAME = + "MIN_SUPPORTED_THEME_VERSION"; + private static final int CM11 = 1; + private static final int CM12_PRE_VERSIONING = 2; + + public static int getVersion() { + int version; + try { + Class themeVersionClass = Class.forName(THEME_VERSION_CLASS_NAME); + Field themeVersionField = themeVersionClass.getField(THEME_VERSION_FIELD_NAME); + version = (Integer) themeVersionField.get(null); + } catch(Exception e) { + // Field doesn't exist. Fallback to SDK level + version = Build.VERSION.SDK_INT < 21 ? CM11 : + CM12_PRE_VERSIONING; + } + return version; + } + + public static int getMinSupportedVersion() { + int getMinSupportedVersion; + try { + Class themeVersionClass = Class.forName(THEME_VERSION_CLASS_NAME); + Field themeVersionField = + themeVersionClass.getField(MIN_SUPPORTED_THEME_VERSION_FIELD_NAME); + getMinSupportedVersion = (Integer) themeVersionField.get(null); + } catch(Exception e) { + // Field doesn't exist. Fallback to SDK level + getMinSupportedVersion = Build.VERSION.SDK_INT < 21 ? CM11 : + CM12_PRE_VERSIONING; + } + return getMinSupportedVersion; + } + + public static ComponentVersion getComponentVersion(ThemeComponent component) { + int version = getVersion(); + if (version == 1) { + throw new UnsupportedOperationException(); + } else if (version == 2) { + return ThemeVersionImpl2.getDeviceComponentVersion(component); + } else { + return ThemeVersionImpl3.getDeviceComponentVersion(component); + } + } + + public static List getComponentVersions() { + int version = getVersion(); + if (version == 1) { + throw new UnsupportedOperationException(); + } else if (version == 2) { + return ThemeVersionImpl2.getDeviceComponentVersions(); + } else { + return ThemeVersionImpl3.getDeviceComponentVersions(); + } + } + + public static class ComponentVersion { + protected int id; + protected String name; + protected ThemeComponent component; + protected int minVersion; + protected int currentVersion; + + protected ComponentVersion(int id, ThemeComponent component, int targetVersion) { + this(id, component, component.name(), targetVersion, targetVersion); + } + + protected ComponentVersion(int id, + ThemeComponent component, + String name, + int minVersion, + int targetVersion) { + this.id = id; + this.component = component; + this.name = name; + this.minVersion = minVersion; + this.currentVersion = targetVersion; + } + + public ComponentVersion(ComponentVersion copy) { + this(copy.id, copy.component, copy.name, copy.minVersion, copy.currentVersion); + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public ThemeComponent getComponent() { + return component; + } + + public int getMinVersion() { + return minVersion; + } + + public int getCurrentVersion() { + return currentVersion; + } + } + + private static class ThemeVersionImpl2 { + private static ArrayList cVersions = new ArrayList() { + { + add(new ComponentVersion(0, ThemeComponent.OVERLAY, 2)); + add(new ComponentVersion(1, ThemeComponent.BOOT_ANIM, 1)); + add(new ComponentVersion(2, ThemeComponent.WALLPAPER, 1)); + add(new ComponentVersion(3, ThemeComponent.LOCKSCREEN, 1)); + add(new ComponentVersion(4, ThemeComponent.ICON, 1)); + add(new ComponentVersion(5, ThemeComponent.FONT, 1)); + add(new ComponentVersion(6, ThemeComponent.SOUND, 1)); + } + }; + + public static ComponentVersion getDeviceComponentVersion(ThemeComponent component) { + for(ComponentVersion compVersion : cVersions) { + if (compVersion.component.equals(component)) { + return new ComponentVersion(compVersion); + } + } + return null; + } + + public static List getDeviceComponentVersions() { + ArrayList versions = new ArrayList(); + versions.addAll(cVersions); + return versions; + } + } + + private static class ThemeVersionImpl3 { + public static ComponentVersion getDeviceComponentVersion(ThemeComponent component) { + for(android.content.ThemeVersion.ComponentVersion version : + android.content.ThemeVersion.ComponentVersion.values()) { + ComponentVersion sdkVersionInfo = fwCompVersionToSdkVersion(version); + if (sdkVersionInfo.component.equals(component)) { + return sdkVersionInfo; + } + } + return null; + } + + public static List getDeviceComponentVersions() { + List versions = new ArrayList(); + + for(android.content.ThemeVersion.ComponentVersion version : + android.content.ThemeVersion.ComponentVersion.values()) { + versions.add(fwCompVersionToSdkVersion(version)); + } + + return versions; + } + + public static ComponentVersion fwCompVersionToSdkVersion( + android.content.ThemeVersion.ComponentVersion version) { + // Find the SDK component with the matching id + // If no ID matches then the FW must have a newer component that we don't + // know anything about. We can still return the id and name + ThemeComponent component = ThemeComponent.UNKNOWN; + for(ThemeComponent aComponent : ThemeComponent.values()) { + if (aComponent.id == version.id) { + component = aComponent; + } + } + + int id = version.id; + String name = version.name(); + int minVersion = version.minSupportedVersion; + int targetVersion = version.currentVersion; + + return new ComponentVersion(id, component, name, minVersion, targetVersion); + } + } +}